Saturday, October 31, 2015

Uninstaller Shortcuts in the Windows 8 Age

Back when Windows XP was the newest Microsoft consumer OS, it was common practice for program installers to create folders in the Start menu "All Programs" list. Each such program's folder contained a shortcut to the program itself, and sometimes a help file or uninstaller.

Nowadays, with the Start menu flattened by Windows 8's Start screen (and, to some extent, the incremental search of Windows 7 and 10's Start text box), I frequently see uninstaller shortcuts come up. It doesn't make sense to me that a particular uninstaller should be readily accessible - it's not like I'm going to remove a program on a daily basis. It's even worse when the shortcut is just called "Uninstall" with no indication as to what program owns it.

I think it's time we stop placing shortcuts to uninstallers. Windows XP and its rigid Start hierarchies are long gone.

Friday, October 30, 2015

Translating Any Principal Name to a SID in .NET

Windows security identifiers (SIDs) are represented in .NET by the SecurityIdentifier class in the System.Security.Principal namespace. .NET provides intuitively apparent ways of getting the SID of a real account (Sid on the UserPrincipal class) or of a well-known account like System (use the SecurityIdentifier constructor that takes a WellKnownSidType). Neither of those methods, however, work for more esoteric principals like TrustedInstaller or for arbitrary user input.

A convenient way to get the SID that represents the account named by a string is to create a new NTAccount object. Then call Translate on that object, passing the Type object for SecurityIdentifier (which you can get in VB.NET with a GetType expression). That produces a real SecurityIdentifier instance that can be used wherever you need to identify a principal.

Thursday, October 29, 2015

Programmatically Creating Group Policy Shortcuts

.NET has official, documented, managed APIs for modifying registry-based Group Policy, but there are no such facilities for non-registry-based preferences like shortcuts. Some poking around in a shortcut-having policy object's folder in SYSVOL reveals that shortcuts are stored in an XML file called Shortcuts.xml in a folder called Shortcuts under Preferences in the GPO's folder. That format is easy to figure out, but I found that creating that structure manually had no effect. Strangely, the Group Policy Editor showed the shortcuts that I created, but neither the reporting module nor client computers paid it attention until I opened the shortcut properties in the GPE and saved it.

I concluded that there must be some other bookkeeping responsible for enabling types of preferences. There is indeed - I discovered that the Active Directory representation of Group Policy Objects includes two fields called gPCMachineExtensionNames and gPCUserExtensionNames. Those objects are found in the Policies container under System in the main directory partition, though it won't appear in Active Directory Users and Computers unless you enable advanced mode. Each field is a list of pairs of GUIDs, representing Group Policy client extensions. It looks like [{GUID}{GUID}][{GUID}{GUID}], where each bracket-enclosed GUID pair is one extension, and the exact number of entries depends on which preferences are present..

To enable the processing of shortcuts, prepend

[{00000000-0000-0000-0000-000000000000}{CEFFA6E2-E3BD-421B-852C-6F6A79A59BC1}]

and append

[{C418DD9D-0D14-4EFB-8FBF-CFE535C8FAC7}{CEFFA6E2-E3BD-421B-852C-6F6A79A59BC1}]

to the appropriate property on the policy object. You can discover the GUIDs of other extensions by creating a GPO with only administrative template policies, observing the field value, adding an entry of the desired type, and seeing what got added to the field.

The best way to fiddle with Active Directory directly in .NET is to use the DirectoryEntry class from System.DirectoryServices. Make sure to call CommitChanges on DirectoryEntry after you've changed the values.

Tuesday, October 27, 2015

PowerShell Bitwise Operators

PowerShell, the fancy new-ish alternative to ye olde command prompt, does have bitwise operators, though they're a little bit difficult to guess. They're handy when using .NET methods that take flags enums as parameters. Named operators start with a hyphen and go between their operands as you would expect. All the bitwise operators are prefixed with "b", so for example "-band" is bitwise and; "-bxor" is bitwise exclusive-or. 8 -bxor 9 produces 1.

Monday, October 26, 2015

Machines Can Be Admins Too

An interesting thing about Windows account management and Active Directory is that machine accounts can do everything a user account can, like be a member of a group. That membership then applies to that computer's SYSTEM account's actions on the network. If a machine account is added to the Domain Admins group, processes running as SYSTEM on that machine will have complete access to the domain. However, that access only comes into play at the next boot; existing processes use a token that does not include newly added group memberships.

Sunday, October 25, 2015

Accessing the Real System32 From 32-bit Programs

On 64-bit editions of Windows, 32-bit programs that attempt to read from or write to System32 will actually perform their operations on SysWOW64, which is also in the Windows directory. That can be a problem if you want to do something with the real System32 files from a 32-bit program, especially without the source code of that program. (Programs can opt out of the redirection by calling the Wow64DisableWow64FsRedirection function.)

For example, I recently wanted to inspect the contents of the Local Group Policy files with a hex editor, which happened to be a 32-bit application. Those files are under System32 and have no useful counterpart in SysWOW64.

The solution is to use a special pseudo-folder called Sysnative instead of System32. \Windows\Sysnative is accessible for 32-bit applications (though you won't see it in a directory listing), but is not at all navigable by or visible to 64-bit applications. Its contents are the real contents of System32, and any files under it are the authoritative versions.

Friday, October 23, 2015

Modifying Group Policy with .NET

There is precious little information on programmatic access to Group Policy, and many people say automatic configuration of Group Policy settings can't be done, but it totally can if you put in a little effort.

First, you'll need the Group Policy Management Console class library, which comes with the Group Policy Management Console in Remote Server Administration Tools. Connect to a domain controller by creating a new GPDomain object. Create a new GPO by calling CreateGpo on your GPDomain. To actually get at the policy settings, you'll need to get a ComputerConfiguration object from the Computer property on Gpo, a PolicySettings object from the Policy property on ComputerConfiguration, and a RegistryPolicy object from the GetRegistry function on PolicySettings (not in read-only mode). To get the user policies, use the User property on Gpo instead of Computer.

The methods on RegistryPolicy that start with "Write" allow you to create registry entries that the policy will enforce. When you're finished writing policies, call Save on the RegistryPolicy object with the parameter True if you're updating the computer policy or False if you're updating the user policy. To figure out what entries do what, you'll need the help of policy definitions (ADMX files).

These can be read with ADMX Migrator, and are found in the \Windows\PolicyDefinitions folder on every machine. (The authoritative copy should be on SYSVOL in a domain, but local copies work too.) In ADMX Migrator, right-click "ADMX Templates" in the left pane and choose "Load Template" to open an ADMX file. Browse around the folders until you find the setting you're looking for, and then note the registry key and value that the setting affects. To see what data you should write, check the Values tab. For settings that have extra configuration (beyond Enabled/Disabled), check the Presentation and Value Lists tab.

Microsoft set up a Group Policy search web site/database thing that lets you get the same info, but as of this writing it has some weird behavior with settings that have extra configuration. It does, interestingly, tell you which ADMX file is responsible for each setting, so that could help you even if the value name isn't quite right.

To link (i.e. actually make it have an effect) the GPO to the domain or to an OU, first call GetSom on your GPDomain. GetSom takes the LDAP-style fully-qualified name of the Scope of Management; the DirectoryServices namespace might help you find available SOMs. Call LinkGpo on your Som with the Gpo object and the position at which to insert it; a constant 1 works. The resulting GpoLink object allows you to change the enforcement and enabledness of the GPO. Once that's done, your GPO is linked and in action.

Thursday, October 22, 2015

Registry Policy (.POL) Format

Microsoft published the format of the registry policy (Local Group Policy or backed-up Group Policy) files, but their document is not at all specific about the byte-level arrangement of the information. I did some tinkering with the .POL files and figured out everything I need to know.

A .POL file starts with the four-byte integer 0x67655250, which is the string "PReg". The file's version follows as a four-byte little-endian integer. The main body of the file consists of records for registry values to update. All text in the body appears to be UTF-16LE, so when it's storing only ASCII, there's a null byte after each character.

At the beginning of a record, there is an open bracket "[" (yes, the punctuation in the MSDN document is literal) and a null byte after it. The path to the key (folder as seen in Registry Editor) follows, also as UTF-16LE, and is terminated by a null character (two null bytes after the last real character). There is then a literal semicolon character, including the null, and the name of the value (name of the entry as seen in Registry Editor). Some values are special, and I don't understand them fully; see the Microsoft document.

After another semicolon character, the data type appears as a four-byte little-endian integer. Common values are 1 (string), 2 (expand string), 4 (four-byte little-endian integer), and 11 (QWORD, LE). The full list appears at line 4884 in this copy of WinNT.h.

The next semicolon-delimited field is the size of the data, which is again a four-byte little-endian integer, and appears all the time, even for types whose data are always a constant size. Finally, after another semicolon character, the data appears. Numeric types are represented in binary; string types always are in UTF-16LE and null-terminated. The record is finished off with a "]" character. No null appears between the ending bracket of one record and the opening bracket of the next.

Wednesday, October 21, 2015

.NET DirectorySecurity Oddities

It's great that .NET has managed APIs for file and directory ACLs, but DirectorySecurity seems to be a little rickety. In particular, I've found that setting the ACL on a directory sometimes does nothing if the directory is hidden. Also, the SetAccessControl instance method on DirectoryInfo has been less reliable in my experience than the SetAccessControl static method on Directory. When I take care to avoid those pitfalls, DirectorySecurity works well.

Tuesday, October 20, 2015

Adobe Acrobat Unattended Install Difficulties

I am attempting to do an unattended deployment of Adobe Acrobat (not Adobe Reader) via msiexec, and I am having a lot of trouble. The installer process sometimes exits with code 1603, which is a generic installation failure. On some machines, the installation works fine after a couple tries, but on others, it never works no matter how much I reboot or retry.

I did recently dig up an Adobe KB article that seems relevant, but it's for an older version (not DC), though a more recent document indicates that the parameter is still useful. I will try the MSI parameters and the registry tweak to see if they help.

Sunday, October 18, 2015

WCF Surprise: Renamed Machines Temporarily Use Old SAM Name

Recently, I was messing around with WCF's impersonation/identification feature on machine accounts, i.e. with WCF clients running as SYSTEM on their respective machines. Meanwhile, I noticed that a machine had a wrong name; I must have forgotten to change the WDS naming scheme before deploying to it. So I changed the name and rebooted as suggested. When the machine came back up, I was surprised to learn that it was still identifying to other machines with its old name.

The server checks the client computer's name by reading ServiceSecurityContext.Current.WindowsIdentity.Name, which produces the name in NetBIOS form, DOMAIN\MACHINE$. Puzzled, I checked the Active Directory record for the machine, and all relevant attributes had been updated to reflect the change. The computer itself displayed the new name in system properties. The WCF server application had been restarted (for other reasons) since the change. Therefore, I have no idea why it was seeing the old name.

If you know what's going on, feel free to leave a comment or answer my Server Fault question.

Saturday, October 17, 2015

Simple, Effective Copy Protection with Asymmetric-Key Cryptography

Copy protection can be a hard problem, and in the end there's really no way for copyright holders to win. Then again, locks are for honest people, so there is a benefit to licensing checks as long as they are simple to implement and don't cause pain for legitimate users.

Asymmetric-key cryptography can be used to build a simple yet reasonably strong method of licensing enforcement. It can't do much if your users are willing and able to whack the executable to remove the checks, but not many manageable systems can. What it can do very well is make sure that a license key is present and produced by a trusted agent. This is how it works:

  • An asymmetric key pair is generated. The public half is burned into the distributed application, and the private half is kept secret with the licensing agents.
  • When a copy is bought, some identifying information about the legal owner is recorded, hashed, and signed with the private key. The resulting file is the license key, and is sent to the owner.
  • When the application starts, it gathers all that identifying information, hashes it, and checks it by decrypting the signed version in the license file with the public key.
Note that this does require a persistent, unique piece of data to identify an owner, so it works better for server applications (especially ones bound to a domain) than end-user applications.

Friday, October 16, 2015

Windows 8 Won't Pin Control Panel Items to Start

I check Windows Update semi-frequently, especially after I install a new device or a large Microsoft program. Windows 8 makes it a bit inconvenient to get to the desktop Windows Update - typing "windows" at the Start screen never makes it bring Windows Update to the top of the list even though "windows update" is the only thing I ever type there that starts with "windows". At least it eventually learns that I prefer the desktop version to the "Check for updates" Metro settings option.

Anyway, I went to pin Windows Update to the Start screen (I had just decided to use the screen for its intended purpose - as a dashboard - and make a "Management" section), but I found that Windows will not allow me to pin a Control Panel entry, even the desktop ones that are basically applications in their own right, to the Start menu. In fact, right-clicking on them in the search results list does nothing at all. Metro settings and files also don't make the pinnability cut, but folders do. Huh.

Thursday, October 15, 2015

Robotics - Meet the Sponsors

Today, both robotics teams gave a presentation to a panel of community engineers selected by the coach. The presentations were about the teams' status, plan, and mission. Personally, I think it's a bit early in the season for this type of meeting, though corporate-style state-of-the-project meetings do have value. Nevertheless, each team discussed the parts of the robot that were together and touched on team workings, introducing each member.

A tiny amount of actual work was done after the presentations, and I learned that the veteran team has started programming with Android Studio. Both teams still have a long way to go; neither robot moves, neither has any useful appendages, and only one has wheels.

I'm not actually sure whether the engineers from the community are potential mentors or sponsors, but they're apparently important - there were cheesecake bites at the meeting.

Monday, October 12, 2015

Fixing Unbootable 15-Series HP Notebooks with Caps Lock Steady Blink

Yesterday I participated in the repair of an HP 15-R110dx notebook computer that refused to boot or do anything at all. When powered on, its Caps Lock key light blinked once every three or four seconds; the pattern wasn't described in any HP documentation that I could find.

It turns out that the CMOS state was corrupt or unusable in some way, so the CMOS battery needed a disconnect/reconnect cycle. Actually performing the repair was exceptionally difficult because the RAM and CMOS battery are under a host of important and inconvenient-to-remove parts, and not accessible from the bottom.

The general procedure to fix this problem is:
  1. Remove the main battery and disconnect the power cable
  2. Remove RAM and CMOS battery
  3. Press the power button (discharges any extra energy)
  4. Reinsert RAM and CMOS battery
  5. Connect power cable and/or main battery
  6. Reboot when prompted about CMOS corruption
Step 2 is written here as five simple words, but it is a challenge, as is reassembly. Disassembly goes like this:
  1. Remove all screws from bottom panel
  2. Remove the DVD drive
  3. Remove the screws hidden under the DVD drive slot
  4. Remove the screws hidden under the back two rubber feet
  5. Pry the keyboard out and disconnect its cable
  6. Pry the larger surrounding plastic piece off
    • Be careful to remove the keyboard separately or you risk tearing the power button cable. (Guess who did that. Twice.)
  7. Unscrew the metal plate and remove it
  8. Unscrew the motherboard and tip it up toward the screen
    • Screws for the motherboard are marked with white arrows.
  9. Remove the RAM and CMOS battery on the underside of the motherboard.
    • Yes, the RAM is on the underside of the motherboard, under all that other stuff. That is just appalling.
If you damaged the power cable in substep 6, you'll need to short across it when applying power for step 3. Fortunately, it's possible to solder it back together.

RubberWilbur's video guide to RAM replacement for these models was very helpful for the disassembly operation. For putting it back together, assembly is the reverse of disassembly.

Once everything is back together and powered, BIOS should come up with a message about CMOS corruption and a directive to press Enter. Press Enter (or just reboot) - CMOS will be reset and all will be good.

Sunday, October 11, 2015

Pasting YouTube Tag Lists

While drafting a post in which I complained about being unable to usefully paste into the YouTube tag list for a video, I noticed that the feature I wanted is already there, just not easily discoverable. Though it does not seem possible to get anything useful by copying from the tag list, YouTube will split a tag list into individual tags if you delimit the tags by commas, not semicolons or spaces or anything else. Therefore, you can prepare a list of tags and easily paste it into each video in a series without having to retype it every time.

Saturday, October 10, 2015

Power Cables and Data Cables from Different Computers

Today I needed to get some data off of an unbootable hard drive that was in a mount in a machine. Since I did not have a special screwdriver and the mount looked very difficult to work with, I decided I would just leave the drive where it was and connect cables from the real machine to it. The problem with that idea was that all the SATA power cables in the real machine were super short and could not reach.

So I carefully positioned the two machines so that the data cable would reach the hard drive from the bootable machine and connected a power cable from the unbootable machine to the drive. I powered on the unbootable machine first (I'm sure it got stuck in BIOS or something, no monitor was on it), then the bootable machine. The contraption worked - the drive was accessible and stayed online as long as I kept the old machine on.

This is also a good trick for situations where a motherboard is out of power cable slots.

Friday, October 9, 2015

Abiathar Confidential - Security & Privacy

I have written these things before, but I thought it would be good to put them all together in one place for easy reference.

Abiathar operates almost completely offline. It works perfectly fine without an Internet connection, but when the Internet is accessible, Abiathar updates itself. That may raise some concerns about the security and privacy of the whole system.

Abiathar uses the network for only three operations: automatic self-update, VeriMaps verification and temporary logo display. On startup, it checks my public Dropbox to see if there is a new version available. If so, a prompt is displayed asking for confirmation. If the user accepts the update, the updater application downloads a script from my Dropbox that can perform only three types of operations: download a file, delete an existing file, and mark a downloaded file to be executed after other operations complete. The entire checking and download processes are done over TLS.

There is the possibility of a critical update, a situation in which I have deemed an update so necessary that Abiathar should not be used at all until the update is installed. This mechanism has never been used, and probably won't ever be - it's for updates that fix earth-shattering, data-destroying bugs. Even if this flag is set on an update, the user still has the option of canceling the update, though the prompt appears in the console window of the temporary updater program instead of the Windows Forms UI of Abiathar proper.

The VeriMaps verifier is used when a maps file that claims to be VeriMaps-signed is opened. The matching public certificate is retrieved from my Dropbox (again over a TLS connection) and used to verify the file's authenticity.

The final type of network usage is purely cosmetic: temporary changes of the big background image in the main form. On startup, a download of a file at a certain path in my Dropbox is attempted. If it succeeds, the resulting image replaces the standard blue-text logo. The downloaded image is not persisted at all on the client, and it is redownloaded for every launch as long as it exists. I have set a temporary logo only once, on Independence Day, as a test of the system.

No user data is ever sent out by Abiathar.

Thursday, October 8, 2015

Centering Objects on Other Objects

There are several programs in which I frequently find myself wanting to align some object to the center (either horizontal or vertical) of another object. Unfortunately, I rarely see that feature. Visual Studio has Format | Align | Centers (or Middles), but there does not appear to be such an option in Adobe Flash Pro (the IDE/designer, not the player). That's a shame, because a lot of the arrangements I would like to produce require perfect centering of objects on other objects.

There might be such an option in Flash, but I am not seeing it and Googling has not helped me yet.

Tuesday, October 6, 2015

.NET Monitor Locks are Re-Entrant

The purpose of the Monitor class in .NET (used by "SyncLock" in VB.NET and "lock" in C#) is to prevent different threads from entering a critical section at the same time. Care must be taken by the programmer to ensure that deadlocks - situations in which threads are waiting for each other directly or indirectly - are impossible. I recently needed to write a recursive function that happened to require careful threading, so I was concerned that the second invocation would hang waiting for the first to finish.

Fortunately, Monitor locks are re-entrant. If a section is entered for a given lock object on the same thread (e.g. in a recursive situation), the section will not be released until a matching amount of Exit calls are made. [Source: MSDN's article on Monitor.Enter]

Sunday, October 4, 2015

Power Failures Happen

Today while attempting to switch off my monitors, I accidentally hit the toggle button for my computer's power, immediately turning it off. Whoops. That's alright, NTFS is designed to be resilient in the face of power loss, so I turned my computer back on. After BIOS did its thing, Windows 8.1 ran some sort of "automatic repair" on my computer and attempted some operation. (Before asking me, and without telling me what it was!)

Automatic Repair couldn't fix the "problem", and so it dumped me into the repair mode UI. Since I was fairly certain that nothing was wrong with the machine, I chose the Continue (try to boot normally) option, which is under the advanced tools menu for some reason. After sitting at a black screen with high disk utilization for a few minutes, Windows came up as normal with only the expected event 51 entries in the Event Log.

So all that was a really long-winded way of saying that everything was fine.

I really wish more programmers would account for the fact that power failures can happen at any time, and that it shouldn't be an earth-shattering catastrophe if the program or machine doesn't go down gracefully. I understand that there are certain critical operations that cannot be continued if power is lost in the middle, but surely an attempt can be made to continue with whatever state was saved to disk before panicking and displaying scary messages to the user.

Saturday, October 3, 2015

Keep My Place in Disconnected Network Folder Structures

I frequently have to browse the directory trees of remote machines, and since mapping a network drive for each place would create a big mess (there are lots of places I need to look at), I have to use double-backslash UNC paths to get where I want. That works great, and I do my work until I need to go somewhere else. I then close my laptop - disconnecting it from the network - and carry it with me. When I reopen it, all the Explorer windows browsing network folders are showing me the Network screen (the list of computers on the domain).

That's rather inconvenient, because there is no indication of what I was doing with that window. It would be really nice if Explorer instead grayed everything and put up a "remote session disconnected" panel that could be clicked to attempt a new connection.

Thursday, October 1, 2015

Keeping Windows Forms Controls Centered

Windows Forms designers may find it necessary to keep a control centered in its container but not stretched if the container expands (e.g. if the user maximizes the window). The way to accomplish this is actually quite simple, and requires no math whatsoever. Simply setting the Anchor property to nothing along a certain axis results in the control staying perfectly centered without any change in size. Setting that property to Bottom only, for example, keeps the control's bottom edge stuck relative to the bottom of the container but allows it to slide horizontally to remain centered.