07 January 2009

Adventures in Windows - Subinacl, Cscript and how I wasted an evening

My wife's desktop machine died a couple of days ago, and now Windows won't boot for some reason. After a few unsuccessful attempts at reviving it, I decided that it would be better to simply move her stuff to a spare machine we had laying around (which actually has better specs, but I digress).

So I duly connected the old disk to the new machine, and tried to copy across a few files. Windows said "Access is denied". Apparently, the account names between old and new machine where different, so Windows would show her files as belonging to an unknown account, and refusing access even to an Administrator.
I could have worked around this by booting a Knoppix livecd and taking over, but that would have been slow; I thought that surely there was a pure-Windows solution, some "admin command-line magic", that would fix things. And so the googling started...

There are basically two main elements in Windows file security: the Owner account, and the Access Control Lists (ACL) applied to the object (or inherited). So the first step was taking ownership of all the objects; I accomplished this with a simple script using WMI:

Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set colFolders = objWMIService.ExecQuery("Select * From Win32_Directory Where Name LIKE 'F:%'")
For Each objFolder in colFolders
    ' Add the input parameters.
    Set objInParam = objFolder.Methods_("TakeOwnerShipEx")._
        inParameters.SpawnInstance_()
    objInParam.Properties_.Item("Recursive") =  true
    objFolder.TakeOwnershipEx
    wscript.echo objFolder.Name
Next

The script uses a WQL query to retrieve all the directory objects, then takes ownership of them, using the Recursive option in order to take over all files included in the directory as well. I ran this from the command line with "cscript myfile.vbs" and it worked. (I have to say that for some reason this script failed on a few directories under "Program Files", but I simply ignored them.)

Now I could open any directory and set permissions on any object, but I still could not copy several files; this was because the ACL on these objects were set to refuse access to everyone but the old user. Unfortunately, I didn't know how to do that with WQL (I honestly don't know whether it's even possible); so I used SubInACL instead. This is a little tool you can download from Microsoft; it "enables administrators to obtain security information about files, registry keys, and services, and transfer this information from user to user, from local or global group to group, and from domain to domain." Exactly what I needed!

subinacl.exe /subdirectories "F:\*" /grant=Administrators=F

This one-liner simply grants Full (F) rights to any object under the F drive. A few minutes later, and I was finally able to copy the files.

And they say Unix is complicated? If this was an ext2 drive, I could simply have mounted the drive as root to do whatever I wanted. Windows administration is really a bitch.

2 comments:

Unknown said...

Indeed, please digress: how come that the better spec'ed machine is laying around instead of being used as a primary computer?

toyg said...

It was actually planned that "one day" she would migrate to this machine, I prepared it more than a year ago, but she never bothered to move because of the tedious first steps (reinstalling apps etc). Now she'll have to do it, and probably one of the drives is completely lost. So I guess somebody learnt a lesson...