Sunday, July 31, 2016

Policy Plus - User policy, computer policy

Today I put together a way of handling the user/computer policy split for Policy Plus. There's now a dropdown box above the categories tree that lets you select whether you want user policies, computer policies, or both. There's also a new View menu, which currently contains only a single item, Empty Categories. When that option is unchecked, categories that don't contain any relevant policies (considering the aforementioned dropdown's setting) are hidden. Changes to those viewing options cause Policy Plus to take you up to the nearest level in the tree that's still visible.

The State column now takes into account the current policy set. That gets interesting when you choose to see both user and computer policies. In that case, it will show "(2)" next to the state if both instances have the same state; it will show a "(U)" or a "(C)" next to the state if only one has any setting, and it will just say "Mixed" if the two instances have different settings.

A policy that's only enabled for the computer
I pushed these and yesterday's changes to GitHub.

Saturday, July 30, 2016

Policy Plus - Policy states

One staple of the Group Policy Editor is the State column, which shows whether each policy setting is Enabled, Disabled, or Not Configured. Determining that is surprisingly tricky, since there's nowhere that the actual policy state is stored; it's serialized to and reverse-engineered from normal Registry entries (stored in POL files, not the actual Registry). Today, I wrote a function that gathers evidence from those entries to determine the state of a given policy setting.

I also updated the PolFile class to have a Save method, though it's not used yet.

I would have pushed these changes, but I haven't yet figured out a good way of handling the user/machine policy split. Currently, Policy Plus uses the machine POL file to determine policy state.

Showing the State column

Friday, July 29, 2016

Policy Plus - Open ADMX folder

Policy Plus could already list the contents of a category in the right pane and navigate the category tree using the left pane. Clicking on subcategories in the right pane, however, did nothing, since I haven't added a policy setting editor yet. Today I added a double-click event for categories in that right pane; it opens the category and updates the left tree view control appropriately. I also added a faux-category in the listing of subcategories that takes the user up one level.

I also added function to the existing menu items. Most notably, Open ADMX Folder to easily load policies from the system's PolicyDefinitions folder, the domain's SYSVOL (only available on domains with centralized definitions, of course), and an arbitrary custom path.

The "Open ADMX Folder" dialog

Thursday, July 28, 2016

Banned from Dropbox public linking

Today I published Abiathar 2.8.5 to the update server, which is actually my public Dropbox. Soon after, I found that all my public links had been deactivated with a message about too much traffic. I'm almost certain that's the incorrect reason. Dropbox also issues that message when the public hosting is deactivated because of abuse: malware. I ran a VirusTotal scan on the new files and I found that unlzexe.exe triggers 10 scanners and the newest Abiathar.exe triggers one.

I removed the UNLZEXE program and sent Dropbox a message explaining the situation. Temporarily, I'm using Amazon S3 to host Abiathar and the optional UNLZEXE component. I even bit-twiddled unlzexe.exe so that it won't trigger any hosts' scanners; Abiathar now undoes that twiddling after the download. Hopefully this will be resolved soon.

Wednesday, July 27, 2016

FMod - Online UNLZEXE

For a while, I have been slightly displeased at the fact that UNLZEXE accounts for a full fourth of the Abiathar executable's size. That feature is rarely used, and Abiathar is fairly large, so I really wanted to get rid of it. Today I tried compressing that embedded program, but no LZW bit count would take off enough size to matter, and .NET 4 doesn't support ZIP files (though .NET 4.5 does).

So I just took out that resource entirely. Abiathar will now check to see if UNLZEXE is in the current folder, and if not, it will download the program from the update server. The download doesn't take long at all. This arrangement won't affect AbiatharOS (WinPE, possibly network-less) installations either, because all the Keen executables there are already unpacked.

The Abiathar program is now just 3MB.

Tuesday, July 26, 2016

Quick fix for Device Manager Code 43

I just investigated a Bluetooth issue that I traced back to the Bluetooth controller (which apparently connects internally via USB) not getting registered properly. It appeared in Device Manager with Code 43. I tried uninstalling it and rebooting, but that did nothing - the device just came back with the same error.

Some Googling turned up a Microsoft document that recommended not rebooting after uninstalling the device, but clicking Scan for hardware changes under the Action menu. Interestingly enough, that fixed the problem - Bluetooth devices immediately began working.

Monday, July 25, 2016

PATH surprise: Adds to the DLL search order

The most desired effect of adding a folder to the PATH environment variable is that typing the name of a program in that folder can run it. There is one other, more subtle effect.

The DLL search order specifies where Windows will look for a DLL file when a program loads it only by file name. The last thing searched is the collection of folders on the PATH. Therefore, if a program attempts to load a DLL that's usually absent (e.g. it's an optional module), it might accidentally find it if you have an appropriately named file in a PATH folder. This could lead to security issues if you put a per-user folder on the system PATH.

Fortunately, loading a DLL by file name only is inadvisable, so well-written programs shouldn't do that.

Based on my Super User answer.

Sunday, July 24, 2016

Forcing modified Sysprep configurations

You can customize Sysprep's behavior to some extent by modifying the XML files in this folder:

C:\Windows\System32\Sysprep\ActionFiles

One snag you might hit after doing that is that Sysprep could fail to "validate your Windows installation" even after you deal with Candy Crush. Somehow, Sysprep detects that it's been tampered with and disables itself. You can undo that by tweaking a Registry setting. Navigate to this key:

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup\Sysprep

If there's a SysprepCorrupt value set to 1, change its data to 0. Assuming everything else about your Windows installation is good, that should let you run Sysprep.

Saturday, July 23, 2016

PowerShell remoting

If you've ever needed to run a command on a remote computer, you've probably used PsExec. I've done that, but I've found something better that comes with Windows: PowerShell's remoting capabilities. Once the firewall is configured to allow remote management, you can use Invoke-Command to run a script block at a remote machine and get the output as a PowerShell object.

Invoke-Command -ComputerName 'example' {gci C:\}

Invoke-Command {type $file} -ComputerName $hostname -Credential (New-Object PSCredential -ArgumentList 'username', (ConvertTo-SecureString 'password' -AsPlainText -Force))

Friday, July 22, 2016

Removing digital signatures from a file

It may be useful to remove digital signatures from a file, e.g. if you've tweaked it with a hex editor and want to run it elevated. Visual Studio and the Windows SDK include a tool for managing the signatures in files: signtool.exe. If you open the Developer Command Prompt, it'll be on your PATH. Otherwise, you can search for it in the Windows Kits folder under the 32-bit Program Files folder. For me, it's at this path:

C:\Program Files (x86)\Windows Kits\10\bin\x86\signtool.exe

Anyway, once you find it, run this:

signtool remove /c C:\path\to\target.exe

It looks like the "remove" feature wasn't always there, so you might need to get the newest Visual Studio if yours doesn't include that ability.

Thursday, July 21, 2016

If phpBB3 is broken, try disabling text formatting features

I continued tinkering with my phpBB3 installation today, and I discovered upon trying to create a subforum that some text features are broken. When I clicked the button to submit my new subforum, I got an error spew telling me that the /e flag of preg_replace is deprecated, which it is. Apparently, the BBCode and smilies parser hasn't been updated yet. So I just turned both of those things off for the whole forum, and that let me create my subforum.

Then I went to create a test post, and no matter what I did, it failed with a message that I hadn't typed enough characters. A warning at the top of the page informed me that I was running into the same problem. Checking the box that disables automatic URL linkifying let me post, but I couldn't find a way to disable that automatically for everyone. So I whacked posting.php to always pretend that check box is set appropriately. And now I have a working forum.

Wednesday, July 20, 2016

I set up phpBB3 on Ubuntu Server

I agreed to put together a quick web forum for a group in which I participate, and I figured that phpBB3 would be a safe choice. Since PHP is (in my understanding) usually run on Linux platforms, I decided to try Ubuntu again, despite my previous problems with it. This time, though, I went with Ubuntu Server. I'll note that Ubuntu Server doesn't have a GUI (by default), so everything I did was from the command line.

Starting fresh, I grabbed the official Ubuntu Server 16 ISO from the official web site and put it in a Generation 1 Hyper-V machine with 512 MB of RAM. Setup went smoothly; the pseudo-GUI guided me through the whole process. It gave me a list of optional features to install, and since I was going to need a web stack, I chose to add LAMP. When the system came online, I updated all the things that wanted it. To set a static IP, I used nano to adjust some config file somewhere, and then I just rebooted. Nano is a very easy-to-use text editor, though I couldn't figure out how to select anything for copy/pasting.

Installing phpBB3 was as simple as sudo apt-get install phpbb3. It asked me for some configuration, I provided it, and it installed. I then deviated slightly from the instructions to make phpBB accessible from the root of my website rather than a subdirectory, and then everything went south. Neither the intended path nor the root path worked from a web browser, and browsing to things that should have been there produced permission errors. I did manage to bump into a phpBB component, but it threw an error about not having mysql_connect. I tried various things, but probably only broke it more.

So I uninstalled and reinstalled phpBB3. That might have been a little much, since I think I had only messed up its registration with Apache. I followed the instructions to the letter this time, but still got the MySQL error. Some Googling determined that the function it's trying to use is so deprecated as to be completely gone. I had to hunt down yet another textual configuration file and set the database provider to a more modern one. That worked, and I got to use a web browser to configure phpBB as I wanted.

When I tried to register a new user, though, I got a 500 server error. When I finally found a relevant log file with useful errors (which was difficult given my lack of Linux command line experience), I saw that there was a PHP syntax issue in the captcha module. Since I'll be manually approving new members anyway, I just disabled anti-spam features in the phpBB web controls, and that fixed the problem.

And with that, I had a working phpBB forum. (Well, I jumped through some hoops splitting a PFX certificate into CER and KEY and getting Apache to serve my site using it, a procedure which also happened to remove the extra subdirectory in web paths. Hooray!) All in all, I was moderately inconvenienced in that I had to finagle stuff to work around phpBB problems, but at least this episode of Linux adventuring ended well.

Tuesday, July 19, 2016

When MDT asks for a deployment share path or credentials

Today I ran a few deployments from an MDT setup I had finished some weeks back. On a couple of those in a certain location in the building, MDT produced a window at startup asking for a path to a deployment share, and after I entered it, credentials to connect, which it then didn't accept. (I had set all of that in the various configuration places, and those settings had worked on many machines.)

A little research from investigating previous problems indicated that sometimes MDT doesn't wait long enough for the network. Since I didn't want to fiddle around with the VBS scripts, I did my best to work in the already-booted MDT setup environment. I finally discovered that when this problem occurs (or when MDT hangs/vanishes), running this command in a command prompt - press F8 - helps:

bddrun /bootstrap

That just starts the MDT process fresh while keeping any network connections. The old process stays around, but will be ended when the system reboots. bddrun is in System32, so you'll need to cd there if you start anywhere else.

Monday, July 18, 2016

Policy Plus - UI time

For a while, Policy Plus has contained classes that load policy definition files. That is sufficient to put together a semi-functional UI, so I did exactly that today. So far, I have a left pane for the categories tree, a middle pane for info on the selected setting, and a right pane for the list of policy settings, just like the real Group Policy Editor.

I haven't yet decided how to handle the split between user settings and machine settings. I'm not entirely satisfied with the GPE's style of splitting them into completely different subtrees, but I'm not sure what would be both better and simple to implement. At the moment, I only display one tree, and since there isn't yet a way to actually configure the settings, that's very easy.

Looking at a policy setting
The icons next to categories and policies have special meanings. On the left, categories with exclamation marks on them are orphans in their ADMX files (i.e. they have a parent set but that parent doesn't exist). Categories with a minus sign (not shown in screenshot) are completely empty. The category on the left with a right arrow on the folder is the currently-selected on. Policy settings with a gear on the page icon require extra configuration, while those without the gear can only be Enabled or Disabled.

Sunday, July 17, 2016

FMod - Extension interaction

In addition to last week's changes to Abiathar's standard tools, I have also been making some small expansions to allow for interaction between extensions. First, though, I added a field to the extension metadata class to let extensions declare a long description for use in the extension information dialog separate from the short description that appears in crash reports.

I also added to that class a field for a delegate to return information ("measurements") that the extension exposes. No extensions currently support anything like that - since it's new - but it could be helpful if people use it. There's a new function on IAbiatharState that retrieves the extension object corresponding to an extension's name, or null of that extension is not present.

These features will be helpful in developing an extension that I have an idea for.

Tuesday, July 12, 2016

FMod - Convenient tileinfo animation links

Quite a while ago, I started adjusting Abiathar's standard tools to respect the number format settings. I finished that today.

Along the way, I also fixed a design flaw in the Tile Instance Remapper that caused custom regions with one point at (0, 0) to not actually get set. The fix mostly involved marking a variable as nullable and then sprinkling HasValue checks around rather than using comparisons to null (which is the same as the default value for a value type).

"Gridlock" on IRC suggested a while back that the Tile Property Modifier allow the user to right-click a tile to animation-link the active one to it. There's already an animation link mode, but it's only mentioned in the contextual help, and using it requires an extra keystroke. Other tileinfo tools all use right-clicking to set the animation target. So I implemented that, with the additional option that holding Shift while right-clicking only makes the animation link, without moving the focus to the target tile.

Monday, July 11, 2016

Policy Plus - Save CMTX files

I had previously created a CmtxFile class for Policy Plus that can load CMTX files and present their comments in an easy-to-use dictionary. Since comment files are designed to be updated, I also need a way to write CMTX files.

So that's what I did today. CmtxFile can now create an instance of itself from a simple dictionary and then save itself to disk. It turns out that the Group Policy Editor is very particular about all the attributes being there. It also doesn't like periods in resource IDs or prefixes. I had to do a little extra legwork to deal with those, but it is working very well now. I intentionally didn't follow the incremental ns convention because I want it to be relatively easy to see what policy namespace a comment refers to, even when viewing the CMTX in a hex or text editor.

Oh, and I figured out the meaning of the three-byte header. It's just the UTF-8 byte order mark, and XmlDocument can handle it automatically. (I knew about byte-order marks, I just didn't recognize the UTF-8 one.)

Sunday, July 10, 2016

Policy Plus - WillDeleteValue considerations

The list policy element has an additive attribute that determines whether the existing contents of the key will be blown away before the new entries are added. Therefore, there's a **delvalues entry in the POL file in addition to the entries, and the order of those entries matters. The PolFile.WillDeleteValue method assumes that all values under a key will be gone if there's a key-clearing entry, but that's not true in the presence of one of these lists.

So today, I adjusted that function to take into account the order of entries. It now iterates through them, updating a "will this value be here" Boolean, then returns the final value.

Then again, this probably wouldn't have mattered, since I think all ADMX files check values outside the list key for the enabled/disabled state. Oh well, you never know when some horrible edge case will come up.

Saturday, July 9, 2016

Policy Plus - Registry policy proxy

Today I filled out the IPolicySource implementation for RegistryPolicyProxy, which turned out to be a lot simpler than the one for PolFile. Every operation could be forwarded directly to the real Registry with a minimum of extra processing.

Before doing that, I adjusted the POL file source to support QWord entries, but then I realized that policy settings only affect string values and DWord values, so then I didn't bother adding special support for the other kinds.

I also added a new function to that interface that gets the list of value names under a specific key because that operation is necessary for dealing with list policy elements. Since most of the format-related infrastructure is done now, I'll soon be able to start building an application.

Friday, July 8, 2016

Windows Server Surprise: Sleep enabled

Today I set up a new Windows Server 2012 R2 installation. I then went home, planning to continue managing it via VPN. When I connected to the network, though, I couldn't reach the server. It responded to ARP queries, but couldn't be pinged or connected to in any way. I concluded that it had gone to sleep, and that the network card had ARP offload enabled. I tried Wake-on-LAN, but it evidently was not enabled.

So, I guess Windows Server can go into power-saving modes by default. That seems like an unusual choice, considering that servers are expected to continue serving requests in the absence of a user at the console.

Thursday, July 7, 2016

Policy Plus - POL files

I want Policy Plus to be able to read policy settings from normal POL files, straight from the Registry, or both at once, so I need to have a common interface of some kind. Today I put together and partially implemented IPolicySource. It currently has two implementing classes: PolFile, which is mostly done, and RegistryPolicyProxy, which is all stubs at the moment.

PolFile can load POL files and determine whether a Registry value exists, including figuring out whether a value will be deleted by any of the several deletion commands. Since the Registry is case-insensitive, it lower-cases everything, but it also keeps track of the first original casing used for each path so that it can (eventually) write the values in their original style. That's so that people see pretty names if they open their Registry.

You can see the current code on GitHub.

Wednesday, July 6, 2016

ntuser.pol: How Windows knows which Registry settings are from policies

The Policies subkey under HKLM or HKCU in the Registry is automatically updated when Group Policy is updated (either on the domain or on the local machine). It's also possible to add entries directly to those Registry locations. Settings added in that way won't show up in the Local Group Policy Editor, but they won't be removed in the next policy refresh. I found several mentions of Group Policy cache files, but they don't exist at all on non-domain-joined Pro machines.

Windows can't just rely on delete-value commands in Disabled policies because changing a set policy to Not Configured needs to remove the values too. To figure out how Windows knew to keep around manually-entered values, I used Process Monitor. Evidently, the Group Policy updating service compiles all applicable GPOs into one POL file called ntuser.pol. That file is stored in \ProgramData for the machine settings and in the root of each user's folder for user settings. Whenever Group Policy is updated, the service compares the new settings against that file, then removes all Registry items that were set by policy but don't appear in the new version. Once the new settings are written, it rewrites ntuser.pol.

Tuesday, July 5, 2016

Policy Plus - Comment files

The Group Policy Editor lets you attach comments to policies. Those comments are stored in a file called comment.cmtx alongside the POL file. The CMTX format does not appear to be documented anywhere. Fortunately, it's fairly similar to the ADMX format. It's an XML file (with three unknown bytes tacked onto the beginning). It has a string table for some reason that I don't understand - it's stored in the same file as the policy list, obliterating the possibility of doing an ADML-style separation of objects and texts. There's also an ADMX-like prefix table, though CMTX files don't target any namespace.

The code to load CMTX files and produce a policy-to-text mapping is available on GitHub.

Monday, July 4, 2016

What are those \??\ (backslash double question mark backslash) paths in Windows?

In certain places within Windows (usually the Registry), you'll see paths that begin with double question marks between backslashes, \??\. These are NT Object Manager object names. The Object Manager is a kernel-mode system that organizes various objects into a tree-like hierarchy. In other places, you may have seen path-like things that start with \Device\. Those are also Object Manager paths, and everything in the \??\ folder is actually a symbolic link to other places in the hierarchy. \??\C: links to the HarddiskVolumeN object for the volume holding your C drive, where N is a number. Only certain parts of Windows are designed to accept Object Manager paths, so you can't use them anywhere you would a normal path.

You can explore this hierarchy with the WinObj tool from Sysinternals.

Note that these paths are completely different than \\?\ paths, which are literal extended-length paths that you can use to access or create file system objects with weird characters in the name.

Based on my Super User answer.

Sunday, July 3, 2016

Policy Plus - Object-orient all the things

Today I filled out the rest of Policy Plus's AdmxBundle.BuildStructures method. It now compiles all the raw ADMX structures into object-oriented classes with hierarchies and relationships. That includes categories, products, policies, and supported-on definitions.

While testing it, I discovered that a Windows ADMX file - PreviousVersions.admx - tries to reference a product from an ADMX file it hasn't imported, so I had to add some handling of that case to the ResolveRef function. If the source ADMX doesn't import a namespace it references, Policy Plus doesn't bother expanding the ref, which will probably always cause the target to not be found, so the supported-on entry that tried to refer to it will just not be added to the support definition.

Other than that, it worked perfectly. I can use Visual Studio's object inspector to look through the ADMX bundle to see the tree of categories and policies.


Saturday, July 2, 2016

Office 2016 is apparently stable now

More than a year ago (wow), I tried a preview version of Office 2016. It did not go well. It did work on Windows 10, though, and I tried it a little in a VM. A few days ago on my Windows 8.1 main machine, Office 2013 asked me to update to the newest version of Office. I hesitantly accepted. It downloaded and installed the new programs successfully.

The only hiccup I ran into during setup was that the first post-upgrade run of each application put up the normal "didn't start correctly last time" dialog, but that went away on later runs. The only application I've been using heavily since the upgrade is Word, and it seems to be working fine. Evidently, Microsoft worked out the kinks.

Interestingly enough, PowerPoint always wants to run as administrator now. That's not happening with any other Office program. It still works fine once I elevate it, though.

Friday, July 1, 2016

Policy Plus - Late loading

Yesterday, I wrote a little bit of code for Policy Plus that assembled the AdmxCategory structures into the more object-oriented PolicyPlusCategory structures. My implementation had a problem, though. If a new ADMX file was added after the call to LoadFolder, RawCategories would be empty and it wouldn't be able to resolve references to categories defined in ADMX files that were loaded earlier. So, I added a temporary dictionary and a function that searches both that and the existing categories. There's actually still a flaw in my most recent commit - the Categories dictionary doesn't contain child elements, so late-loaded categories can only reference existing top-level categories. That's fixed, but I have more changes I want to make (getting the other kinds of resources object-ified) before I push a new commit.