Posts Tagged ‘Windows’

Robocopy can silently fail to copy directories with invalid UTF-16 names (or, why I always compare after copying)

December 11, 2014

Over the last few days I’ve been copying the bulk of the home directories on my primary file server over to a new volume (don’t ask) and, of course, I did a comparison afterwards to make sure the copy was successful [1].  I’m talking about 3070 home directories, comprising over seven million files structured in any number of strange and wonderful ways.

I wasn’t at all surprised to find that 3069 of those directories had copied perfectly; robocopy is pretty reliable.

I was a little surprised to find that one directory had an anomaly, but still, glitches happen.  I became puzzled, though, when I realized what the problem was: an entire subdirectory was missing.  Robocopy hadn’t reported any errors.  What’s more, when I ran robocopy over that home directory again, it reported that there was nothing to do: as far as it was concerned, source and destination were a perfect match.

Explorer didn’t show me much.  The name of the two directories in the source looked the same; the first character was shown as a box.  Another little tool of mine, though, could see the difference:

.\%d898Adobe\
.\%dabdAdobe\

The tool escapes non-ASCII characters with a percent sign followed by a hexadecimal representation, so the first wide character is 0xD898 in the first directory and 0xDADB in the second.  Otherwise the names are the same.  Only the first one was present in the destination.

The next step, obviously, was to look up the Unicode code points 0xD898 and 0xDADB.  As it turns out, they are “high-surrogate code points”, used in UTF-16 to encode Unicode code points larger than 16 bits.  The key here is that surrogate code points are only valid in pairs: an individual surrogate code point is meaningless.

Of course, NTFS doesn’t care.  It doesn’t really understand Unicode, so one 16-bit character is much like another.  As far as NTFS is concerned, those are perfectly good (and distinct) names.  Robocopy, however, must for some reason be converting or normalizing the UTF-16 strings, and as a result it sees those two names as identical.  (It appears to be ignoring the second occurrence of the “same” name in a single directory; it doesn’t attempt to copy the second subdirectory at all.)

So, if you’re in the habit of creating files with invalid UTF-16 names, be warned. 🙂

[1] Using some code I wrote myself.  Microsoft don’t seem to have provided a reliable directory-level comparison tool, and I’m not aware of any existing third-party solutions.  I should open-source that tool one day.

Advertisements

Adobe Creative Suite 6 Installs Very Slowly

March 1, 2013

[Additional 2014-01-10: the same issue occurs with Adobe Creative Cloud and the CCP.  In this case the outbound attempts are on both port 80 and port 443, so you’ll need two rules.]

Here’s the scenario: when using AAMEE (the “Adobe Application Manager Enterprise Edition”) to install Adobe Creative Suite 6 on a machine [1] on an isolated LAN (i.e., a machine with no direct connection to the internet) it takes a very long time to install.  A very, very long time.  During most of this time CPU and disk activity are minimal.

It turns out that the installer is trying to contact various web sites on the internet, including crl.verisign.net, presumably in order to see whether any of the digital certificates on files in the install media have been revoked.  When the attempt times out, the installer continues, but it makes many such attempts.

The workaround I recommend is to install an outbound Windows Firewall rule blocking web traffic.  Windows then instantly fails any attempt to contact a web site.  You can do this from an administrative command line like this (split for readability):

netsh advfirewall firewall add rule name="block www" dir=out 
    action=block protocol=tcp remoteport=80

To remove the rule later, this is the command:

netsh advfirewall firewall delete rule name="block www"

So how much time does this save?  Well, on one of our new machines, the installer takes 30 minutes if the firewall rule is in place.  Without it, it takes five hours.

I’ll be raising this with Adobe and perhaps, if we’re lucky, the next version won’t be quite so vigorous in its efforts to check the digital signatures.  In the meantime, you may find this approach useful.

[1] The same problem may exist when using the regular installer; I haven’t checked.

Forcing Windows to identify a special-purpose network

February 3, 2013

One problem that comes up moderately frequently when dealing with Windows servers is that the Network Location Awareness service (NLA) doesn’t allow you to assign a particular adapter to a particular network.  On ordinary networks NLA seems to do a reasonable job, but typically it can’t cope with special-purpose networks such as SANs or point-to-point links; these are all lumped together as the “Unidentified Network” which by default is contained in the Public network profile.

Why is this a problem?  Because the Windows Firewall is configured on a per-profile basis.  That’s fine if Windows Firewall doesn’t interfere with whatever you’re doing on the special-purpose network.  Unfortunately, sometimes it does.

If you search the internet, you’ll find a number of scripts which change which network profile the “Unidentified Network” is put into.  You can also do this with group policy.  This means you can make unidentified networks Private, and turn Windows Firewall off (or set relaxed rules) for Private networks.  Is this a solution?  Not really, because it doesn’t just affect your special-purpose network, it affects every unidentified network from now on.  So if, for any reason, NLA ever fails to identify the network associated with your primary internet connection, your firewall will go down.  I’m not happy about that.

I’ve found a possible workaround.  IMPORTANT: I haven’t tested this thoroughly, and at the moment I’m not planning to use it on my production server (or at least only if every other option fails).  I’ve only tried it on Windows 2012 although I suspect it will work on older versions as well.  It is entirely possible that it only works for certain ethernet drivers.  Try this only at your own risk and please take proper and adequate precautions.

In addition to adapter settings such as the DNS prefix, NLA uses the default gateway’s MAC address to uniquely identify the network.  Special-purpose networks don’t generally have a default gateway; if yours does, you probably don’t have this problem in the first place!  The idea is to create a fictitious default gateway, with suitable parameters, and the trick is that you have to give the fictitious gateway the same ethernet address as the local network adapter on the special-purpose network in question.  If you give it a make-believe ethernet address, it won’t work; you could instead give it the address of another machine on the same network, but then it won’t work if that machine is ever off-line.

(If your special network is a point-to-point link, you might instead prefer to specify the actual IP address at the other end of the link as the default gateway, if you don’t mind that NLA will see it as a new network if the ethernet address ever changes.)

So, for example: when I use get-netadapter in PowerShell I see the following results:

PS C:\Users\Administrator> get-netadapter

Name                      InterfaceDescription                    ifIndex Status       MacAddress             LinkSpeed
----                      --------------------                    ------- ------       ----------             ---------
Ethernet 2                Broadcom BCM5709C NetXtreme II Gi...#42      13 Disconnected 00-10-18-EC-7F-84          0 bps
SAN 2                     Broadcom BCM5716C NetXtreme II Gi...#41      15 Up           08-9E-01-39-53-AB         1 Gbps
SAN 1                     Broadcom BCM5709C NetXtreme II Gi...#43      12 Up           00-10-18-EC-7F-86         1 Gbps
UoW                       Broadcom BCM5716C NetXtreme II Gi...#40      14 Up           08-9E-01-39-53-AA         1 Gbps

In order to assign a specific network to the third adapter (interface index 12) I would use the following commands:

new-netroute 0.0.0.0/0 -interfaceindex 12 -nexthop 192.0.2.1 -publish no -routemetric 9999
new-netneighbor 192.0.2.1 -interfaceindex 12 -linklayeraddress 001018ec7f86 -state permanent

The first command assigns the default gateway for the interface.  I chose IP address 192.0.2.1 because it is reserved and will never be used by a real device; I suggest you do the same.  We don’t want this route to be published, and we set the metric to 9999 so that it won’t ever be used.  (The system uses the default gateway with the lowest metric.)

The second command assigns the fictitious IP address an ethernet address; as discussed before, we use the same ethernet address as the adapter we’re assigning it to.  Note that the ethernet address must be entered in a different format to that in which it is displayed; just remove the hyphens.  We make the mapping permanent.  (You can use the remove-netneighbor command if you want to remove it later.)

I hope this is helpful.  If you do try it, please let me know how it goes.

Safe Computing: Another Case of Too Many Moving Parts

May 15, 2012

So, one of this month’s Windows XP updates, KB2686509, has a problem.  Long story short, in order to fix a security problem, Microsoft had to make the rules more strict for software that installs custom keyboard layouts.  If I’ve understood correctly, most software already does it the recommended way, but if you have software installed that is incompatible with the new rules the update will refuse to install.  You may be able to fix the problem yourself, or you may have to contact your software vendor.

That isn’t actually the interesting part.  The update will also refuse to install if you’ve remapped a key, for reasons that aren’t entirely clear.

Thought for today: If God wanted us to remap keys, he’d have given us a control panel.

Nah, too easy an answer.  People have reasons for wanting to remap keys, and the process is, or at least was, documented.  If Microsoft are going to make it that easy, of course people are going to do it, and it shouldn’t cause strange problems years later.

No, this is another case of too many moving parts.  We need to be able to configure this sort of thing, sure, but it needs to be done in a controlled way, so that issues can be avoided, or at least properly identified.  Of course, none of the suggestions in my previous post would have addressed this issue, so the question becomes: what should the ideal operating system do to deal with this sort of situation?

I think the solution [1] is to associate changes to the registry (or rather, its equivalent) with the application (or component) that made those changes.  This would probably be implemented by keeping a collection of registry settings for each application; a query for a particular setting would return the default value only if no application had made any changes.  As a bonus, you’d know when two applications or components were in conflict, although to be honest I’m not sure what you’d do about it.

(This doesn’t mean that you couldn’t make ad-hoc changes; in this context, an “application” could be a single text file, not much different from a Windows .reg file except that it would have to include a name to go in the list of installed software.  The registry editor could build these for you.)

Anyway, if Windows worked like that, KB2686509 wouldn’t have had to, metaphorically speaking, shrug its shoulders at you.  It would know which application had configured the setting it was upset about and could say something like, “I can’t install because I am an incompatible with the installed program, Freddy’s Keyboard Mapper.  Please contact the vendor for an upgrade, or uninstall that program and try again.”

I think that would have upset fewer people.

Harry.

[1] By solution, I mean a way for a hypothetical new operating system to avoid running into this sort of trouble.  It would not be feasible to modify Windows to work in this way.

When Guest is the administrator

May 5, 2011

Nommo was kind enough to point me to his latest blog entry which discusses a troubleshooting case where the Guest account had somehow wound up being the only active administrator account on a Windows Vista computer.  This was reasonably easy to reproduce (although I used Windows 7 instead) and, indeed, user management tools don’t work as might be expected.

This is interesting.  In most other respects the Guest account still functions as an administrative account.  At first I thought I understood exactly why this happened (to do with the way LAN Manager handled security way back in the days of DOS) but a bit of experimentation showed I was wrong.  It now looks as though a Guest logon is tagged in some way and prohibited from doing any user management – the Guest account can’t even look up its own details – unless you elevate to it from another account, in which case it has user-level access to account management but not administrator-level.  Weird, huh?

Only the actual Guest account is affected; other accounts that are in both Administrators and Guests are not.

Because only account management is blocked, you can get around this in a few ways.  Probably the simplest in most cases is to download the psexec tool from Microsoft.  Start an elevated command-line window by typing “cmd” into the “Search Programs and Files” box in the Start Menu and pressing Control-Shift-Enter.  Then type:

cd /d c:\directory\where\psexec\was\downloaded\to
psexec -s \\127.0.0.1 net localgroup Administrators /add myusername

pressing ENTER after each line and changing “myusername” to the username of the other (currently non-administrative) account.

Alternately, you could edit the registry as described in my earlier post but you don’t need to boot from external media:

  1. Go to the Start Menu and type “regedit” and press ENTER.
  2. Open HKEY_LOCAL_MACHINE, then SYSTEM, then Setup.
  3. Double-click on SetupType in the right-hand pane.  Enter 2 and press OK.
  4. Double-click on CmdLine.  Enter cmd.exe and press OK.
  5. Reboot the machine.  A command window should appear.
  6. Type “net localgroup Administrators /add myusername” and press ENTER.
  7. Type: “exit” and press ENTER.

Again, “myusername” should be replaced with the username of an existing, non-administrative account.  After this procedure, the account is administrative.  You could also use “net user myusername newpassword” to change the password if necessary.  (The same caveat applies as in my previous post: doing this permanently locks you out of any encrypted files in the account.)

Now, obviously Guest shouldn’t be an administrator.  The fact that things behave oddly in this situation is not a bug.  However, if Guest is an administrator the normal recovery options don’t work properly.  In particular you are supposed to be able to log in as Administrator if no usable administrative accounts exist, and in this situation you can’t, and this is a bug.

Hope this helps.

Installing 32-bit software as SYSTEM in Windows 7 x64

February 20, 2011

Hi,

I recently ran into an issue updating the Sun Java runtime on our x64 machines.  We don’t have the budget for fancy deployment solutions, so we just use a startup script (actually an executable, but that’s just fine-tuning) that checks the version number and runs the installer(s) as necessary.

Installing the 32-bit JRE results in error code 1619, which NET HELPMSG translates as “This installation package could not be opened. Verify that the package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer package.”  Running the installer in interactive mode produces the same message.  The installer works normally when run from the context of a logged-in user.

Several hours of troubleshooting later, I identified the source of the problem.  Startup scripts run as local system.  In Windows 7, processes that run as local system have a special profile found in c:\windows\system32\config\systemprofile.  Unfortunately, on 64-bit systems, there are two system32 folders; one for 64-bit processes,and another (whose real name is syswow64) for 32-bit processes.  As a result, there are two separate system profiles; one for 32-bit, one for 64-bit.

So what?  Well, the Sun Java installer unpacks into a subfolder of the LocalLow application data directory.  In this case, the folder in question is c:\windows\system32\config\systemprofile\AppData\LocalLow\Sun\Java\jre1.6.0_24.  Because this is a 32-bit process, though, it is really writing to syswow64 instead of system32.

The Windows Installer, however, is a 64-bit process.  So when it is asked to open the MSI file, it’s looking in the wrong place; hence error code 1619.  The file can’t be opened because it can’t be found.

The same underlying problem (duplication of the system profile) seems to be the cause of this problem with Known Folders warning 1002 appearing repeatedly in the event log.  Some 32-bit system process is registering folder paths inside the (32-bit) system profile and of course these folders can’t be found by 64-bit processes.

For the problem with installing 32-bit software, there are a number of possible workarounds.  You could manually extract the installer files, copy them to a suitable path on the local system, and run them directly.  Most installers won’t mind this, although some will balk or fail to function properly.  Alternatively (and this is the solution I chose) you could create the necessary directory ahead of time and add a junction point (mklink /J) from the 64-bit profile to the 32-bit profile (note that this command line assumes you are in a 32-bit context, and has been split for readability):

mklink /J c:\windows\sysnative\config\systemprofile\AppData\LocalLow\Sun\Java\jre1.6.0_24
 c:\windows\syswow64\config\systemprofile\AppData\LocalLow\Sun\Java\jre1.6.0_24

This is the equivalent command if you are in a 64-bit context:

mklink /J c:\windows\system32\config\systemprofile\AppData\LocalLow\Sun\Java\jre1.6.0_24
 c:\windows\syswow64\config\systemprofile\AppData\LocalLow\Sun\Java\jre1.6.0_24

Another possible approach would be to merge the two system profiles together and create a junction point from one to the other.  That would solve this issue for all installers, as well as the Known Folders issue and any other variants.  However, I can’t recommend doing this; it’s too broad a change, and there’s no way to predict what it might break.  If you’re very brave, go ahead, but test thoroughly – and don’t blame me!

Hope this helps.

Harry.

Incorrect Username or Password – or perhaps the clock is wrong

July 2, 2010

Greetings!

OK, this one had me puzzled for an hour or two.  My main test box having failed, I had taken one of the older machines hanging around my office and given it a once-over; some extra RAM, a bigger hard disk drive, that sort of thing.  I noticed the motherboard battery had died, but figured I could live without it.  What the hey; the machine stays connected to the mains most of the time anyway.

So I go to install Windows 7 on the box, using our automated install system on my USB stick.  This is a Windows PE image which runs Windows Setup in unattended mode over the network.  It also includes a bit of in-house code so that you can provide an administrator password to join the machine to the domain in advance; once this password has been accepted, everything else happens automatically.  A few hours later the machine will be ready to use, software and all.  This sort of streamlining may seem unnecessary, but it does make life easier.

Except that this time the domain controller wouldn’t accept my password.  Typed it in again; no luck.  After trying once more, well, okay, several times more, and logging in on another machine to make sure I hadn’t gotten confused about which password went with which account, I realised there really was something wrong.

So I try it on another machine, and it works perfectly.  I try booting the first machine from a copy on CD instead of the one on my USB stick; no difference.  Bringing up a command line window allows me to explicitly attempt to connect to the domain controllers as well as other network servers, with both my own account and a test account with a simpler password – just in case!

The results were puzzling to say the least.  Error code 86 – the network password is not correct – for any user account but only from that one machine and only when connecting to a domain controller.  The file server, by comparison, was perfectly happy to accept the supposedly “incorrect” passwords.  In case there was something wrong with the Windows PE image, I repeated the experiment using the standard Windows 7 install DVD, but this exhibited the same problem.  Swapping the keyboards and network cables between the machines was a long shot at best, this didn’t pan out either.  The event log on the domain controller showed the logon failures but provided no additional information.  For some reason, the problem didn’t occur when booted to a copy of Windows PE 2 (which is based on Vista rather than Windows 7) but this didn’t help me much.

Eventually it dawned on me that the flat motherboard battery meant that the on-board clock would have been reset; the computer thought the year was 2004.  Mismatched clocks have been known to cause authentication problems, and sure enough, once I had corrected the date and time via the BIOS the domain controller accepted my password and the automated installer set to work.

I’m not sure what the moral of this story is exactly.  I suppose I should have remembered the failed battery as soon as the machine started behaving oddly, and stopped to think about whether there could be a connection.  Anyway, I’ve tagged this as a bug, not because the authentication should necessarily have worked, but because the error code (or at least the event log!) should have indicated the actual problem instead of insisting that the password was wrong.

Harry.

Resetting a password in Windows 7 or Windows Vista

March 9, 2010

One problem that comes up now and again for any OS (well, any modern OS) is how to recover administrative access to the system when the password has been forgotten.

There’s a reasonably straightforward solution [1] for Windows 7, which I haven’t seen on the web so far, so I thought I should publish it.  Be aware that I can’t offer or provide any warranty, support, or assistance with this procedure, apart perhaps from clarifying any part of the instructions that aren’t clear.  It’s always worked for me, but that’s all I can promise.

Additional note 13 June 2012: see also this question on superuser.com, which provides a number of alternatives.

This procedure also works on Windows Vista; the underlying technique works on Windows XP as well but is not usually feasible because the Windows XP install CD does not contain a command-line recovery option.

One important caveat: since this resets the password rather than letting you find out what it is, any encrypted files belonging to the user will be permanently lost.

This is the short version, for advanced users and sysadmins:

  1. Boot to Windows 7 from the installation or repair DVD, or from Windows PE 3 boot media, or from a Windows 7 installation on another HDD.  If the target OS is Vista, use the Vista installation DVD, or Windows PE 2, or another Vista installation.  (Booting to a mismatched version of Windows might work, but I’ve never tried it; if the registry file formats aren’t exactly the same between versions, this could result in a corrupted registry and an unbootable system.)
  2. Load the SYSTEM registry hive from the target OS.  Back it up first.
  3. In the Setup key, change SetupType to 2 and CmdLine to cmd.exe.
  4. Boot the target OS.  You’ll get a command-line window in system context.

The long version, for everyone else:

  1. Boot to your Windows 7 or Windows Vista installation DVD, whichever matches the installed OS.  If you purchased your computer from a responsible vendor, they’ll have provided you with one, although unfortunately many vendors don’t.
    Additional note 8 September 2011: In Windows 7, there is an option in the Start Menu (under Maintenance) to Create a System Repair Disc.  The CD or DVD this option creates is perfect for the job.  However, you have to be an administrator to use it, so unless you’ve done it ahead of time or can use a friend’s Windows 7 machine you’re out of luck.
    Additional note 1 September 2011: If your computer is 64-bit capable (you don’t need to actually be running a 64-bit OS) then you can use the install disk for Microsoft’s free server product, Hyper-V.  You can find it here.  Note, however, that it is a fairly big download, a little more than a gigabyte.
    Additional note 5 May 2011: Nommo was kind enough to point me to this post on Microsoft Answers which provides a link to downloadable repair disks for Vista and Windows 7.  I can’t from my own knowledge confirm that these disks are legitimate, and Microsoft aren’t telling, so use only at your own risk.  Indications are that they are probably OK.  (Personally, I wouldn’t use the charged-download option until I’d checked how much my OEM was going to charge to provide an installation disk.  Make sure the OEM knows you need a Windows installation disk, not a system recovery disk.)
    A vendor system recovery disk might offer the same functionality, and in some cases you can order an installation DVD from your vendor (or from Microsoft?).
  2. Select your language options on the first screen and press Next to continue.
  3. Choose “Repair Your Computer”.
  4. Choose “Use recovery tools…” and select your OS.  Make a note of which drive letter it is on, e.g., C: or D:.  This might not be the same drive letter you see when booted normally.
    Additional note 1 September 2011: if you get an error message when you press Next, this might be because the install disk you are using is not compatible with the version of Windows you have installed.  This will happen, for example, if you are using the Hyper-V install disk.  Don’t panic.  Just press SHIFT-F10 to open a command prompt and skip ahead to step 6.
  5. Select Command Prompt.
  6. In the command prompt window that appears, type “regedit” and press ENTER.
  7. Select HKEY_LOCAL_MACHINE and then choose Load Hive from the File menu.
  8. Find and open the file named SYSTEM on the drive you noted in step 4.  If Windows is in the default configuration, this will be in windows\system32\config.
  9. Enter a key name, e.g., “xxx”.
  10. Click the plus icon to the left of HKEY_LOCAL_MACHINE to open this key.  Select the xxx key.
  11. Select Export from the File Menu.  Change the Save as type to Registry Hive Files.  Type a name for the backup, for example, systembackup, and press Save.  (This step creates a backup of the unmodified SYSTEM registry hive as a precaution.)
  12. Open the xxx key, and select Setup.
  13. Double-click on SetupType in the right-hand pane.  Enter 2 and press OK.
  14. Double-click on CmdLine.  Enter cmd.exe and press OK.
  15. Close Registry Editor.  Type “regedit” and press ENTER to open it again.  (This step does not appear to be necessary in Windows 7, but in Windows Vista if you do not do this the next step might fail with an Access Denied error.)
  16. Open HKEY_LOCAL_MACHINE, select xxx, and choose Unload Hive from the File Menu.  Push Yes.
  17. Close the command window and the Registry Editor.  Remove the installation DVD and select Restart.
  18. When your computer boots up, another command window should appear.
  19. Type “net user foo bar”, replacing foo with the username of the account whose password you want to reset, and bar with the new password.  For example, you might type “net user Administrator letmein”.  Press ENTER.
  20. If you want to use the built-in Administrator account, you will probably need to enable it: type “net user Administrator /active:yes” and press ENTER.
  21. If you don’t know what the administrative username(s) are, type “net localgroup administrators” and press ENTER to find out.
  22. Type “exit” and press ENTER.
  23. When the logon screen appears, use the username and the new password to log in.

Note that if the entire disk is encrypted, this procedure will not work at all.  System administrators who want to prevent users from using techniques like this one to reset passwords should consider disk encryption. [2]  Another option is to configure the system BIOS to disallow booting from removable media, although if the user can open the case of the machine this can usually be reset.

Hope this helps.

Harry.

[1] Well, for some definitions of straightforward, anyway.

[2] I’ve heard tell of some administrators whose “solution” to this issue is to use the network firewall to block access to any web sites with instructions on resetting passwords!  Whether they also inspect all printed material entering the building, and ban anybody they think might be smart enough to just remember how to do it, I don’t know.

IOCTL_DISK_GET_LENGTH_INFO doesn’t work on floppy disks

January 12, 2010

I was trying to write a floppy disk image to a physical disk the other day, and my home-made imaging tool was refusing to work.  Once I got around to tracking this down, it turned out that IOCTL_DISK_GET_LENGTH_INFO simply doesn’t work on floppy disks, returning error code 1, ERROR_INVALID_FUNCTION, Incorrect Function.

This happens on both Windows XP and Windows 7, and presumably on other versions as well.  I suspect Microsoft would categorise this as a feature rather than a bug. 🙂

I’m not sure if this is the best workaround, but it’s what I came up with.  Note that IOCTL_DISK_GET_DRIVE_GEOMETRY_EX also doesn’t work for floppy disks.

I haven’t tested this with, e.g., ZIP disks, or with a wide range of USB memory sticks.  Feel free to copy-and-paste this code segment into your own project if it will help, but it comes without any warranty, express or implied.

if (!DeviceIoControl
 (
  houtput,
  IOCTL_DISK_GET_DRIVE_GEOMETRY,
  NULL,
  0,
  &target_diskgeometry,
  sizeof(target_diskgeometry),
  &byte_count,
  NULL
 ))
{
 err = GetLastError();
 fprintf(stderr, "Error %u getting output device geometry.\n", err);
 return err;
}

switch (target_diskgeometry.MediaType)
{
case Unknown:
case RemovableMedia:
case FixedMedia:

 if (!DeviceIoControl
  (
   houtput,
   IOCTL_DISK_GET_LENGTH_INFO,
   NULL,
   0,
   &target_disklength,
   sizeof(target_disklength),
   &byte_count,
   NULL
  ))
 {
  err = GetLastError();
  fprintf(stderr, "Error %u getting output device length.\n", err);
  return err;
 }

 fprintf(stderr, "Output disk has %I64i bytes.\n\n", target_disklength.Length.QuadPart);
 break;

default:

 target_disklength.Length.QuadPart =
  target_diskgeometry.Cylinders.QuadPart *
  target_diskgeometry.TracksPerCylinder *
  target_diskgeometry.SectorsPerTrack *
  target_diskgeometry.BytesPerSector;

 fprintf(stderr,
  "\n"
  "Output device appears to be a floppy disk.  WARNING: if this is not a\n"
  "floppy disk the calculated output device size is probably incorrect,\n"
  "which might result in an incomplete copy.\n"
  "\n"
  "Output disk has %I64i bytes.\n"
  "\n",
  target_disklength.Length.QuadPart);

 break;
}

Hope this helps.

Addendum: note that the figures returned by IOCTL_DISK_GET_DRIVE_GEOMETRY don’t give you the correct device length for hard disk drives, so that’s why this code uses IOCTL_DISK_GET_LENGTH_INFO unless the device is a floppy disk.

Hard Links Aren’t The Same As Shortcuts

December 29, 2009

I was recently pointed to this interesting article/blog on TechRepublic, which talks about the WinSxS folder in Windows Vista.

Mr. Detwiler quotes Joseph Conway, Senior Support Escalation Engineer at Microsoft, as saying that other files in the system are hard links to files in the WinSxS folder, and Michael Beck, a Microsoft program manager, as saying that the files in the WinSxS folder are hard links to files elsewhere in the system.  Bill then adds: “Luckily, this dichotomy has no impact on our efforts to reduce the size of the WinSxS folder.”

In fact, there is no dichotomy: the two statements are just different ways of saying the same thing, because hard links are symmetric – when you create a hard link, what you are really doing you are creating a second directory entry for an existing file.  This directory entry is otherwise perfectly normal, and there is no difference between it and the original one.  In fact, there isn’t even any way to tell for sure which one (if either) is the original!

As a concrete if contrived example, suppose we wanted to create a single file but put it in two folders, c:\fred and c:\joe.  We could create the file in c:\fred and then put a hard link in c:\joe; we could create the file in c:\joe and put a hard link in c:\fred; or we could create the file in c:\alice, put hard links in both c:\fred and c:\joe, and then delete the original link from c:\alice.  (Note that when you “delete” a file with more than one directory entry, only the directory entry is removed.)

The key point here is that it doesn’t make any difference which of these options we choose, as the end result is exactly the same.  So whether we then say “the file in c:\fred is a hard link to the file in c:\joe” or “the file in c:\joe is a hard link to the file in c:\fred” is entirely a matter of taste, as both statements are equally valid.  Strictly speaking, all either statement means is that c:\fred\myfile and c:\joe\alsomyfile are two different names for the same file.

Incidentally, this is also true of hard links in Unix file systems.  In either case, hard links should not be confused with symbolic links (reparse points in NTFS) or with Windows Explorer shortcuts, both of which are quite distinct from their targets.