Update contrib.
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of the License "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
22 #define _WIN32_WINNT 0x0400
25 #pragma warning (disable:4201) // warning C4201: nonstandard extension used : nameless struct/union
31 const int KSectorSize = 512;
32 BYTE TheBuffer[KSectorSize];
35 T Min(T aLeft,T aRight)
36 {return(aLeft<aRight ? aLeft : aRight);}
40 const unsigned char KPartitionTypeEmpty=0x00;
41 const unsigned char KPartitionTypeFAT12=0x01;
42 const unsigned char KPartitionTypeFAT16small=0x04;
43 const unsigned char KPartitionTypeFAT16=0x06;
44 const unsigned char KPartitionTypeNTFS=0x07;
45 const unsigned char KPartitionTypeWin95FAT32=0x0b;
46 const unsigned char KPartitionTypeWin95FAT32LBA=0x0c;
47 const unsigned char KPartitionTypeWin95FAT16LBA=0x0e;
48 const unsigned char KPartitionTypeWin95ExtdLBA=0x0f;
49 const unsigned char KPartitionTypeHiddenFAT12=0x11;
50 const unsigned char KPartitionTypeHiddenFAT16small=0x14;
51 const unsigned char KPartitionTypeHiddenFAT16=0x16;
52 const unsigned char KPartitionTypeHiddenNTFS=0x17;
53 const unsigned char KPartitionTypeHiddenWin95FAT32=0x1b;
54 const unsigned char KPartitionTypeHiddenWin95FAT32LBA=0x1c;
55 const unsigned char KPartitionTypeHiddenWin95FAT16LBA=0x1e;
57 const unsigned char KBootIndicatorBootable=0x80;
59 const int KDiskSectorSize = 512;
60 const int KDiskSectorSizeLog2 = 9;
62 const int KMegaByte = 0x100000;
63 const int KMegaByteLog2 = 20;
64 const int KMegaByteToSectorSizeShift = KMegaByteLog2 - KDiskSectorSizeLog2;
65 const int KMegaByteInSectors = KMegaByte >> KMegaByteToSectorSizeShift;
67 const int KMaxPartitionEntries=0x4;
68 const int KMBRFirstPartitionOffset=0x1BE;
69 const int KMBRSignatureOffset=0x1FE;
71 inline BOOL PartitionIsFAT(unsigned char a)
74 a==KPartitionTypeFAT12 ||
75 a==KPartitionTypeFAT16small ||
76 a==KPartitionTypeFAT16 ||
77 a==KPartitionTypeFAT16 ||
78 a==KPartitionTypeWin95FAT16LBA ||
79 a==KPartitionTypeHiddenFAT12 ||
80 a==KPartitionTypeHiddenFAT16small ||
81 a==KPartitionTypeHiddenFAT16 ||
82 a==KPartitionTypeHiddenWin95FAT16LBA
86 inline BOOL PartitionIsFAT32(unsigned char a)
89 a==KPartitionTypeWin95FAT32 ||
90 a==KPartitionTypeWin95FAT32LBA ||
91 a==KPartitionTypeHiddenWin95FAT32 ||
92 a==KPartitionTypeHiddenWin95FAT32LBA
96 inline BOOL PartitionIsNTFS(unsigned char a)
99 a==KPartitionTypeNTFS ||
100 a==KPartitionTypeHiddenNTFS
104 class TMBRPartitionEntry
107 BOOL IsValidPartition()
108 { return (iNumSectors>0 && iPartitionType!=KPartitionTypeEmpty); }
109 BOOL IsValidDosPartition()
110 { return (iNumSectors>0 && PartitionIsFAT(iPartitionType)); }
111 BOOL IsDefaultBootPartition()
112 { return(iX86BootIndicator==KBootIndicatorBootable && (IsValidDosPartition() || IsValidFAT32Partition())); }
113 BOOL IsValidFAT32Partition()
114 { return (iNumSectors>0 && PartitionIsFAT32(iPartitionType)); }
116 unsigned char iX86BootIndicator;
117 unsigned char iStartHead;
118 unsigned char iStartSector;
119 unsigned char iStartCylinder;
120 unsigned char iPartitionType;
121 unsigned char iEndHead;
122 unsigned char iEndSector;
123 unsigned char iEndCylinder;
129 char* GetPartitionType(unsigned char aType)
133 case KPartitionTypeFAT12: return "FAT12";
134 case KPartitionTypeFAT16: return "FAT16";
135 case KPartitionTypeFAT16small: return "FAT16";
136 case KPartitionTypeWin95FAT32: return "FAT32";
143 void ReadMbr(unsigned char* aMbrBuf, int aDiskSizeInSectors, BOOL aHexDump)
145 // printf("Reading MBR...\n");
149 for (n=0; n<KDiskSectorSize; n+=16)
151 printf("%08X : %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
153 aMbrBuf[n+0x00],aMbrBuf[n+0x01],aMbrBuf[n+0x02],aMbrBuf[n+0x03],aMbrBuf[n+0x04],aMbrBuf[n+0x05],aMbrBuf[n+0x06],aMbrBuf[n+0x07],
154 aMbrBuf[n+0x08],aMbrBuf[n+0x09],aMbrBuf[n+0x0A],aMbrBuf[n+0x0B],aMbrBuf[n+0x0C],aMbrBuf[n+0x0D],aMbrBuf[n+0x0E],aMbrBuf[n+0x0F]);
160 if ((aMbrBuf[KMBRSignatureOffset+0] != 0x55) ||
161 (aMbrBuf[KMBRSignatureOffset+1] != 0xAA))
163 printf("No valid MBR\n");
168 TMBRPartitionEntry *pe;
169 for (i=0, pe = (TMBRPartitionEntry*)(&aMbrBuf[KMBRFirstPartitionOffset]); i < KMaxPartitionEntries && pe->iPartitionType != 0; i++, pe++)
171 if (pe->iFirstSector + pe->iNumSectors > (DWORD) aDiskSizeInSectors)
173 printf("No valid MBR\n");
178 printf("Partitions: \n");
179 printf(" # Name Type Fat BtI Hed Sct Cyl Hed Sct Cyl FirstSect NumSectors\n");
181 for (i=0, pe = (TMBRPartitionEntry*)(&aMbrBuf[KMBRFirstPartitionOffset]); i < KMaxPartitionEntries && pe->iPartitionType != 0; i++, pe++)
183 char* partitionName = GetPartitionType(pe->iPartitionType);
184 printf("%3d: %-6s %3u %3u %3u %3u %3u %3u %3u %3u %3u %10u %10u (%u MB)\n",
188 pe->IsValidDosPartition() || pe->IsValidFAT32Partition() ? 1 : 0,
189 pe->iX86BootIndicator,
198 pe->iNumSectors >> KMegaByteToSectorSizeShift);
200 if (pe->iPartitionType == KPartitionTypeHiddenNTFS)
202 printf("Drive contains an NTFS partition, aborting for safety\n");
209 BOOL WriteMbr(unsigned char* aMbrBuf, int aFatSectorCount)
211 TMBRPartitionEntry *pe=(TMBRPartitionEntry*)(&aMbrBuf[KMBRFirstPartitionOffset]);
213 // first partition starts at one MB
214 int sectorStart = KMegaByteInSectors;
216 // Create FAT partition
217 pe->iFirstSector = sectorStart;
220 pe->iNumSectors = aFatSectorCount;
221 pe->iX86BootIndicator = 0x00;
222 if (pe->iNumSectors < 32680)
223 pe->iPartitionType = KPartitionTypeFAT12;
224 else if(pe->iNumSectors < 65536)
225 pe->iPartitionType = KPartitionTypeFAT16small;
226 else if (pe->iNumSectors < 1048576)
227 pe->iPartitionType = KPartitionTypeFAT16;
229 pe->iPartitionType = KPartitionTypeWin95FAT32;
230 sectorStart+= pe->iNumSectors;
232 aMbrBuf[KMBRSignatureOffset+0] = 0x55;
233 aMbrBuf[KMBRSignatureOffset+1] = 0xAA;
239 int main(int argc,char *argv[])
244 printf("MbrUtil - Decodes and optionally writes or erases the Master Boot Record on a removable drive\n");
245 printf("Syntax : MbrUtil <drive letter> [-e] [-w <FatSizeInMegabytes>] [FAT] [FAT32]\n");
247 printf("-e : erase Master Boot Record:\n");
248 printf("-w : create FAT partition of size <FatSizeInMegabytes>:\n");
249 printf("E.g. : MbrUtil f:\n");
250 printf(" : MbrUtil f: -w 16 FAT\n");
254 bool writeMbr = false;
255 bool eraseMbr = false;
256 int fatSectorCount = 0;
257 char* fatType = "FAT";
259 char driveLetter = (char) toupper(argv[1][0]);
260 if ((strlen(argv[1]) > 2) ||
261 (strlen(argv[1]) == 2 && argv[1][1] != ':') ||
262 (driveLetter < 'A' || driveLetter > 'Z'))
264 printf("invalid drive letter");
268 for (int i=2; i<argc; i++)
270 if (strcmpi(argv[i], "-e") == 0)
274 else if (strcmpi(argv[i], "-w") == 0)
280 printf("no drive size specified");
283 int fatSizeInMegabytes = atoi(argv[i]);
284 fatSectorCount = fatSizeInMegabytes << KMegaByteToSectorSizeShift;
285 // printf("fatSizeInMegabytes %d, fatSectorCount %d\n", fatSizeInMegabytes, fatSectorCount);
287 else if (strcmpi(argv[i], "FAT") == 0)
290 else if (strcmpi(argv[i], "FAT32") == 0)
296 printf("invalid option");
302 char diskName[10] = "\\\\.\\?:";
303 diskName[4] = driveLetter;
304 char physDiskName[20] = "\\\\.\\PHYSICALDRIVE?";
308 DISK_GEOMETRY geometry;
310 HANDLE logDeviceHandle;
311 HANDLE physDeviceHandle;
317 //*****************************************************************************************
318 // open logical drive...
319 //*****************************************************************************************
320 printf("Opening %s...\n", diskName);
321 logDeviceHandle = CreateFileA(
323 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE ,
324 NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, NULL);
325 if (logDeviceHandle == INVALID_HANDLE_VALUE)
327 printf("CreateFileA() returned INVALID_HANDLE_VALUE\n");
334 IOCTL_DISK_GET_DRIVE_GEOMETRY,
343 printf("IOCTL_DISK_GET_DRIVE_GEOMETRY failed error %x", GetLastError());
344 CloseHandle(logDeviceHandle);
348 LONGLONG diskSizeInBytes = geometry.Cylinders.QuadPart * geometry.TracksPerCylinder * geometry.SectorsPerTrack * KDiskSectorSize;
349 int diskSizeInMegaBytes = (int) (diskSizeInBytes / KMegaByte);
350 int diskSizeInSectors = (int) (diskSizeInBytes / KDiskSectorSize);
353 printf("Drive %c MediaType: %d (%s). Size: %ld MBytes, %lu sectors\n",
356 geometry.MediaType==RemovableMedia ? "RemovableMedia" :
357 geometry.MediaType==FixedMedia ? "FixedMedia" : "?",
361 // printf("Size: %llu sectors\n", diskSizeInSectors);
363 if (geometry.MediaType != RemovableMedia)
365 printf("Drive is not removable, exiting");
366 CloseHandle(logDeviceHandle);
370 if (fatSectorCount + KMegaByteInSectors > diskSizeInSectors)
372 printf("Specified size is too big");
373 CloseHandle(logDeviceHandle);
377 //*****************************************************************************************
378 // Get physical device number
379 //*****************************************************************************************
380 STORAGE_DEVICE_NUMBER storageDeviceNumber;
381 b = IOCTL_STORAGE_GET_DEVICE_NUMBER;
384 IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &storageDeviceNumber, sizeof(storageDeviceNumber), &bytesRead, 0);
385 // printf("IOCTL_STORAGE_GET_DEVICE_NUMBER b %d DeviceNumber %d\n", b, storageDeviceNumber.DeviceNumber);
388 printf("IOCTL_STORAGE_GET_DEVICE_NUMBER failed error %x", GetLastError());
389 CloseHandle(logDeviceHandle);
395 //*****************************************************************************************
396 // open physical drive...
397 //*****************************************************************************************
398 physDiskName[strlen(physDiskName)-1] = (char) ('0' + storageDeviceNumber.DeviceNumber);
400 printf("Opening %s...\n", physDiskName);
401 physDeviceHandle = CreateFileA(
403 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE ,
404 NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, NULL);
405 if (physDeviceHandle == INVALID_HANDLE_VALUE)
407 printf("CreateFileA() returned INVALID_HANDLE_VALUE\n");
414 //*******************************************************
416 //*******************************************************
417 dwRet = SetFilePointer(
418 physDeviceHandle, 0, 0, FILE_BEGIN);
421 printf("Unable to set file pointer, exiting");
422 CloseHandle(physDeviceHandle);
423 CloseHandle(logDeviceHandle);
426 if (!ReadFile (physDeviceHandle, TheBuffer, KSectorSize, &bytesRead, NULL) )
428 printf("ReadFile failed with %d", GetLastError());
429 CloseHandle(physDeviceHandle);
430 CloseHandle(logDeviceHandle);
433 if(bytesRead != KSectorSize)
435 printf("ReadFile length too small: %d", bytesRead);
436 CloseHandle(physDeviceHandle);
437 CloseHandle(logDeviceHandle);
441 //*******************************************************
443 //*******************************************************
444 ReadMbr(TheBuffer, diskSizeInSectors, false);
446 //*******************************************************
448 //*******************************************************
451 printf("Writing MBR...\n");
452 memset(TheBuffer, 0, sizeof(TheBuffer));
453 b = WriteMbr(TheBuffer, fatSectorCount);
455 writeMbr = eraseMbr = false;
459 printf("Erasing MBR...\n");
460 memset(TheBuffer, 0, sizeof(TheBuffer));
462 if (writeMbr || eraseMbr)
464 // Write first sector
465 dwRet = SetFilePointer(
466 physDeviceHandle, 0, 0, FILE_BEGIN);
469 printf("Unable to set file pointer, exiting");
470 CloseHandle(physDeviceHandle);
471 CloseHandle(logDeviceHandle);
474 if (!WriteFile (physDeviceHandle, TheBuffer, KSectorSize, &bytesWritten, NULL) )
476 printf("WriteFile failed with %d", GetLastError());
477 CloseHandle(physDeviceHandle);
478 CloseHandle(logDeviceHandle);
481 if(bytesWritten != KSectorSize)
483 printf("WriteFile length too small: %d", bytesWritten);
484 CloseHandle(physDeviceHandle);
485 CloseHandle(logDeviceHandle);
489 ReadMbr(TheBuffer, diskSizeInSectors, false);
493 CloseHandle(physDeviceHandle);
496 if (writeMbr || eraseMbr)
498 printf("Dismounting %s...\n", diskName);
501 FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &bytesRead, 0);
503 printf("FSCTL_DISMOUNT_VOLUME b %d err %d\n", b, GetLastError());
506 CloseHandle(logDeviceHandle);
508 //*******************************************************
510 //*******************************************************
511 if (writeMbr || eraseMbr)
515 sprintf(prompt, "Eject card from drive %C: and press ENTER when ready...\n", driveLetter);
521 STARTUPINFO si = {0,};
522 PROCESS_INFORMATION pi;
524 GetWindowsDirectory(winCmd, sizeof(winCmd));
525 strncat(winCmd, "\\system32\\cmd.exe", sizeof(winCmd));
526 sprintf(cmdArgs, "/C format %c: /FS:%s /Q /X", driveLetter, fatType);
527 printf("Executing : %s %s\n", winCmd, cmdArgs);
529 winCmd, //__in_opt LPCTSTR lpApplicationName,
530 cmdArgs, //__inout_opt LPTSTR lpCommandLine,
531 NULL, //__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
532 NULL, //__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
533 FALSE, //__in BOOL bInheritHandles,
534 0, //__in DWORD dwCreationFlags,
535 NULL, //__in_opt LPVOID lpEnvironment,
536 NULL, //__in_opt LPCTSTR lpCurrentDirectory,
537 &si, //__in LPSTARTUPINFO lpStartupInfo,
538 &pi); //__out LPPROCESS_INFORMATION lpProcessInformation
540 printf("CreateProcess failed with %d", GetLastError());
542 dwRet = WaitForSingleObject(pi.hProcess, INFINITE);
543 CloseHandle(pi.hThread);
544 CloseHandle(pi.hProcess);