The usual disclaimers apply...this is what worked for me - if you try it and it goes wrong and you haven't taken the normal sensible precautions before embarking on an endeavour like this then please don't come crying to me.
Step 1 - Partition the new hard disk
I found it easiest to do this from Windows. I connected the new hard disk to the PC and created the partitions using the normal Disk Management tool. You will save yourself some trouble if you "match up" the partition numbers on the old and new disks (i.e. if your Windows partition is on partition #1 on the old disk, make sure it is on partition #1 on the new disk also). On some of the PCs there was a Dell diagnostics partition present (so the Windows partition was actually the second partition). More about this below.
Step 2 - Delete (or rename) the HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices key in the registry
Doing this now will save you a world of pain later on. The problem is that Windows maintains a mapping of volume IDs to drive letters under this registry key
Here, my new drive was mounted as drive N: when I partitioned it. If I do nothing now, Windows will remount it as drive N: (instead of C:) when I later boot from it, which won't end well. If I just zap this registry key, Windows will recreate it when it next boots (although it will have forgotten about what drive letters you liked for your USB keys etc.) I guess you could just delete the entries for C: and N:...I didn't try this.
Step 3 - Reboot into Linux
I variously used Fedora Core 8 and Knoppix 5.1.1...both contained the required NTFS tools and both worked perfectly. At this stage, I have both the old and the new drives attached to the PC. I did this with various combinations to attachment from direct PATA to USB-to-PATA or USB-to-SATA converters and they all worked perfectly.
Step 4 - Dell Diagnostics Partition
One of the candidates was a Dell PC and I wanted to preserve the Dell Diagnostics partition, partly because it is a good thing to have and partly - as I mentioned above - to keep my partition numbering consistent between the old and the new drives (which saves a bunch of trouble). I did this by using the gparted utility to create a new partition on the new disk, similar in size to the original (but rounded up to an even cylinder boundary) with a system ID of 'de' (copied from the original). Then I simply did a "dump" sector-by-sector copy of the diagnostics partition from the old to the new:-
# dd if=/dev/sda1 of=/dev/sdb1 bs=32768
This worked a treat. I could then recreate my NTFS partition (again using gparted) as the second partition on the drive. It may seem that this rather wastes the effort of partitioning the disk in Step 1 above, but by doing it this way the standard Microsoft boot code is installed in the MBR. Of course, there are lots of other ways the same thing could be achieved, such as copying the MBR from the original disk to the new disk using the command
# dd if=/dev/sda of=/dev/sdb bs=512 count=1
...and then using gparted to resize the partitions accordingly. Either way, be very careful. If you manage to zap the partition table on your original disk at this stage you are going to have a seriously bad day !
The fun isn't over yet...see below !
Step 5 - Clone the NTFS parition
The next step is to clone the contents of the old NTFS partition into the new one. This is done using the aptly-named ntflsclone command:-
# ntfsclone -O /dev/sdb2 /dev/sda2
In this form, the command clones /dev/sda2 to /dev/sdb2. Once again, be careful. This command doesn't ask for any confirmation and if you get your partitions mixed up (e.g. specify them the wrong way around) it will hurt.
Step 6 - Resize the partition
At this point, all of the data is copied from the old disk to the new disk, but the filesystem on the new disk still "thinks" it is the same size as it was on the old disk. If you just reboot at this point you will find - to your dismay - that the new filesystem is no bigger than the old one, even though the partition containing the filesystem is bigger.
To fix this, we run ntfsresize on the new partition
# ntfsresize /dev/sdb2
Step 7 - Fix the number of "hidden sectors" in the NTFS Boot Sector
If the new NTFS partition doesn't start on the same sector number as the old one, you will need to adjust the number of "hidden sectors" recorded at offset 0x1C in the NTFS boot sector.
TODO: Describe using "hexedit" to complete this job
I did it a different way (kind of by accident). I wound up booting from the Windows Vista installation DVD and selecting "Repair". This located and repaired the incorrect boot sector for me automatically.
Step 8 - Insert the new disk and reboot
All going well, it will boot up exactly as before - except possibly faster - and you will miraculously have lots of available space
Step 9 - Defragment
If your original disk was heavily fragmented (which it probably was if you were running close to capacity for a good while), then the copy is still heavily fragmented. Now would be an excellent time to defragment the new partition.
In the course of my research I came across a promising tool called XXCLONE. This works a different way, being file-oriented rather than sector/block-oriented. Apparently, it copies individual files from the old to the new. As an experiment, I cloned one of the PCs using this tool rather than using the procedure described above. Initially all seemed well...I could boot from it and everything appeared to work OK. However, a few days later I was trying to install Microsoft.NET Framework 3.5 and found that it simply would not install. I can't be certain that the problem was with the method used to clone the disk, but when I went back and recloned using the Linux tools I could then install the same .NET Framework without any problems. If the problem was caused by XXCLONE it is a pity...it is very elegant and simple to use. I have sent some feedback to the developers...hopefully it will be helpful to them.
I can't claim to have worked all of this out from scratch by myself. The most useful online guide I found was Michael Dominok's at http://www.dominok.net/en/it/en.it.clonexp.html.