// Dependencies: shellapi.h, shell32.lib for SHGetFileInfo() // windows.h, kernel32.lib for GetDiskFreeSpace() // io.h for _waccess() #include #include #include #include #include //#include #include //#include #include "switches.h" #include "wizres.h" extern HINSTANCE g_hInstance; #if !defined(SHFMT_OPT_FULL) #if defined (__cplusplus) extern "C" { #endif DWORD WINAPI SHFormatDrive(HWND,UINT,UINT,UINT); #define SHFMT_ID_DEFAULT 0xffff #define SHFMT_OPT_FULL 0x0001 #define SHFMT_OPT_SYSONLY 0x0002 #define SHFMT_ERROR 0xffffffffL #define SHFMT_CANCEL 0xfffffffeL #define SHFMT_NOFORMAT 0xffffffdL #if defined (__cplusplus) } #endif #endif // Miscellaneous declarations not contain in header files // These will be miscellaneous items found in other files within this project int RMessageBox(HWND hw,UINT_PTR uiResIDTitle, UINT_PTR uiResIDText, UINT uiType); extern HWND c_hDlg; extern WCHAR pszFileName[]; INT g_iFileSize = 0; INT g_iBufferSize = 0; INT g_iSectorSize = 0; HANDLE g_hFile = NULL; BOOL GetFileSize(WCHAR *pszFilePath,INT *icbSize) { WIN32_FILE_ATTRIBUTE_DATA stWFAD = {0}; if (NULL == pszFilePath) return FALSE; if (NULL == icbSize) return FALSE; if (!GetFileAttributesEx(pszFilePath,GetFileExInfoStandard,&stWFAD)) return FALSE; #ifdef LOUDLY #ifdef LOUDLY WCHAR rgc[100]; swprintf(rgc,L"GetFileSize returns %d\n",stWFAD.nFileSizeLow); OutputDebugString(rgc); #endif #endif *icbSize = stWFAD.nFileSizeLow; return TRUE; } DWORD GetDriveFreeSpace(WCHAR *pszFilePath) { WCHAR *pwc; WCHAR rgcModel[]={L"A:"}; DWORD dwSpc,dwBps,dwCfc,dwTcc,dwFree; if (NULL == pszFilePath) return 0; rgcModel[0] = *pszFilePath; if (!GetDiskFreeSpace(rgcModel,&dwSpc,&dwBps,&dwCfc,&dwTcc)) { #ifdef LOUDLY WCHAR rgwc[100]; swprintf(rgwc,L"GetDriveFreeSpace encountered error %x\n",GetLastError()); OutputDebugString(rgwc); OutputDebugString(L"GetDriveFreeSpace returning 0\n"); #endif return 0; } dwFree = dwBps * dwCfc * dwSpc; #ifdef LOUDLY WCHAR rgc[100]; swprintf(rgc,L"GetDriveFreeSpace returns %d\n",dwFree); OutputDebugString(rgc); #endif return dwFree; } DWORD GetDriveSectorSize(WCHAR *pszFilePath) { WCHAR *pwc; WCHAR rgcModel[]={L"A:"}; DWORD dwSpc,dwBps,dwCfc,dwTcc; if (NULL == pszFilePath) return 0; rgcModel[0] = *pszFilePath; if (!GetDiskFreeSpace(rgcModel,&dwSpc,&dwBps,&dwCfc,&dwTcc)) { #ifdef LOUDLY WCHAR rgwc[100]; swprintf(rgwc,L"GetDriveSectorSize encountered error %x\n",GetLastError()); OutputDebugString(rgwc); OutputDebugString(L"GetDriveSectorSize returning 0\n"); #endif return 0; } #ifdef LOUDLY WCHAR rgc[100]; swprintf(rgc,L"GetDriveSectorSize returns %d\n",dwBps); OutputDebugString(rgc); #endif return dwBps; } // take data size, sector size, return ptr to finished buffer LPVOID CreateFileBuffer(INT iDataSize,INT iSectorSize) { INT iSize; LPVOID lpv; if (iDataSize == iSectorSize) iSize = iDataSize; else { iSize = iDataSize/iSectorSize; iSize += 1; iSize *= iSectorSize; } g_iBufferSize = iSize; lpv = VirtualAlloc(NULL,iSize,MEM_COMMIT,PAGE_READWRITE | PAGE_NOCACHE); #ifdef LOUDLY WCHAR rgc[100]; if (lpv) OutputDebugString(L"CreateFileBuffer succeeded\n"); else OutputDebugString(L"CreateFileBuffer failed ******\n"); swprintf(rgc,L"File Buffer size is %d\n",g_iBufferSize); OutputDebugString(rgc); #endif return lpv; } // take ptr to buffer, release using VirtualFree() void ReleaseFileBuffer(LPVOID lpv) { ZeroMemory(lpv,g_iBufferSize); VirtualFree(lpv,0,MEM_RELEASE); #ifdef LOUDLY OutputDebugString(L"ReleaseFileBuffer called\n"); #endif return; } /* MediumIsPresent() returns true if there is a readable medium present in the drive. */ BOOL FileMediumIsPresent(TCHAR *pszPath) { UINT uMode = 0; BOOL bResult = FALSE; TCHAR rgcModel[]=TEXT("A:"); DWORD dwError = 0; if (*pszPath == 0) return FALSE; rgcModel[0] = *pszPath; uMode = SetErrorMode(SEM_FAILCRITICALERRORS); if (0 == _waccess(rgcModel,0)) { bResult = TRUE; } else dwError = GetLastError(); #ifdef LOUDLY WCHAR rgwc[100]; swprintf(rgwc,L"_waccess returns error %x for %s\n",dwError,rgcModel); OutputDebugString(rgwc); if (!bResult) OutputDebugString(L"FileMediumIsPresent returning FALSE\n"); else OutputDebugString(L"FileMediumIsPresent returning TRUE\n"); #endif // Correct certain obvious errors with the user's help if (ERROR_UNRECOGNIZED_MEDIA == dwError) { // unformatted disk WCHAR rgcFmt[200] = {0}; WCHAR rgcMsg[200] = {0}; WCHAR rgcTitle[200] = {0}; #ifdef LOUDLY OutputDebugString(L"FileMediumIsPresent found an unformatted medium\n"); #endif INT iCount = LoadString(g_hInstance,IDS_MBTFORMAT,rgcTitle,200 - 1); iCount = LoadString(g_hInstance,IDS_MBMFORMAT,rgcFmt,200 - 1); if (0 == iCount) goto LblNoBox; swprintf(rgcMsg,rgcFmt,rgcModel); INT iDrive = PathGetDriveNumber(rgcModel); int iRet = MessageBox(c_hDlg,rgcMsg,rgcTitle,MB_YESNO); if (IDYES == iRet) { dwError = SHFormatDrive(c_hDlg,iDrive,SHFMT_ID_DEFAULT,0); if (0 == bResult) bResult = TRUE; } } LblNoBox: uMode = SetErrorMode(uMode); return bResult; } // // On save, create file if // absent. Return handle on success, NULL on fail. FileName will be in // c_rgcFileName. // HANDLE GetInputFile(void) { HANDLE hFile = INVALID_HANDLE_VALUE; DWORD dwErr; WIN32_FILE_ATTRIBUTE_DATA stAttributes = {0}; #ifdef LOUDLY OutputDebugString(L"GetInputFile() opening input file "); OutputDebugString(pszFileName); OutputDebugString(L"\n"); #endif if (FileMediumIsPresent(pszFileName)) { g_iSectorSize = GetDriveSectorSize(pszFileName); if (0 == g_iSectorSize) return NULL; if (GetFileAttributesEx(pszFileName,GetFileExInfoStandard,&stAttributes)) { // file exists and we have a size for it. g_iFileSize = stAttributes.nFileSizeLow; } else { dwErr = GetLastError(); if (dwErr == ERROR_FILE_NOT_FOUND) RMessageBox(c_hDlg,IDS_MBTWRONGDISK ,IDS_MBMWRONGDISK ,MB_ICONEXCLAMATION); else { #ifdef LOUDLY { WCHAR rgs[200] = {0}; swprintf(rgs,L"GetFileAttributesEx() failed, error = %x\n",dwErr); OutputDebugString(rgs); } #endif RMessageBox(c_hDlg,IDS_MBTDISKERROR ,IDS_MBMDISKERROR ,MB_ICONEXCLAMATION); } g_hFile = NULL; return NULL; } // end GetFileAttributes hFile = CreateFileW(pszFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL); if (INVALID_HANDLE_VALUE == hFile) { dwErr = GetLastError(); if (dwErr == ERROR_FILE_NOT_FOUND) RMessageBox(c_hDlg,IDS_MBTWRONGDISK ,IDS_MBMWRONGDISK ,MB_ICONEXCLAMATION); else RMessageBox(c_hDlg,IDS_MBTDISKERROR ,IDS_MBMDISKERROR ,MB_ICONEXCLAMATION); } } else { RMessageBox(c_hDlg,IDS_MBTNODISK ,IDS_MBMNODISK ,MB_ICONEXCLAMATION); } if ((NULL == hFile) || (INVALID_HANDLE_VALUE == hFile)) { g_hFile = NULL; return NULL; } g_hFile = hFile; return hFile; } void CloseInputFile(void) { #ifdef LOUDLY OutputDebugString(L"Input file closed\n"); #endif if (g_hFile) { CloseHandle(g_hFile); g_hFile = NULL; } return; } HANDLE GetOutputFile(void) { //HANDLE hFile = INVALID_HANDLE_VALUE; HANDLE hFile = NULL; DWORD dwErr; if (FileMediumIsPresent(pszFileName)) { g_iSectorSize = GetDriveSectorSize(pszFileName); if (0 == g_iSectorSize) return NULL; hFile = CreateFileW(pszFileName, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_FLAG_NO_BUFFERING, NULL); if ((NULL == hFile) || (INVALID_HANDLE_VALUE == hFile)) { dwErr = GetLastError(); #ifdef LOUDLY TCHAR rgct[500]; swprintf(rgct,L"File create returns %x\n",dwErr); OutputDebugString(rgct); #endif if ((dwErr == ERROR_FILE_EXISTS)) { if (IDYES != RMessageBox(c_hDlg,IDS_MBTOVERWRITE ,IDS_MBMOVERWRITE ,MB_YESNO)) { // Overwrite abandoned. g_hFile = NULL; return NULL; } else { SetFileAttributes(pszFileName,FILE_ATTRIBUTE_NORMAL); hFile = CreateFileW(pszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_NO_BUFFERING, NULL); #ifdef LOUDLY dwErr = GetLastError(); swprintf(rgct,L"File create failed %x\n",dwErr); OutputDebugString(rgct); #endif } } // end if already exists error } // end if NULL == hFile } else { RMessageBox(c_hDlg,IDS_MBTNODISK ,IDS_MBMNODISK ,MB_ICONEXCLAMATION); } if (INVALID_HANDLE_VALUE == hFile) { g_hFile = NULL; return NULL; } #ifdef LOUDLY OutputDebugString(L"File successfully created\n"); #endif g_hFile = hFile; return hFile; } /* DWORD ReadPrivateData(PWSTR,LPBYTE *,INT *) DWORD WritePrivateData(PWSTR,LPBYTE,INT) These functions read or write a reasonably short block of data to a disk device, avoiding buffering of the data. This allows the data to be wiped by the client before the buffers are released. The DWORD return value is that which would return from GetLastError() and can be handled accordingly. ReadPrivateData() returns a malloc'd pointer which must be freed by the client. It also returns the count of bytes read from the medium to the INT *. The file is closed following the read operation before the function returns. WritePrivateData() writes a count of bytes from LPBYTE to the disk. When it returns, the buffer used to do so has been flushed and the file is closed. */ /* prgb = byte ptr to data returned from the read piCount = size of active data field within the buffer Note that even if the read fails (file not found, read error, etc.) the buffer ptr is still valid. */ //ReadFile(c_hFile,c_pPrivate,c_cbPrivate,&c_cbPrivate,NULL) return bytes read INT ReadPrivateData(BYTE **prgb,INT *piCount) { LPVOID lpv; DWORD dwBytesRead; if (NULL == prgb) return 0; if (NULL == piCount) return 0; if (g_hFile) { lpv = CreateFileBuffer(g_iFileSize,g_iSectorSize); if (NULL == lpv) { *prgb = 0; // indicate no need to free this buffer *piCount = 0; return 0; } *prgb = (BYTE *)lpv; // even if no data, gotta free using VirtualFree() *piCount = 0; if (0 == ReadFile(g_hFile,lpv,g_iBufferSize,&dwBytesRead,NULL)) return 0; *piCount = g_iFileSize; #ifdef LOUDLY OutputDebugString(L"ReadPrivateData success\n"); #endif return g_iFileSize; } return 0; } /* Write data to file at g_rgwczFileName Convert size to multiple of sector size Alloc buffer Copy data to buffer Write data Scrub Buffer, release return 0 */ BOOL WritePrivateData(BYTE *lpData,INT icbData) { DWORD dwcb = 0; LPVOID lpv; if (NULL == g_hFile) return FALSE; if (NULL == lpData) return FALSE; if (0 == icbData) return FALSE; if (g_hFile) { g_iFileSize = icbData; lpv = CreateFileBuffer(g_iFileSize,g_iSectorSize); if (NULL == lpv) { return FALSE; } ZeroMemory(lpv,g_iBufferSize); memcpy(lpv,lpData,icbData); WriteFile(g_hFile,lpv,g_iBufferSize,&dwcb,NULL); VirtualFree(lpv,g_iBufferSize,MEM_RELEASE); } // ret TRUE iff file write succeeds and count of bytes is correct #ifdef LOUDLY if (dwcb) OutputDebugString(L"WritePrivateData succeeded\n"); else OutputDebugString(L"WritePrivateData failed ***\n"); #endif if (dwcb != g_iBufferSize) return FALSE; else return TRUE; }