Posts Tagged ‘Utilities’

The case of the undeletable directory

I had a “fun” time today with some directories that I could not delete.  These were mandatory roaming profiles that I previously had attempted to upload to a file server using “robocopy”.  Owing to switches that I used when performing the upload, directory junctions were treated as files, and robocopy got caught in a recursive loop because of a circular reference to “Application Data”.  By the time I caught the problem, I had created a set of nested “Application Data” directories that must have been over 400 characters long.

All of the tricks I had used in the past to delete “deep” directories were failing me.  “Dir /s /q [dirName]” failed with “Access Denied”, even though I was the directory owner.  Running the command as System encountered the same problem.  I mapped a drive to the directory, as deep down in the nested folders as I could get.  From there, I was able to “CD” to the deepest “Application Data” directory, but I still could not delete the directory.  (I got a “directory not empty” error.)

Eventually, Google unveiled a suggestion to use “robocopy” to mirror an empty directory to the problematic directory.  (Unfortunately, I have lost track of the link, so I cannot give credit where it is due.)  “Good idea,” I thought.  Why not use the utility that created the problem to solve the problem?  After all, if robocopy can create paths that are 400 characters long, perhaps it can delete them, too.

To test, I simply created an empty directory “E:\foo”, and ran the command:
robocopy.exe /mir /e E:\foo E:\mandatory\corruptProfile

Robocopy quickly chewed though the problematic profile, and a few seconds later I had an empty directory that I was able to delete.  Hurray!

WiFi Profiles for Windows 8

So Windows 8 is here, to little fanfare at the University.  While I am always happy to have an updated version of Windows to work with, I see that I have yet to blog anything about it.  Perhaps that is because, unlike with the release of Windows 7, there was so little that was relatively “wrong” with the previous release.  I find myself with not much “to do” to get the enterprise ready for Windows 8.  Other reasons for the lack of hype… Windows 7 applications seem, for the most part, to “just work” on Windows 8, thus necessitating very little in the way of application compatibility planning.

Still, we have run into a few hiccups.  I spent most of the last two days updating the UVM WiFi Configuration Tool scripts and experimenting with Group Policy settings to make WPA2-protected wireless working consistently (Previously discussed here, way back in ought-eight.).  In the end, there was very little that I did to the WiFi policies that was Windows 8 specific.  The WiFi profile that we are using maintains backward compatibility with both Windows 7 and Windows Vista.

Here are the details:

  • The 802.1x settings in our WiFi profile was updated to use “user authentication” instead of “user or computer authentication”.  Under XP, this option was called “user reauthentication”.  “ReAuthentication” meant that the computer would attempt to log on as the computer account, but that if the connection was lost, it would re-authenticate as the logged on user.  Under XP, it was not possible to prevent computer authentication attempts.  However, under Win7/Win8, user authentication is just that… only user authentication is attempted, computer authentication is excluded.  We have verified this by looking at the RADIUS server logs.  Switching to “user authentication” will cut down on log errors on the RADIUS servers, and will result in fewer errors on client systems as well.
  • We have added a new trust anchor for our RADIUS server certificate in the WiFi profile.  This was necessitated by mergers and acquisitions on the CA business.  “Equifax” provided our original WPA2/PEAP certificate.  When we went to renew our certificate, we found that Equifax had been acquired by GeoTrust, and that new certificates would be issued from a GeoTrust intermediate CA.  However, this intermediate CA would be cross-signed using the Equifax root CA, so the Equifax trust anchor would still work.  The problem is that if a system has both the GeoTrustandEquifax certs present in the local trusted roots certificate store, it will validate the “” up to the GeoTrust anchor, and will ignore the cross-signing with Equifax.  This results in WiFi connection errors.  When I add the GeoTrust cert as an additional trust anchor, the problem goes away.
  • The VBScript I use to install the WiFi profile is packaged inside a 7-Zip self extractor.  The use of this self-extractor triggers the Windows “Program Compatibility Assistant”, which in turn raises a “This program might not have installed correctly” error after the tool runs.  This problem is corrected by embedding a “manifest” file into the tool.  Typically, this is done using the “mt.exe” tool included in the Windows SDK.  Unfortunately, MT.exe corrupts self-extracting 7-Zip archives (this also is a known problem with WinRAR, and perhaps other similar tools).  Fortunately I was able to work around the problem using “Resource Tuner” from Heaventools.  I needed to add “trustInfo” and “compatibility” sections to the manifest.  My blog engine is really bad about posting XML content in a page, so I will forego posting the manifest here. You can find sample manifests pretty easily though Google.
  • When we run the packaged configuration tool, we get a warning that the application package is unsigned and may not be trustworthy.  I used “signtool.exe” from the Windows SDK to add a signature to the executable, so now it is considered somewhat more trustworthy.  Good instructions on the use of signtool.exe can be found here:
    I am using a code signing cert that we obtained from the certificate service, hosted by Comodo.  It works.
  • Finally, I updated the profile installer VBScript to make reconfiguration a bit easier (subroutines were converted to functions so that variables set at the start of the script can be passed down to the function.  We then can set things like the trust anchor name, WiFi network name, and log file name at the start of the script where they are more easily edited.  Also, I removed support for Windows XP… no more Service Pack detection, Hotfix installation, or third-party profile installation utilities are needed by the script.  I was able to hack the script down to about a quarter of its original size as a result.  The new script is included below, for those who like that sort of thing…


Option Explicit
'On Error Resume Next
'Install UVM WPA2-Enterprise wireless profile
' Version 1.3 by J. Greg Mackinnon, University of Vermont
' Supported platforms:  Windows Vista, 7, and 8
' Requires external tools:  "CertMgr.exe" (from the Windows Platform SDK)
' Requires external files:  Root CA certificate file, 
'                           WiFi XML configuration files for Vista+ Windows OS.
'                            (obtained by running "netsh wlan export profile UVM .\"
' NOTE: modify variables in the "Define variables" section to suit your environment.

' Version 1.0 - Supported UVM WiFi using WPA2, Equifax certs, Windows XP SP2+ and Vista OS
' Version 1.1 - Updated to support Windows 7
' Version 1.2 - Updated to support Windows 8.  Removed support for XP 
'             - Removed third-party "ZWlanCfg" utility and OS Hotfix installation functions (were only needed for XP support)
' Version 1.3 - Converted existing subroutines to functions to allow for easier switching of CAs and WiFi networks.
'             - Moved Global Variables to the top of the script for easier modification.
'             - Updated CA cert and WPA Profile supporting files to use "GeoTrust" instead of "Equifax".

' Create constants
Const cLogFile = "install_UVM_WiFi.log"

' Declare variables
Dim oShell, oUserEnv, oFSO, oFile, oRegExp
Dim iSPVer
Dim sTempEnv, strComputer, sOSTest, sOS, sCertName, sCertFile, sNetName, sProfileFile
Dim bReRun

' Define variables
bReRun = False
strComputer = "."
sOSTest = "Vista|Windows 7|Windows 8" 'Regular Expression for OS compatibility testing
sCertName = "GeoTrust Global CA"      'Friendly name of the trust anchor certificate
sCertFile = "GeoTrustGlobalCA.cer"    'Name of the trust anchor file
sNetName = "UVM"                      'Name of the WiFi Access Point
sProfileFile = ".\Wi-Fi-UVM.xml"      'Name of the Vista+ wlan profile file.

' Instantiate global objects
Set oShell = WScript.CreateObject("WScript.Shell")
Set oFSO = CreateObject("Scripting.FileSystemObject")
sTempEnv = oShell.ExpandEnvironmentStrings("%TEMP%") & "\"
Set oFile = oFSO.CreateTextFile(sTempEnv & cLogFile,True)
Set oRegExp = New RegExp
oRegExp.IgnoreCase = True
oRegExp.Global = True
oRegExp.Pattern = sOSTest

' Define Functions
Function fDetectOS(sOS, iSPVer)
'Detect OS Function - detects OS Caption string and Service Pack integer from WMI WIN32_OperatingSystem.
'Expects to varibles passed, returns the full OS Caption String, and SP Major Version intger
	'Declare variables
	Dim colItems
	Dim objWMIService, objItem
	'Instantiate local objects/collections
	Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2") 
	Set colItems = objWMIService.ExecQuery("Select * from Win32_OperatingSystem")

	For Each objItem In colItems
	  sOS = objItem.Caption
	  oFile.WriteLine "Detected Operating System: " & sOS
	  iSPVer = CInt(objItem.ServicePackMajorVersion)
	  oFile.WriteLine "Detected Service Pack Version: " & iSPVer
	  oFile.WriteLine "Service Pack Minor Version: " & objItem.ServicePackMinorVersion
	'Clean local objects/variables
	Set objItem = Nothing
	Set colItems = Nothing
	Set objWMIService = Nothing
End Function

Function fInstCert(sCertName,sCertFile)
' Installs cert with sCertName root CA cert into machine "root" store.
' Requires:  certmgr.exe from the Windows Platform SDK (available with VS .NET or VS 2008 installations), 
'	sCertName variable - contains the friendly name of the root CA
'	sCertFile variable - contains the name of the root CA certificate file
' Requres:  Root CA cert file
' Notes:  We use the "root" argument to certmgr.exe to install into the "Trusted Root Certificate Authorities".  
'		We also could use "ca" to install Intermediate Certificate Authorities.
'		In a previous version of this script we used "oShell.Run", but his returned unexpected results on the
'		Windows 7 platform... using .Exec now.
	Dim bCertPresent, bInstSuccess
	Dim oExec
	Dim sOut

	bCertPresent = false
	bInstSuccess = false
	set oExec = oShell.Exec("certmgr.exe -c -s -r localMachine root")

	Do Until oExec.StdOut.AtEndOfStream
		sOut = oExec.StdOut.ReadLine()
		if InStr(sOut, sCertName) Then
			'oFile.WriteLine sOut
			'WScript.Echo sOut
			bCertPresent = true
		End If

	if bCertPresent = false then
		oFile.WriteLine "Root Certificate for """ & sCertName & """ needs to be installed.  Attempting install..."
		set oExec = oShell.Exec("certmgr.exe -add -c " & sCertFile & " -s -r localMachine root")
		Do Until oExec.StdOut.AtEndOfStream
			sOut = oExec.StdOut.ReadLine()
			if InStr(sOut, "Succeeded") Then
				'oFile.WriteLine sOut
				bInstSuccess = true
			End If
		if bInstSuccess = true then
			oFile.WriteLine "Certificate installed successfully"
			oFile.WriteLine "Certificate failed to install... You will need to install the " _
				& "certificate manually.  See the instructions at " _
				& ", then run this script again to compelte installation of the UVM wireless profile."
			WScript.Quit -2
		end if
		oFile.WriteLine "Root Certificate for """ & sCertName & """ is already installed."
	End If
End Function

Function fImportProfile(sProfileFile,sNetName)
'Imports Vista+ Wireless Profile using NETSH command.  
'Requires: a Vista+ wifi profile file exported using NETSH, 
'	sProfileFile - string containing name of the wlan XML profile file to be imported
'	sNetName - string contining the name of the wlan profile name (WiFi Network Name)

	'On Error Resume Next
	Const cUserScope = "all"
	Dim iStrMatch
	Dim oExec, oStdOut
	Dim sStdOutLine
	oFile.WriteLine "Executing command: netsh wlan add profile filename=""" & sProfileFile & """ user=" & cUserScope & ""
	Set oExec = oShell.Exec("netsh wlan add profile filename=""" & sProfileFile & """ user=" & cUserScope & "")
	Set oStdOut = oExec.stdOut
	While Not oStdOut.AtEndOfStream
		sStdOutLine = oStdOut.ReadLine
		iStrMatch = CInt(InStr(sStdOutLine, "Profile " & sNetName & " is added on interface"))
		If iStrMatch > 0 Then
			WScript.Echo "The " & sNetName & " wireless profile was added successfully to your system"
		ElseIf iStrMatch = 0 Then
			WScript.Echo "The wireless profile failed to import.  Please see the manual profile " _
			& "configuration instructions available at  A " _
			& "log file named " & cLogFile & " which contains the full error message can be " _
			& "found in the " & sTempEnv & " directory."
			WScript.Quit -3
		End If
	Set oStdOut = Nothing
	Set oExec = Nothing
End Function
' End Functions

' Begin Main

fDetectOS sOS, iSPVer

If oRegExp.Test(sOS) = True Then
	fInstCert sCertName, sCertFile
	fImportProfile sProfileFile, sNetName
	oFile.WriteLine "Your operating system is not supported for use with this script."
	WScript.Quit -4
End If


' Environment cleanup 
Set oFile = Nothing
Set oFSO = Nothing
Set oUserEnv = Nothing
Set oShell = Nothing
Set oRegExp = Nothing

' End Main

The Mysterious Case of the Un-Deletable MBR (Or, More Reasons to Hate PGP)

Shortly after releasing MDT 2012 on the general public I got a call from a colleague who told me that his LiteTouch deployment was failing.  He was able to boot to LiteTouch media, go though the configuration wizard, and initiate setup.  LiteTouch would partition the drive, Windows Setup would start, the image would get written to the computer, and then the system would reboot… so far so good. What happened next was unexpected.  The computer booted to the PGP BootGuard screen.

Turns out we were dealing with a system that had been encrypted using PGP Whole Disk Encryption. However, we have a lot of those, and deployment has not failed on them before.  In the past, LiteTouch dutifully has erased the Master Boot Record (MBR) and all existing partition tables on the system, effectively wiping PGP BootGuard from the machine before running Windows Setup.

So what changed?  Is this a bug in MDT 2012?  Something new in PGP Desktop version 10.2.0 MP4?  Or a configuration problem in our LiteTouch environment.

Let’s omit the details of ~6 hours of troubleshooting… it was a change in the WinPE LiteTouch environment, and PGP.  It appears, though investigation, that the PGP filter drivers attempt to block access to the MBR of the hard drive.  Since I had injected PGP drivers into the LiteTouch 32-bit boot media, I had, effectively created a situation where DiskPart.exe would be unable to remove PGP BootGuard from the system.  The really irritating part is that the PGP drivers do not pass any indication to the Windows utilities that there has been an error writing to the MBR.  DiskPart.exe, BootSect.exe, and the DaRT Disk Commander all can be used to repair MBRs.  But when used in a PGP-enabled environment they all report success in manipulating the disk MBR, but all of them fail to make any real change to the true MBR.  How do you usually erase a drive?  For me, I would run “diskpart.exe, select disk 0, clean”.  With PGP drivers in place, you could run this series of commands, think that you had erased the drive, but still end up with PGP BootGuard in your MBR.  It really is maddening.

Symantec/PGP claim that you can remove the MBR data by “deinstrumenting” the disk using the “pgpwde.exe” command.  The problem with this is, pgpwde will not let you deinstrument an encrypted drive.  So, you would have to decrypt the drive first, then deinstrument.  I am not wasting time on that.  Worse yet, if your drive was partially encrypted when you erased the data partition, PGPWDE still reports the drive status as “partially encrypted”, and refuses to perform any actions on the drive (such as “deinstrument”) until the current encryption (on the nonexistent drive) completes.  AARGH!

Fortunately, I was able to find a low-level disk manipulation utility that actually works in 32-bit PGP-enabled WinPE environments.  PlDD.exe:

There are other “DD” equivalents for Windows.  Most of them either fail to work against PGP (GnuWin32 DD.exe and the Crysocome DD), or will not function under WinPE (FAU DD).  PlDD is pretty old, and it does not work under 64-bit Windows.  But, we don’t need 64-bit support (PGP does not provide 64-bit drivers for WinPE!), it works perfectly in 32-bit Windows.  Thus, this is the perfect tool for the time being.

Getting the right command syntax to pldd.exe was a bit challenging as the tool itself has scarce documentation.  I wish I could credit all of the resources that I used to put this dense command together, but I have since lost the browser tabs.  The following is the pldd.exe command, suitable for plugging into an MDT task sequence as a custom command:

cmd.exe /c “%SCRIPTROOT%\Pldd.exe if of=\\.\PhysicalDrive0 bs=512 count=1″

Argument breakdown:

  • if = In File.  In this version of DD, if provided with parameters, will use a string of zeros as input.
  • of = Out file.  In this case, we are using the Windows device path “\\.\PhysicalDrive0″, which is fixed disk zero.  I think this device path is referenced in the gnuwin32 dd docs.
  • bs = Block size.  We are choosing to write in 512 byte blocks.
  • count = The number of blocks to write.  We are going to write one 512 byte block to the “out file”.

To summarize, we use pldd to write 512 bytes of zeros to the start of physical drive zero.  This action wipes out the MBR and the disk signature of the drive (sorry, I lost my reference for this factoid, too).  Zeroing 512 bytes of disk is rather faster than zeroing the entire drive, which is the only other option I have seen referenced in the tubes for fixing this issue.

Share and Enjoy.

Microsoft Emergency Repair Disk, PGP, and Windows System Recovery

Microsoft Campus Agreement includes access to the Microsoft "Diagnostics and Recovery Toolkit" (DaRT), the chief component of which is the Emergency Repair Disk (ERD).  ERD boot images can be found in the Microsoft Campus Agreement share:

DaRT is part of the larger Microsoft Desktop Optimization Pack (MDOP).  You can locate the DaRT installer and repair disk generation utility in the MDOP distribution utility:

The DaRT recovery disk contains many immensely useful utilities, including:

  • Offline Registry Editor
  • NTFS File Restore (undelete utiltiy)
  • Disk Commander (disk repair)
  • Secure Wipe (securely erases a drive)
  • Offline Hotfix Uninstaller
  • System File Consistency (SFC) scanner
  • Offline "Standalone System Sweeper" (malware removal tool)

Those of you who have been using PGP Whole Disk Encryption might be wondering if any of these utilities may be wondering if these sorts of utilities will be at all useful on systems that have been encrypted.  The answer is yes, as long as the boot media has had PGP command line utilities added to it.  We have generated an ERD image with PGP drivers already pre-injected:

You also can transfer the ERD image to a bootable USB drive by following the directions in the README file here:

Unfortunately, PGP has not (yet) provided command line utilities for 64-bit WinPE environments.  But fortunately, you can use 32-bit WinPE to access 64-bit versions of Windows.  In this case, you will only be able to run a small subset of the ERD utilities against the offline OS.  However, you can decrypt your 64-bit OS using the 32-bit ERD, and then run the 64-bit ERD against the decrypted drive (clearly, this will take a large time commitment).

To access an encrypted disk for use with the DaRT ERD, you may need to "fake out" the ERD boot menu. 

  1. When the system restore process starts, the tool will not be able to detect an Operating System.  Select the "Restore your computer using a system image…" option, as shown below:
  2. When the tool fails to detect a restoration image, click "Cancel":
  3. Then click "cancel" again.  From the System Recovery Options dialog, select "Command Prompt":
  4. Once inside the command prompt you can use the "PGPWDE" utility to access your drive. 

Here are some sample PGPWDE commands:

  • "pgpwde.exe –enum" – Take note of the disk numbers of any encrypted drives that you wish to unlock (typically "0" for the first disk on the system).
  • "pgpwde.exe –auth –disk 0 –interactive" – To unlock the disk for direct access by utilities on the DaRT ERD.
  • "pgpwde.exe –decrypt –disk 0 –interactive" – To fully decrypt the disk (note that this can take a long time, and there is no progress indicator).
  • "pgpwde.exe –status –disk 0" – To view the status of a disk encryption or decryption process on a specified drive.

Note that after you have run the "pgpwde.exe –auth" command, you can then re-launch the System Recovery conosle by running the command:

  • winpeshl.exe

You now should be able to launch the Microsoft Diagnostics and Recovery Toolset or use the "System Restore" option in the System Recovery Options dialog, and have full access to the Operating System on the encrypted disk.

Share and enjoy.

HTTP to HTTPS redirect using Iconic URL Rewriter

So, you have a site that needs to to run over SSL-only (shouldn’t they all?)? You don’t trust your clients to type that ever-important “s” after “http” (and why would they?)? You think they will get scared off by those “Secure connection required” error pages (they will!)? You are not running IIS7 (who is?)? Not using ASP.NET?

In the past we accomplished this using a client-side redirect, by creating a custom 404.3 error page with a Javascript redirect. This worked well, but what if you client systems won’t support javascript (i.e. it is a webdav connection)?

Codplex to the rescue! The venerable “Ionic URL Rewrite” ISAPI filter has been updated, and published on Codeplex:

Thanks, Cheeso!

IIRF now supports the ability to return URL redirects, in addition to simple rewrites.  To use IIRF to redirect a non-SSL URL to a secure version, follow the installation instructions included with IIRF.  Then:

  • Stop your production IIS site from listening on port 80 and enforce SSL usage.
  • Make sure that the production site is not using host headers that would override your port settings.
  • Set up a secondary IIS site which listens on port 80 only.  Add the IIRF ISAPI filter to this site.

Here is some sample entires you could use in the IsapiRewrite4.ini configration file to accomplish the redirect.  Note that [R] instead of [R=301] also works, but this performs a 302 “Temporary” redirect.  Conceptually I prefer a 301 (not that it matters because search crawlers are not hitting our Intranet sites):

Read More

Making Order of Chaos with MS LogParser 2.2

I was having some trouble today sifting though some SharePoint diagnostic logs.  There is way too much noise in the logs, and the TSV format makes finding information less than simple.  Luckily, I decided to give MS Log Parser a go… it has been sitting in an install directory waiting for some excercise for over a year…

LogParser lets us run SQL-like queries against the contents of many different types of structured data files, including CSV, TSV, XML, W3C, IIS, and many others.  Output can be formatted in almost as many ways, including to a GUI dataview window. Anyone who likes SQL queries will love this.

Below is a simple sample conversion that I ran to strip out all “Medium” rated alerts, and anything that was not generated by the SharePoint Search Services.:

LogParser.exe -i:TSV -o TSV "SELECT Timestamp, Process, Area, Category, Level, Message
INTO searchEvents.tsv from 'c:\Program Files\Common Files\Microsoft Shared\web server
extensions\12\LOGS\SHAREPOINT1-20081111-1237.log' WHERE Area='Search Server Common'
AND Level<>'Medium'"

BitLocker Recovery Tool Problems

The motherboard on my trusty Dell Latitude D820 went sour this Sunday, requiring a full replacement.  No one was ever killed by losing access to their laptop for a few days, but I was somewhat annoyed to have lost access to my iTunes installation (thus making backup and sync of my iPod impossible), and I also had a few video files which I was working with stored locally.  So I decided to try testing out the BitLocker recovery tool to see if I could get access to my files.

First, we had to grab the BitLocker Recovery Tool from Microsoft:

I installed the tool onto a Vista desktop, and connected my laptop drive to the system using a SATA-to-USB converter, such as the one seen here:
That worked really well… my BitLocker-encrypted drive immediately became visible to Windows, although it (quite naturally) could not be read.

I then ran repair-bde.exe, providing the BDE recovery key which I had escrowed in Active Directory.  I used the option to extract the recovered data to an image file on my external ieee1394 drive.  Repair-bde dutifully extracted the drive contents to a file, and reported success.

Now the tricky part… how do we read this massive image file?  It does not appear to be a WIM file (i.e. “imagex /mount” claims that this is not a valid WIM image).  It cannot be mounted as an ISO, nor can it be extracted using any of the archive handlers supported by 7-zip.  It cannot be mounted as a virtual disk using Virtual PC.  What is it???

I contacted Microsoft support to find out… support claims that I should use “IMGMOUNT.EXE” to mount the image.  Some Googling suggests that this utility is part of the short-lived “Automated Deployment Services”, or “ADS” product that Microsoft released to allow deployment of Windows Server 2003 images:

So I downloaded ADS, and did a “custom” install, and selected the “image creation tools”.  This installed “IMGMOUNT.EXE” on my system, in the “%ProgramFiles%\Microsoft ADS\bin” directory.  Unfortunately, IMGMOUNT also reports that this is not a valid image.  Microsoft support also told me that the third-party tool “ISOBuster” should be able to mount the image:
But this failed to work, too.  I guess the image generated by Repair-bde.exe simply was not valid.

Oh well, by this time, my laptop has been repaired and I was able to get back into my OS using the BitLocker recovery password.  I guess the takehome lesson is not to use the recover-to-image option of the repair-bde tool… instead, recover to the root on an external drive.  This may not work any better, but at least you will know immediately if the utility is successful in decrypting your drive contents.

The other problem that I ran into was the fact that I lost my TPM chip with the motherboard.  As you may know, your BitLocker decryption keys are stored on your TPM, and that your TPM cannot be detached from your motherboard.  New motherboard=new TPM.  Oh well… It looks like I need to turn off BitLocker on my system, decrypt the whole drive, and then re-activate BitLocker.  There does not appear to be a way to write the BitLocker decryption keys to the TPM once the drive is already encrypted… Bummer!