| 0 |      1 | /*
 | 
|  |      2 | * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
 | 
|  |      3 | * All rights reserved.
 | 
|  |      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".
 | 
|  |      8 | *
 | 
|  |      9 | * Initial Contributors:
 | 
|  |     10 | * Nokia Corporation - initial contribution.
 | 
|  |     11 | *
 | 
|  |     12 | * Contributors:
 | 
|  |     13 | *
 | 
|  |     14 | * Description:
 | 
|  |     15 | *
 | 
|  |     16 | */
 | 
|  |     17 | //
 | 
|  |     18 | // MbrUtil.cpp
 | 
|  |     19 | //
 | 
|  |     20 | 
 | 
|  |     21 | 
 | 
|  |     22 | #define _WIN32_WINNT 0x0400
 | 
|  |     23 | #include <windows.h>
 | 
|  |     24 | 
 | 
|  |     25 | #pragma warning (disable:4201) // warning C4201: nonstandard extension used : nameless struct/union
 | 
|  |     26 | #include <winioctl.h>
 | 
|  |     27 | 
 | 
|  |     28 | #include <stdio.h>
 | 
|  |     29 | 
 | 
|  |     30 | 
 | 
|  |     31 | const int KSectorSize = 512;
 | 
|  |     32 | BYTE TheBuffer[KSectorSize];
 | 
|  |     33 | 
 | 
|  |     34 | template <class T>
 | 
|  |     35 | T Min(T aLeft,T aRight)
 | 
|  |     36 | 	{return(aLeft<aRight ? aLeft : aRight);}
 | 
|  |     37 | 
 | 
|  |     38 | 
 | 
|  |     39 | 
 | 
|  |     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;
 | 
|  |     56 | 
 | 
|  |     57 | const unsigned char KBootIndicatorBootable=0x80;
 | 
|  |     58 | 
 | 
|  |     59 | const int KDiskSectorSize = 512;
 | 
|  |     60 | const int KDiskSectorSizeLog2 = 9;
 | 
|  |     61 | 
 | 
|  |     62 | const int KMegaByte = 0x100000;
 | 
|  |     63 | const int KMegaByteLog2 = 20;
 | 
|  |     64 | const int KMegaByteToSectorSizeShift = KMegaByteLog2 - KDiskSectorSizeLog2;
 | 
|  |     65 | const int KMegaByteInSectors = KMegaByte >> KMegaByteToSectorSizeShift;
 | 
|  |     66 | 
 | 
|  |     67 | const int KMaxPartitionEntries=0x4;
 | 
|  |     68 | const int KMBRFirstPartitionOffset=0x1BE;
 | 
|  |     69 | const int KMBRSignatureOffset=0x1FE;
 | 
|  |     70 | 
 | 
|  |     71 | inline BOOL PartitionIsFAT(unsigned char a)
 | 
|  |     72 | 	{
 | 
|  |     73 | 	return (
 | 
|  |     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
 | 
|  |     83 | 		);
 | 
|  |     84 | 	}
 | 
|  |     85 | 
 | 
|  |     86 | inline BOOL PartitionIsFAT32(unsigned char a)
 | 
|  |     87 | 	{
 | 
|  |     88 | 	return (
 | 
|  |     89 | 		a==KPartitionTypeWin95FAT32					||
 | 
|  |     90 | 		a==KPartitionTypeWin95FAT32LBA				||
 | 
|  |     91 | 		a==KPartitionTypeHiddenWin95FAT32			||
 | 
|  |     92 | 		a==KPartitionTypeHiddenWin95FAT32LBA
 | 
|  |     93 | 		);
 | 
|  |     94 | 	}
 | 
|  |     95 | 
 | 
|  |     96 | inline BOOL PartitionIsNTFS(unsigned char a)
 | 
|  |     97 | 	{
 | 
|  |     98 | 	return (
 | 
|  |     99 | 		a==KPartitionTypeNTFS						||
 | 
|  |    100 | 		a==KPartitionTypeHiddenNTFS
 | 
|  |    101 | 		);
 | 
|  |    102 | 	}
 | 
|  |    103 | 
 | 
|  |    104 | class TMBRPartitionEntry
 | 
|  |    105 | 	{
 | 
|  |    106 | public:
 | 
|  |    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)); }
 | 
|  |    115 | public:
 | 
|  |    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;
 | 
|  |    124 | 	DWORD iFirstSector;
 | 
|  |    125 | 	DWORD iNumSectors;
 | 
|  |    126 | 	};
 | 
|  |    127 | 
 | 
|  |    128 | 
 | 
|  |    129 | char* GetPartitionType(unsigned char aType)
 | 
|  |    130 | 	{
 | 
|  |    131 | 	switch (aType)
 | 
|  |    132 | 		{
 | 
|  |    133 | 		case KPartitionTypeFAT12: return "FAT12";
 | 
|  |    134 | 		case KPartitionTypeFAT16: return "FAT16";
 | 
|  |    135 | 		case KPartitionTypeFAT16small: return "FAT16";
 | 
|  |    136 | 		case KPartitionTypeWin95FAT32: return "FAT32";
 | 
|  |    137 | 		default:
 | 
|  |    138 | 			return "????";
 | 
|  |    139 | 
 | 
|  |    140 | 		}
 | 
|  |    141 | 	}
 | 
|  |    142 | 
 | 
|  |    143 | void ReadMbr(unsigned char* aMbrBuf, int aDiskSizeInSectors, BOOL aHexDump)
 | 
|  |    144 | 	{
 | 
|  |    145 | //	printf("Reading MBR...\n");
 | 
|  |    146 | 	if (aHexDump)
 | 
|  |    147 | 		{
 | 
|  |    148 | 		int n;
 | 
|  |    149 | 		for (n=0; n<KDiskSectorSize; n+=16)
 | 
|  |    150 | 			{
 | 
|  |    151 | 			printf("%08X : %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
 | 
|  |    152 | 				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]);
 | 
|  |    155 | 			}
 | 
|  |    156 | 		}
 | 
|  |    157 | 
 | 
|  |    158 | 
 | 
|  |    159 | 
 | 
|  |    160 | 	if ((aMbrBuf[KMBRSignatureOffset+0] != 0x55) ||
 | 
|  |    161 | 		(aMbrBuf[KMBRSignatureOffset+1] != 0xAA))
 | 
|  |    162 | 		{
 | 
|  |    163 | 		printf("No valid MBR\n");
 | 
|  |    164 | 		return;
 | 
|  |    165 | 		}
 | 
|  |    166 | 
 | 
|  |    167 | 	int i;
 | 
|  |    168 | 	TMBRPartitionEntry *pe;
 | 
|  |    169 | 	for (i=0, pe = (TMBRPartitionEntry*)(&aMbrBuf[KMBRFirstPartitionOffset]); i < KMaxPartitionEntries && pe->iPartitionType != 0; i++, pe++)
 | 
|  |    170 | 		{
 | 
|  |    171 | 		if (pe->iFirstSector + pe->iNumSectors > (DWORD) aDiskSizeInSectors)
 | 
|  |    172 | 			{
 | 
|  |    173 | 			printf("No valid MBR\n");
 | 
|  |    174 | 			return;
 | 
|  |    175 | 			}
 | 
|  |    176 | 		}
 | 
|  |    177 | 		
 | 
|  |    178 | 	printf("Partitions: \n");
 | 
|  |    179 | 	printf("  #  Name  Type Fat BtI Hed Sct Cyl Hed Sct Cyl  FirstSect NumSectors\n");
 | 
|  |    180 | 	
 | 
|  |    181 | 	for (i=0, pe = (TMBRPartitionEntry*)(&aMbrBuf[KMBRFirstPartitionOffset]); i < KMaxPartitionEntries && pe->iPartitionType != 0; i++, pe++)
 | 
|  |    182 | 		{
 | 
|  |    183 | 		char* partitionName = GetPartitionType(pe->iPartitionType);
 | 
|  |    184 | 		printf("%3d: %-6s %3u %3u %3u %3u %3u %3u %3u %3u %3u %10u %10u (%u MB)\n", 
 | 
|  |    185 | 			i,
 | 
|  |    186 | 			partitionName,
 | 
|  |    187 | 			pe->iPartitionType,
 | 
|  |    188 | 			pe->IsValidDosPartition() || pe->IsValidFAT32Partition() ? 1 : 0,
 | 
|  |    189 | 			pe->iX86BootIndicator,
 | 
|  |    190 | 			pe->iStartHead,
 | 
|  |    191 | 			pe->iStartSector,
 | 
|  |    192 | 			pe->iStartCylinder,
 | 
|  |    193 | 			pe->iEndHead,
 | 
|  |    194 | 			pe->iEndSector,
 | 
|  |    195 | 			pe->iEndCylinder,
 | 
|  |    196 | 			pe->iFirstSector,
 | 
|  |    197 | 			pe->iNumSectors,
 | 
|  |    198 | 			pe->iNumSectors >> KMegaByteToSectorSizeShift);
 | 
|  |    199 | 
 | 
|  |    200 | 		if (pe->iPartitionType == KPartitionTypeHiddenNTFS)
 | 
|  |    201 | 			{
 | 
|  |    202 | 			printf("Drive contains an NTFS partition, aborting for safety\n");
 | 
|  |    203 | 			return;
 | 
|  |    204 | 			}
 | 
|  |    205 | 		}
 | 
|  |    206 | 	}
 | 
|  |    207 | 
 | 
|  |    208 | 
 | 
|  |    209 | BOOL WriteMbr(unsigned char* aMbrBuf, int aFatSectorCount)
 | 
|  |    210 | 	{
 | 
|  |    211 | 	TMBRPartitionEntry *pe=(TMBRPartitionEntry*)(&aMbrBuf[KMBRFirstPartitionOffset]);
 | 
|  |    212 | 
 | 
|  |    213 | 	// first partition starts at one MB
 | 
|  |    214 | 	int sectorStart = KMegaByteInSectors;
 | 
|  |    215 | 
 | 
|  |    216 | 	// Create FAT partition
 | 
|  |    217 | 	pe->iFirstSector = sectorStart;
 | 
|  |    218 | 
 | 
|  |    219 | 
 | 
|  |    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;
 | 
|  |    228 | 	else
 | 
|  |    229 | 		pe->iPartitionType = KPartitionTypeWin95FAT32;
 | 
|  |    230 | 	sectorStart+= pe->iNumSectors;
 | 
|  |    231 | 
 | 
|  |    232 | 	aMbrBuf[KMBRSignatureOffset+0] = 0x55;
 | 
|  |    233 | 	aMbrBuf[KMBRSignatureOffset+1] = 0xAA;
 | 
|  |    234 | 
 | 
|  |    235 | 	return true;
 | 
|  |    236 | 	}
 | 
|  |    237 | 
 | 
|  |    238 | 
 | 
|  |    239 | int main(int argc,char *argv[])
 | 
|  |    240 | 	{
 | 
|  |    241 | 
 | 
|  |    242 | 	if (argc < 2)
 | 
|  |    243 | 		{
 | 
|  |    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");
 | 
|  |    246 | 		printf("Where  :\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");
 | 
|  |    251 | 		exit(0);
 | 
|  |    252 | 		}
 | 
|  |    253 | 
 | 
|  |    254 | 	bool writeMbr = false;
 | 
|  |    255 | 	bool eraseMbr = false;
 | 
|  |    256 | 	int fatSectorCount = 0;
 | 
|  |    257 | 	char* fatType = "FAT";
 | 
|  |    258 | 
 | 
|  |    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'))
 | 
|  |    263 | 		{
 | 
|  |    264 | 		printf("invalid drive letter");
 | 
|  |    265 | 		exit(4);
 | 
|  |    266 | 		}
 | 
|  |    267 | 
 | 
|  |    268 | 	for (int i=2; i<argc; i++)
 | 
|  |    269 | 		{
 | 
|  |    270 | 		if (strcmpi(argv[i], "-e") == 0)
 | 
|  |    271 | 			{
 | 
|  |    272 | 			eraseMbr = true;
 | 
|  |    273 | 			}
 | 
|  |    274 | 		else if (strcmpi(argv[i], "-w") == 0)
 | 
|  |    275 | 			{
 | 
|  |    276 | 			writeMbr = true;
 | 
|  |    277 | 			i++;
 | 
|  |    278 | 			if (i >= argc)
 | 
|  |    279 | 				{
 | 
|  |    280 | 				printf("no drive size specified");
 | 
|  |    281 | 				exit(4);
 | 
|  |    282 | 				}
 | 
|  |    283 | 			int fatSizeInMegabytes = atoi(argv[i]);
 | 
|  |    284 | 			fatSectorCount = fatSizeInMegabytes << KMegaByteToSectorSizeShift;
 | 
|  |    285 | //			printf("fatSizeInMegabytes %d, fatSectorCount %d\n", fatSizeInMegabytes, fatSectorCount);
 | 
|  |    286 | 			}
 | 
|  |    287 | 		else if (strcmpi(argv[i], "FAT") == 0)
 | 
|  |    288 | 			{
 | 
|  |    289 | 			}
 | 
|  |    290 | 		else if (strcmpi(argv[i], "FAT32") == 0)
 | 
|  |    291 | 			{
 | 
|  |    292 | 			fatType = argv[i];
 | 
|  |    293 | 			}
 | 
|  |    294 | 		else
 | 
|  |    295 | 			{
 | 
|  |    296 | 			printf("invalid option");
 | 
|  |    297 | 			exit(4);
 | 
|  |    298 | 			}
 | 
|  |    299 | 		}
 | 
|  |    300 | 
 | 
|  |    301 | 
 | 
|  |    302 | 	char diskName[10] = "\\\\.\\?:";
 | 
|  |    303 | 	diskName[4] = driveLetter;
 | 
|  |    304 | 	char physDiskName[20] = "\\\\.\\PHYSICALDRIVE?";
 | 
|  |    305 | 
 | 
|  |    306 | 
 | 
|  |    307 | 
 | 
|  |    308 | 	DISK_GEOMETRY geometry;
 | 
|  |    309 | 	DWORD dummy;
 | 
|  |    310 | 	HANDLE logDeviceHandle;
 | 
|  |    311 | 	HANDLE physDeviceHandle;
 | 
|  |    312 | 	BOOL b;
 | 
|  |    313 | 	DWORD bytesRead;    
 | 
|  |    314 | 	DWORD bytesWritten;
 | 
|  |    315 | 	DWORD dwRet;
 | 
|  |    316 | 
 | 
|  |    317 | 	//*****************************************************************************************
 | 
|  |    318 | 	// open logical drive...
 | 
|  |    319 | 	//*****************************************************************************************
 | 
|  |    320 | 	printf("Opening %s...\n", diskName);
 | 
|  |    321 | 	logDeviceHandle = CreateFileA(
 | 
|  |    322 | 		diskName, 
 | 
|  |    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) 
 | 
|  |    326 | 		{
 | 
|  |    327 | 		printf("CreateFileA() returned INVALID_HANDLE_VALUE\n");
 | 
|  |    328 | 		exit(4);
 | 
|  |    329 | 		}
 | 
|  |    330 | 
 | 
|  |    331 | 	// query geometry
 | 
|  |    332 | 	b = DeviceIoControl(
 | 
|  |    333 | 			logDeviceHandle, 
 | 
|  |    334 | 			IOCTL_DISK_GET_DRIVE_GEOMETRY, 
 | 
|  |    335 | 			NULL, 
 | 
|  |    336 | 			0, 
 | 
|  |    337 | 			&geometry, 
 | 
|  |    338 | 			sizeof(geometry), 
 | 
|  |    339 | 			&dummy, 
 | 
|  |    340 | 			(LPOVERLAPPED)NULL);
 | 
|  |    341 | 	if (!b)
 | 
|  |    342 | 		{
 | 
|  |    343 | 		printf("IOCTL_DISK_GET_DRIVE_GEOMETRY failed error %x", GetLastError());
 | 
|  |    344 | 		CloseHandle(logDeviceHandle);
 | 
|  |    345 | 		exit(4);
 | 
|  |    346 | 		}
 | 
|  |    347 | 	
 | 
|  |    348 | 	LONGLONG diskSizeInBytes = geometry.Cylinders.QuadPart * geometry.TracksPerCylinder * geometry.SectorsPerTrack * KDiskSectorSize;
 | 
|  |    349 | 	int diskSizeInMegaBytes = (int) (diskSizeInBytes / KMegaByte);
 | 
|  |    350 | 	int diskSizeInSectors = (int) (diskSizeInBytes / KDiskSectorSize);
 | 
|  |    351 | 
 | 
|  |    352 | 
 | 
|  |    353 | 	printf("Drive %c MediaType: %d (%s). Size: %ld MBytes, %lu sectors\n", 
 | 
|  |    354 | 		driveLetter, 
 | 
|  |    355 | 		geometry.MediaType,
 | 
|  |    356 | 		geometry.MediaType==RemovableMedia ? "RemovableMedia" :
 | 
|  |    357 | 			geometry.MediaType==FixedMedia ? "FixedMedia" : "?",
 | 
|  |    358 | 		diskSizeInMegaBytes,
 | 
|  |    359 | 		diskSizeInSectors
 | 
|  |    360 | 		);
 | 
|  |    361 | //	printf("Size: %llu sectors\n", diskSizeInSectors);
 | 
|  |    362 | 
 | 
|  |    363 | 	if (geometry.MediaType != RemovableMedia)
 | 
|  |    364 | 		{
 | 
|  |    365 | 		printf("Drive is not removable, exiting");
 | 
|  |    366 | 		CloseHandle(logDeviceHandle);
 | 
|  |    367 | 		exit(4);
 | 
|  |    368 | 		}
 | 
|  |    369 | 
 | 
|  |    370 | 	if (fatSectorCount + KMegaByteInSectors > diskSizeInSectors)
 | 
|  |    371 | 		{
 | 
|  |    372 | 		printf("Specified size is too big");
 | 
|  |    373 | 		CloseHandle(logDeviceHandle);
 | 
|  |    374 | 		exit(4);
 | 
|  |    375 | 		}
 | 
|  |    376 | 
 | 
|  |    377 | 	//*****************************************************************************************
 | 
|  |    378 | 	// Get physical device number
 | 
|  |    379 | 	//*****************************************************************************************
 | 
|  |    380 | 	STORAGE_DEVICE_NUMBER storageDeviceNumber;
 | 
|  |    381 | 	b = IOCTL_STORAGE_GET_DEVICE_NUMBER;
 | 
|  |    382 | 	b = DeviceIoControl(
 | 
|  |    383 | 		  logDeviceHandle,
 | 
|  |    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);
 | 
|  |    386 | 	if (!b)
 | 
|  |    387 | 		{
 | 
|  |    388 | 		printf("IOCTL_STORAGE_GET_DEVICE_NUMBER failed error %x", GetLastError());
 | 
|  |    389 | 		CloseHandle(logDeviceHandle);
 | 
|  |    390 | 		exit(4);
 | 
|  |    391 | 		}
 | 
|  |    392 | 
 | 
|  |    393 | 
 | 
|  |    394 | 
 | 
|  |    395 | 	//*****************************************************************************************
 | 
|  |    396 | 	// open physical drive...
 | 
|  |    397 | 	//*****************************************************************************************
 | 
|  |    398 | 	physDiskName[strlen(physDiskName)-1] = (char) ('0' + storageDeviceNumber.DeviceNumber);
 | 
|  |    399 | 
 | 
|  |    400 | 	printf("Opening %s...\n", physDiskName);
 | 
|  |    401 | 	physDeviceHandle = CreateFileA(
 | 
|  |    402 | 		physDiskName, 
 | 
|  |    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) 
 | 
|  |    406 | 		{
 | 
|  |    407 | 		printf("CreateFileA() returned INVALID_HANDLE_VALUE\n");
 | 
|  |    408 | 		exit(4);
 | 
|  |    409 | 		}
 | 
|  |    410 | 
 | 
|  |    411 | 
 | 
|  |    412 | 
 | 
|  |    413 | 
 | 
|  |    414 | 	//*******************************************************
 | 
|  |    415 | 	// Read first sector
 | 
|  |    416 | 	//*******************************************************
 | 
|  |    417 | 	dwRet = SetFilePointer(
 | 
|  |    418 | 		physDeviceHandle, 0, 0, FILE_BEGIN);
 | 
|  |    419 | 	if (dwRet != 0)
 | 
|  |    420 | 		{
 | 
|  |    421 | 		printf("Unable to set file pointer, exiting");
 | 
|  |    422 | 		CloseHandle(physDeviceHandle);
 | 
|  |    423 | 		CloseHandle(logDeviceHandle);
 | 
|  |    424 | 		exit(4);
 | 
|  |    425 | 		}
 | 
|  |    426 | 	if (!ReadFile (physDeviceHandle, TheBuffer, KSectorSize, &bytesRead, NULL) )
 | 
|  |    427 | 		{
 | 
|  |    428 | 		printf("ReadFile failed with %d", GetLastError());
 | 
|  |    429 | 		CloseHandle(physDeviceHandle);
 | 
|  |    430 | 		CloseHandle(logDeviceHandle);
 | 
|  |    431 | 		exit(4);
 | 
|  |    432 | 		}
 | 
|  |    433 | 	if(bytesRead != KSectorSize)
 | 
|  |    434 | 		{
 | 
|  |    435 | 		printf("ReadFile length too small: %d", bytesRead);
 | 
|  |    436 | 		CloseHandle(physDeviceHandle);
 | 
|  |    437 | 		CloseHandle(logDeviceHandle);
 | 
|  |    438 | 		exit(4);
 | 
|  |    439 | 		}
 | 
|  |    440 | 
 | 
|  |    441 | 	//*******************************************************
 | 
|  |    442 | 	// Interpret MBR
 | 
|  |    443 | 	//*******************************************************
 | 
|  |    444 | 	ReadMbr(TheBuffer, diskSizeInSectors, false);
 | 
|  |    445 | 	
 | 
|  |    446 | 	//*******************************************************
 | 
|  |    447 | 	// Write new MBR
 | 
|  |    448 | 	//*******************************************************
 | 
|  |    449 | 	if (writeMbr)
 | 
|  |    450 | 		{
 | 
|  |    451 | 		printf("Writing MBR...\n");
 | 
|  |    452 | 		memset(TheBuffer, 0, sizeof(TheBuffer));
 | 
|  |    453 | 		b = WriteMbr(TheBuffer, fatSectorCount);
 | 
|  |    454 | 		if (!b)
 | 
|  |    455 | 			writeMbr = eraseMbr = false;
 | 
|  |    456 | 		}
 | 
|  |    457 | 	if (eraseMbr)
 | 
|  |    458 | 		{
 | 
|  |    459 | 		printf("Erasing MBR...\n");
 | 
|  |    460 | 		memset(TheBuffer, 0, sizeof(TheBuffer));
 | 
|  |    461 | 		}
 | 
|  |    462 | 	if (writeMbr || eraseMbr)
 | 
|  |    463 | 		{
 | 
|  |    464 | 		// Write first sector
 | 
|  |    465 | 		dwRet = SetFilePointer(
 | 
|  |    466 | 			physDeviceHandle, 0, 0, FILE_BEGIN);
 | 
|  |    467 | 		if (dwRet != 0)
 | 
|  |    468 | 			{
 | 
|  |    469 | 			printf("Unable to set file pointer, exiting");
 | 
|  |    470 | 			CloseHandle(physDeviceHandle);
 | 
|  |    471 | 			CloseHandle(logDeviceHandle);
 | 
|  |    472 | 			exit(4);
 | 
|  |    473 | 			}
 | 
|  |    474 | 		if (!WriteFile (physDeviceHandle, TheBuffer, KSectorSize, &bytesWritten, NULL) )
 | 
|  |    475 | 			{
 | 
|  |    476 | 			printf("WriteFile failed with %d", GetLastError());
 | 
|  |    477 | 			CloseHandle(physDeviceHandle);
 | 
|  |    478 | 			CloseHandle(logDeviceHandle);
 | 
|  |    479 | 			exit(4);
 | 
|  |    480 | 			}
 | 
|  |    481 | 		if(bytesWritten != KSectorSize)
 | 
|  |    482 | 			{
 | 
|  |    483 | 			printf("WriteFile length too small: %d", bytesWritten);
 | 
|  |    484 | 			CloseHandle(physDeviceHandle);
 | 
|  |    485 | 			CloseHandle(logDeviceHandle);
 | 
|  |    486 | 			exit(4);
 | 
|  |    487 | 			}
 | 
|  |    488 | 		if (writeMbr)
 | 
|  |    489 | 			ReadMbr(TheBuffer, diskSizeInSectors, false);
 | 
|  |    490 | 		}
 | 
|  |    491 | 
 | 
|  |    492 | 	
 | 
|  |    493 | 	CloseHandle(physDeviceHandle);
 | 
|  |    494 | 
 | 
|  |    495 | 
 | 
|  |    496 | 	if (writeMbr || eraseMbr)
 | 
|  |    497 | 		{
 | 
|  |    498 | 		printf("Dismounting %s...\n", diskName);
 | 
|  |    499 | 		b = DeviceIoControl(
 | 
|  |    500 | 		  logDeviceHandle,
 | 
|  |    501 | 		  FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &bytesRead, 0);
 | 
|  |    502 | 		if (!b)
 | 
|  |    503 | 			printf("FSCTL_DISMOUNT_VOLUME b %d err %d\n", b, GetLastError());
 | 
|  |    504 | 		}
 | 
|  |    505 | 
 | 
|  |    506 | 	CloseHandle(logDeviceHandle);
 | 
|  |    507 | 	
 | 
|  |    508 | 	//*******************************************************
 | 
|  |    509 | 	// Format the disk
 | 
|  |    510 | 	//*******************************************************
 | 
|  |    511 | 	if (writeMbr || eraseMbr)
 | 
|  |    512 | 		{
 | 
|  |    513 | 		printf("\n");
 | 
|  |    514 | 		char prompt[80];
 | 
|  |    515 | 		sprintf(prompt, "Eject card from drive %C: and press ENTER when ready...\n", driveLetter);
 | 
|  |    516 | 		printf(prompt);
 | 
|  |    517 | 		getchar();
 | 
|  |    518 | 
 | 
|  |    519 | 		char winCmd[1024];
 | 
|  |    520 | 		char cmdArgs[1024];
 | 
|  |    521 | 		STARTUPINFO si = {0,};
 | 
|  |    522 | 		PROCESS_INFORMATION pi;
 | 
|  |    523 | 
 | 
|  |    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);
 | 
|  |    528 | 		b = CreateProcessA(
 | 
|  |    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
 | 
|  |    539 | 		if (!b)
 | 
|  |    540 | 			printf("CreateProcess failed with %d", GetLastError());
 | 
|  |    541 | 
 | 
|  |    542 | 		dwRet = WaitForSingleObject(pi.hProcess, INFINITE);
 | 
|  |    543 | 		CloseHandle(pi.hThread);
 | 
|  |    544 | 		CloseHandle(pi.hProcess);
 | 
|  |    545 | 
 | 
|  |    546 | 		}
 | 
|  |    547 | 
 | 
|  |    548 | 	return 0;
 | 
|  |    549 | 	} |