sl@0: /* sl@0: * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * sl@0: */ sl@0: // sl@0: // MbrUtil.cpp sl@0: // sl@0: sl@0: sl@0: #define _WIN32_WINNT 0x0400 sl@0: #include sl@0: sl@0: #pragma warning (disable:4201) // warning C4201: nonstandard extension used : nameless struct/union sl@0: #include sl@0: sl@0: #include sl@0: sl@0: sl@0: const int KSectorSize = 512; sl@0: BYTE TheBuffer[KSectorSize]; sl@0: sl@0: template sl@0: T Min(T aLeft,T aRight) sl@0: {return(aLeft> KMegaByteToSectorSizeShift; sl@0: sl@0: const int KMaxPartitionEntries=0x4; sl@0: const int KMBRFirstPartitionOffset=0x1BE; sl@0: const int KMBRSignatureOffset=0x1FE; sl@0: sl@0: inline BOOL PartitionIsFAT(unsigned char a) sl@0: { sl@0: return ( sl@0: a==KPartitionTypeFAT12 || sl@0: a==KPartitionTypeFAT16small || sl@0: a==KPartitionTypeFAT16 || sl@0: a==KPartitionTypeFAT16 || sl@0: a==KPartitionTypeWin95FAT16LBA || sl@0: a==KPartitionTypeHiddenFAT12 || sl@0: a==KPartitionTypeHiddenFAT16small || sl@0: a==KPartitionTypeHiddenFAT16 || sl@0: a==KPartitionTypeHiddenWin95FAT16LBA sl@0: ); sl@0: } sl@0: sl@0: inline BOOL PartitionIsFAT32(unsigned char a) sl@0: { sl@0: return ( sl@0: a==KPartitionTypeWin95FAT32 || sl@0: a==KPartitionTypeWin95FAT32LBA || sl@0: a==KPartitionTypeHiddenWin95FAT32 || sl@0: a==KPartitionTypeHiddenWin95FAT32LBA sl@0: ); sl@0: } sl@0: sl@0: inline BOOL PartitionIsNTFS(unsigned char a) sl@0: { sl@0: return ( sl@0: a==KPartitionTypeNTFS || sl@0: a==KPartitionTypeHiddenNTFS sl@0: ); sl@0: } sl@0: sl@0: class TMBRPartitionEntry sl@0: { sl@0: public: sl@0: BOOL IsValidPartition() sl@0: { return (iNumSectors>0 && iPartitionType!=KPartitionTypeEmpty); } sl@0: BOOL IsValidDosPartition() sl@0: { return (iNumSectors>0 && PartitionIsFAT(iPartitionType)); } sl@0: BOOL IsDefaultBootPartition() sl@0: { return(iX86BootIndicator==KBootIndicatorBootable && (IsValidDosPartition() || IsValidFAT32Partition())); } sl@0: BOOL IsValidFAT32Partition() sl@0: { return (iNumSectors>0 && PartitionIsFAT32(iPartitionType)); } sl@0: public: sl@0: unsigned char iX86BootIndicator; sl@0: unsigned char iStartHead; sl@0: unsigned char iStartSector; sl@0: unsigned char iStartCylinder; sl@0: unsigned char iPartitionType; sl@0: unsigned char iEndHead; sl@0: unsigned char iEndSector; sl@0: unsigned char iEndCylinder; sl@0: DWORD iFirstSector; sl@0: DWORD iNumSectors; sl@0: }; sl@0: sl@0: sl@0: char* GetPartitionType(unsigned char aType) sl@0: { sl@0: switch (aType) sl@0: { sl@0: case KPartitionTypeFAT12: return "FAT12"; sl@0: case KPartitionTypeFAT16: return "FAT16"; sl@0: case KPartitionTypeFAT16small: return "FAT16"; sl@0: case KPartitionTypeWin95FAT32: return "FAT32"; sl@0: default: sl@0: return "????"; sl@0: sl@0: } sl@0: } sl@0: sl@0: void ReadMbr(unsigned char* aMbrBuf, int aDiskSizeInSectors, BOOL aHexDump) sl@0: { sl@0: // printf("Reading MBR...\n"); sl@0: if (aHexDump) sl@0: { sl@0: int n; sl@0: for (n=0; niPartitionType != 0; i++, pe++) sl@0: { sl@0: if (pe->iFirstSector + pe->iNumSectors > (DWORD) aDiskSizeInSectors) sl@0: { sl@0: printf("No valid MBR\n"); sl@0: return; sl@0: } sl@0: } sl@0: sl@0: printf("Partitions: \n"); sl@0: printf(" # Name Type Fat BtI Hed Sct Cyl Hed Sct Cyl FirstSect NumSectors\n"); sl@0: sl@0: for (i=0, pe = (TMBRPartitionEntry*)(&aMbrBuf[KMBRFirstPartitionOffset]); i < KMaxPartitionEntries && pe->iPartitionType != 0; i++, pe++) sl@0: { sl@0: char* partitionName = GetPartitionType(pe->iPartitionType); sl@0: printf("%3d: %-6s %3u %3u %3u %3u %3u %3u %3u %3u %3u %10u %10u (%u MB)\n", sl@0: i, sl@0: partitionName, sl@0: pe->iPartitionType, sl@0: pe->IsValidDosPartition() || pe->IsValidFAT32Partition() ? 1 : 0, sl@0: pe->iX86BootIndicator, sl@0: pe->iStartHead, sl@0: pe->iStartSector, sl@0: pe->iStartCylinder, sl@0: pe->iEndHead, sl@0: pe->iEndSector, sl@0: pe->iEndCylinder, sl@0: pe->iFirstSector, sl@0: pe->iNumSectors, sl@0: pe->iNumSectors >> KMegaByteToSectorSizeShift); sl@0: sl@0: if (pe->iPartitionType == KPartitionTypeHiddenNTFS) sl@0: { sl@0: printf("Drive contains an NTFS partition, aborting for safety\n"); sl@0: return; sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: BOOL WriteMbr(unsigned char* aMbrBuf, int aFatSectorCount) sl@0: { sl@0: TMBRPartitionEntry *pe=(TMBRPartitionEntry*)(&aMbrBuf[KMBRFirstPartitionOffset]); sl@0: sl@0: // first partition starts at one MB sl@0: int sectorStart = KMegaByteInSectors; sl@0: sl@0: // Create FAT partition sl@0: pe->iFirstSector = sectorStart; sl@0: sl@0: sl@0: pe->iNumSectors = aFatSectorCount; sl@0: pe->iX86BootIndicator = 0x00; sl@0: if (pe->iNumSectors < 32680) sl@0: pe->iPartitionType = KPartitionTypeFAT12; sl@0: else if(pe->iNumSectors < 65536) sl@0: pe->iPartitionType = KPartitionTypeFAT16small; sl@0: else if (pe->iNumSectors < 1048576) sl@0: pe->iPartitionType = KPartitionTypeFAT16; sl@0: else sl@0: pe->iPartitionType = KPartitionTypeWin95FAT32; sl@0: sectorStart+= pe->iNumSectors; sl@0: sl@0: aMbrBuf[KMBRSignatureOffset+0] = 0x55; sl@0: aMbrBuf[KMBRSignatureOffset+1] = 0xAA; sl@0: sl@0: return true; sl@0: } sl@0: sl@0: sl@0: int main(int argc,char *argv[]) sl@0: { sl@0: sl@0: if (argc < 2) sl@0: { sl@0: printf("MbrUtil - Decodes and optionally writes or erases the Master Boot Record on a removable drive\n"); sl@0: printf("Syntax : MbrUtil [-e] [-w ] [FAT] [FAT32]\n"); sl@0: printf("Where :\n"); sl@0: printf("-e : erase Master Boot Record:\n"); sl@0: printf("-w : create FAT partition of size :\n"); sl@0: printf("E.g. : MbrUtil f:\n"); sl@0: printf(" : MbrUtil f: -w 16 FAT\n"); sl@0: exit(0); sl@0: } sl@0: sl@0: bool writeMbr = false; sl@0: bool eraseMbr = false; sl@0: int fatSectorCount = 0; sl@0: char* fatType = "FAT"; sl@0: sl@0: char driveLetter = (char) toupper(argv[1][0]); sl@0: if ((strlen(argv[1]) > 2) || sl@0: (strlen(argv[1]) == 2 && argv[1][1] != ':') || sl@0: (driveLetter < 'A' || driveLetter > 'Z')) sl@0: { sl@0: printf("invalid drive letter"); sl@0: exit(4); sl@0: } sl@0: sl@0: for (int i=2; i= argc) sl@0: { sl@0: printf("no drive size specified"); sl@0: exit(4); sl@0: } sl@0: int fatSizeInMegabytes = atoi(argv[i]); sl@0: fatSectorCount = fatSizeInMegabytes << KMegaByteToSectorSizeShift; sl@0: // printf("fatSizeInMegabytes %d, fatSectorCount %d\n", fatSizeInMegabytes, fatSectorCount); sl@0: } sl@0: else if (strcmpi(argv[i], "FAT") == 0) sl@0: { sl@0: } sl@0: else if (strcmpi(argv[i], "FAT32") == 0) sl@0: { sl@0: fatType = argv[i]; sl@0: } sl@0: else sl@0: { sl@0: printf("invalid option"); sl@0: exit(4); sl@0: } sl@0: } sl@0: sl@0: sl@0: char diskName[10] = "\\\\.\\?:"; sl@0: diskName[4] = driveLetter; sl@0: char physDiskName[20] = "\\\\.\\PHYSICALDRIVE?"; sl@0: sl@0: sl@0: sl@0: DISK_GEOMETRY geometry; sl@0: DWORD dummy; sl@0: HANDLE logDeviceHandle; sl@0: HANDLE physDeviceHandle; sl@0: BOOL b; sl@0: DWORD bytesRead; sl@0: DWORD bytesWritten; sl@0: DWORD dwRet; sl@0: sl@0: //***************************************************************************************** sl@0: // open logical drive... sl@0: //***************************************************************************************** sl@0: printf("Opening %s...\n", diskName); sl@0: logDeviceHandle = CreateFileA( sl@0: diskName, sl@0: GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE , sl@0: NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, NULL); sl@0: if (logDeviceHandle == INVALID_HANDLE_VALUE) sl@0: { sl@0: printf("CreateFileA() returned INVALID_HANDLE_VALUE\n"); sl@0: exit(4); sl@0: } sl@0: sl@0: // query geometry sl@0: b = DeviceIoControl( sl@0: logDeviceHandle, sl@0: IOCTL_DISK_GET_DRIVE_GEOMETRY, sl@0: NULL, sl@0: 0, sl@0: &geometry, sl@0: sizeof(geometry), sl@0: &dummy, sl@0: (LPOVERLAPPED)NULL); sl@0: if (!b) sl@0: { sl@0: printf("IOCTL_DISK_GET_DRIVE_GEOMETRY failed error %x", GetLastError()); sl@0: CloseHandle(logDeviceHandle); sl@0: exit(4); sl@0: } sl@0: sl@0: LONGLONG diskSizeInBytes = geometry.Cylinders.QuadPart * geometry.TracksPerCylinder * geometry.SectorsPerTrack * KDiskSectorSize; sl@0: int diskSizeInMegaBytes = (int) (diskSizeInBytes / KMegaByte); sl@0: int diskSizeInSectors = (int) (diskSizeInBytes / KDiskSectorSize); sl@0: sl@0: sl@0: printf("Drive %c MediaType: %d (%s). Size: %ld MBytes, %lu sectors\n", sl@0: driveLetter, sl@0: geometry.MediaType, sl@0: geometry.MediaType==RemovableMedia ? "RemovableMedia" : sl@0: geometry.MediaType==FixedMedia ? "FixedMedia" : "?", sl@0: diskSizeInMegaBytes, sl@0: diskSizeInSectors sl@0: ); sl@0: // printf("Size: %llu sectors\n", diskSizeInSectors); sl@0: sl@0: if (geometry.MediaType != RemovableMedia) sl@0: { sl@0: printf("Drive is not removable, exiting"); sl@0: CloseHandle(logDeviceHandle); sl@0: exit(4); sl@0: } sl@0: sl@0: if (fatSectorCount + KMegaByteInSectors > diskSizeInSectors) sl@0: { sl@0: printf("Specified size is too big"); sl@0: CloseHandle(logDeviceHandle); sl@0: exit(4); sl@0: } sl@0: sl@0: //***************************************************************************************** sl@0: // Get physical device number sl@0: //***************************************************************************************** sl@0: STORAGE_DEVICE_NUMBER storageDeviceNumber; sl@0: b = IOCTL_STORAGE_GET_DEVICE_NUMBER; sl@0: b = DeviceIoControl( sl@0: logDeviceHandle, sl@0: IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &storageDeviceNumber, sizeof(storageDeviceNumber), &bytesRead, 0); sl@0: // printf("IOCTL_STORAGE_GET_DEVICE_NUMBER b %d DeviceNumber %d\n", b, storageDeviceNumber.DeviceNumber); sl@0: if (!b) sl@0: { sl@0: printf("IOCTL_STORAGE_GET_DEVICE_NUMBER failed error %x", GetLastError()); sl@0: CloseHandle(logDeviceHandle); sl@0: exit(4); sl@0: } sl@0: sl@0: sl@0: sl@0: //***************************************************************************************** sl@0: // open physical drive... sl@0: //***************************************************************************************** sl@0: physDiskName[strlen(physDiskName)-1] = (char) ('0' + storageDeviceNumber.DeviceNumber); sl@0: sl@0: printf("Opening %s...\n", physDiskName); sl@0: physDeviceHandle = CreateFileA( sl@0: physDiskName, sl@0: GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE , sl@0: NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, NULL); sl@0: if (physDeviceHandle == INVALID_HANDLE_VALUE) sl@0: { sl@0: printf("CreateFileA() returned INVALID_HANDLE_VALUE\n"); sl@0: exit(4); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: //******************************************************* sl@0: // Read first sector sl@0: //******************************************************* sl@0: dwRet = SetFilePointer( sl@0: physDeviceHandle, 0, 0, FILE_BEGIN); sl@0: if (dwRet != 0) sl@0: { sl@0: printf("Unable to set file pointer, exiting"); sl@0: CloseHandle(physDeviceHandle); sl@0: CloseHandle(logDeviceHandle); sl@0: exit(4); sl@0: } sl@0: if (!ReadFile (physDeviceHandle, TheBuffer, KSectorSize, &bytesRead, NULL) ) sl@0: { sl@0: printf("ReadFile failed with %d", GetLastError()); sl@0: CloseHandle(physDeviceHandle); sl@0: CloseHandle(logDeviceHandle); sl@0: exit(4); sl@0: } sl@0: if(bytesRead != KSectorSize) sl@0: { sl@0: printf("ReadFile length too small: %d", bytesRead); sl@0: CloseHandle(physDeviceHandle); sl@0: CloseHandle(logDeviceHandle); sl@0: exit(4); sl@0: } sl@0: sl@0: //******************************************************* sl@0: // Interpret MBR sl@0: //******************************************************* sl@0: ReadMbr(TheBuffer, diskSizeInSectors, false); sl@0: sl@0: //******************************************************* sl@0: // Write new MBR sl@0: //******************************************************* sl@0: if (writeMbr) sl@0: { sl@0: printf("Writing MBR...\n"); sl@0: memset(TheBuffer, 0, sizeof(TheBuffer)); sl@0: b = WriteMbr(TheBuffer, fatSectorCount); sl@0: if (!b) sl@0: writeMbr = eraseMbr = false; sl@0: } sl@0: if (eraseMbr) sl@0: { sl@0: printf("Erasing MBR...\n"); sl@0: memset(TheBuffer, 0, sizeof(TheBuffer)); sl@0: } sl@0: if (writeMbr || eraseMbr) sl@0: { sl@0: // Write first sector sl@0: dwRet = SetFilePointer( sl@0: physDeviceHandle, 0, 0, FILE_BEGIN); sl@0: if (dwRet != 0) sl@0: { sl@0: printf("Unable to set file pointer, exiting"); sl@0: CloseHandle(physDeviceHandle); sl@0: CloseHandle(logDeviceHandle); sl@0: exit(4); sl@0: } sl@0: if (!WriteFile (physDeviceHandle, TheBuffer, KSectorSize, &bytesWritten, NULL) ) sl@0: { sl@0: printf("WriteFile failed with %d", GetLastError()); sl@0: CloseHandle(physDeviceHandle); sl@0: CloseHandle(logDeviceHandle); sl@0: exit(4); sl@0: } sl@0: if(bytesWritten != KSectorSize) sl@0: { sl@0: printf("WriteFile length too small: %d", bytesWritten); sl@0: CloseHandle(physDeviceHandle); sl@0: CloseHandle(logDeviceHandle); sl@0: exit(4); sl@0: } sl@0: if (writeMbr) sl@0: ReadMbr(TheBuffer, diskSizeInSectors, false); sl@0: } sl@0: sl@0: sl@0: CloseHandle(physDeviceHandle); sl@0: sl@0: sl@0: if (writeMbr || eraseMbr) sl@0: { sl@0: printf("Dismounting %s...\n", diskName); sl@0: b = DeviceIoControl( sl@0: logDeviceHandle, sl@0: FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &bytesRead, 0); sl@0: if (!b) sl@0: printf("FSCTL_DISMOUNT_VOLUME b %d err %d\n", b, GetLastError()); sl@0: } sl@0: sl@0: CloseHandle(logDeviceHandle); sl@0: sl@0: //******************************************************* sl@0: // Format the disk sl@0: //******************************************************* sl@0: if (writeMbr || eraseMbr) sl@0: { sl@0: printf("\n"); sl@0: char prompt[80]; sl@0: sprintf(prompt, "Eject card from drive %C: and press ENTER when ready...\n", driveLetter); sl@0: printf(prompt); sl@0: getchar(); sl@0: sl@0: char winCmd[1024]; sl@0: char cmdArgs[1024]; sl@0: STARTUPINFO si = {0,}; sl@0: PROCESS_INFORMATION pi; sl@0: sl@0: GetWindowsDirectory(winCmd, sizeof(winCmd)); sl@0: strncat(winCmd, "\\system32\\cmd.exe", sizeof(winCmd)); sl@0: sprintf(cmdArgs, "/C format %c: /FS:%s /Q /X", driveLetter, fatType); sl@0: printf("Executing : %s %s\n", winCmd, cmdArgs); sl@0: b = CreateProcessA( sl@0: winCmd, //__in_opt LPCTSTR lpApplicationName, sl@0: cmdArgs, //__inout_opt LPTSTR lpCommandLine, sl@0: NULL, //__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes, sl@0: NULL, //__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, sl@0: FALSE, //__in BOOL bInheritHandles, sl@0: 0, //__in DWORD dwCreationFlags, sl@0: NULL, //__in_opt LPVOID lpEnvironment, sl@0: NULL, //__in_opt LPCTSTR lpCurrentDirectory, sl@0: &si, //__in LPSTARTUPINFO lpStartupInfo, sl@0: &pi); //__out LPPROCESS_INFORMATION lpProcessInformation sl@0: if (!b) sl@0: printf("CreateProcess failed with %d", GetLastError()); sl@0: sl@0: dwRet = WaitForSingleObject(pi.hProcess, INFINITE); sl@0: CloseHandle(pi.hThread); sl@0: CloseHandle(pi.hProcess); sl@0: sl@0: } sl@0: sl@0: return 0; sl@0: }