Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

445 lines
13 KiB

  1. // Dependencies: shellapi.h, shell32.lib for SHGetFileInfo()
  2. // windows.h, kernel32.lib for GetDiskFreeSpace()
  3. // io.h for _waccess()
  4. #include <windef.h>
  5. #include <windows.h>
  6. #include <string.h>
  7. #include <io.h>
  8. #include <stdio.h>
  9. //#include <shellapi.h>
  10. #include <shlwapi.h>
  11. //#include <shlobjp.h>
  12. #include "switches.h"
  13. #include "wizres.h"
  14. extern HINSTANCE g_hInstance;
  15. #if !defined(SHFMT_OPT_FULL)
  16. #if defined (__cplusplus)
  17. extern "C" {
  18. #endif
  19. DWORD WINAPI SHFormatDrive(HWND,UINT,UINT,UINT);
  20. #define SHFMT_ID_DEFAULT 0xffff
  21. #define SHFMT_OPT_FULL 0x0001
  22. #define SHFMT_OPT_SYSONLY 0x0002
  23. #define SHFMT_ERROR 0xffffffffL
  24. #define SHFMT_CANCEL 0xfffffffeL
  25. #define SHFMT_NOFORMAT 0xffffffdL
  26. #if defined (__cplusplus)
  27. }
  28. #endif
  29. #endif
  30. // Miscellaneous declarations not contain in header files
  31. // These will be miscellaneous items found in other files within this project
  32. int RMessageBox(HWND hw,UINT_PTR uiResIDTitle, UINT_PTR uiResIDText, UINT uiType);
  33. extern HWND c_hDlg;
  34. extern WCHAR pszFileName[];
  35. INT g_iFileSize = 0;
  36. INT g_iBufferSize = 0;
  37. INT g_iSectorSize = 0;
  38. HANDLE g_hFile = NULL;
  39. BOOL GetFileSize(WCHAR *pszFilePath,INT *icbSize)
  40. {
  41. WIN32_FILE_ATTRIBUTE_DATA stWFAD = {0};
  42. if (NULL == pszFilePath) return FALSE;
  43. if (NULL == icbSize) return FALSE;
  44. if (!GetFileAttributesEx(pszFilePath,GetFileExInfoStandard,&stWFAD)) return FALSE;
  45. #ifdef LOUDLY
  46. #ifdef LOUDLY
  47. WCHAR rgc[100];
  48. swprintf(rgc,L"GetFileSize returns %d\n",stWFAD.nFileSizeLow);
  49. OutputDebugString(rgc);
  50. #endif
  51. #endif
  52. *icbSize = stWFAD.nFileSizeLow;
  53. return TRUE;
  54. }
  55. DWORD GetDriveFreeSpace(WCHAR *pszFilePath)
  56. {
  57. WCHAR *pwc;
  58. WCHAR rgcModel[]={L"A:"};
  59. DWORD dwSpc,dwBps,dwCfc,dwTcc,dwFree;
  60. if (NULL == pszFilePath) return 0;
  61. rgcModel[0] = *pszFilePath;
  62. if (!GetDiskFreeSpace(rgcModel,&dwSpc,&dwBps,&dwCfc,&dwTcc))
  63. {
  64. #ifdef LOUDLY
  65. WCHAR rgwc[100];
  66. swprintf(rgwc,L"GetDriveFreeSpace encountered error %x\n",GetLastError());
  67. OutputDebugString(rgwc);
  68. OutputDebugString(L"GetDriveFreeSpace returning 0\n");
  69. #endif
  70. return 0;
  71. }
  72. dwFree = dwBps * dwCfc * dwSpc;
  73. #ifdef LOUDLY
  74. WCHAR rgc[100];
  75. swprintf(rgc,L"GetDriveFreeSpace returns %d\n",dwFree);
  76. OutputDebugString(rgc);
  77. #endif
  78. return dwFree;
  79. }
  80. DWORD GetDriveSectorSize(WCHAR *pszFilePath)
  81. {
  82. WCHAR *pwc;
  83. WCHAR rgcModel[]={L"A:"};
  84. DWORD dwSpc,dwBps,dwCfc,dwTcc;
  85. if (NULL == pszFilePath) return 0;
  86. rgcModel[0] = *pszFilePath;
  87. if (!GetDiskFreeSpace(rgcModel,&dwSpc,&dwBps,&dwCfc,&dwTcc))
  88. {
  89. #ifdef LOUDLY
  90. WCHAR rgwc[100];
  91. swprintf(rgwc,L"GetDriveSectorSize encountered error %x\n",GetLastError());
  92. OutputDebugString(rgwc);
  93. OutputDebugString(L"GetDriveSectorSize returning 0\n");
  94. #endif
  95. return 0;
  96. }
  97. #ifdef LOUDLY
  98. WCHAR rgc[100];
  99. swprintf(rgc,L"GetDriveSectorSize returns %d\n",dwBps);
  100. OutputDebugString(rgc);
  101. #endif
  102. return dwBps;
  103. }
  104. // take data size, sector size, return ptr to finished buffer
  105. LPVOID CreateFileBuffer(INT iDataSize,INT iSectorSize)
  106. {
  107. INT iSize;
  108. LPVOID lpv;
  109. if (iDataSize == iSectorSize) iSize = iDataSize;
  110. else
  111. {
  112. iSize = iDataSize/iSectorSize;
  113. iSize += 1;
  114. iSize *= iSectorSize;
  115. }
  116. g_iBufferSize = iSize;
  117. lpv = VirtualAlloc(NULL,iSize,MEM_COMMIT,PAGE_READWRITE | PAGE_NOCACHE);
  118. #ifdef LOUDLY
  119. WCHAR rgc[100];
  120. if (lpv) OutputDebugString(L"CreateFileBuffer succeeded\n");
  121. else OutputDebugString(L"CreateFileBuffer failed ******\n");
  122. swprintf(rgc,L"File Buffer size is %d\n",g_iBufferSize);
  123. OutputDebugString(rgc);
  124. #endif
  125. return lpv;
  126. }
  127. // take ptr to buffer, release using VirtualFree()
  128. void ReleaseFileBuffer(LPVOID lpv)
  129. {
  130. ZeroMemory(lpv,g_iBufferSize);
  131. VirtualFree(lpv,0,MEM_RELEASE);
  132. #ifdef LOUDLY
  133. OutputDebugString(L"ReleaseFileBuffer called\n");
  134. #endif
  135. return;
  136. }
  137. /*
  138. MediumIsPresent() returns true if there is a readable medium present in the drive.
  139. */
  140. BOOL FileMediumIsPresent(TCHAR *pszPath) {
  141. UINT uMode = 0;
  142. BOOL bResult = FALSE;
  143. TCHAR rgcModel[]=TEXT("A:");
  144. DWORD dwError = 0;
  145. if (*pszPath == 0) return FALSE;
  146. rgcModel[0] = *pszPath;
  147. uMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  148. if (0 == _waccess(rgcModel,0)) {
  149. bResult = TRUE;
  150. }
  151. else dwError = GetLastError();
  152. #ifdef LOUDLY
  153. WCHAR rgwc[100];
  154. swprintf(rgwc,L"_waccess returns error %x for %s\n",dwError,rgcModel);
  155. OutputDebugString(rgwc);
  156. if (!bResult) OutputDebugString(L"FileMediumIsPresent returning FALSE\n");
  157. else OutputDebugString(L"FileMediumIsPresent returning TRUE\n");
  158. #endif
  159. // Correct certain obvious errors with the user's help
  160. if (ERROR_UNRECOGNIZED_MEDIA == dwError)
  161. {
  162. // unformatted disk
  163. WCHAR rgcFmt[200] = {0};
  164. WCHAR rgcMsg[200] = {0};
  165. WCHAR rgcTitle[200] = {0};
  166. #ifdef LOUDLY
  167. OutputDebugString(L"FileMediumIsPresent found an unformatted medium\n");
  168. #endif
  169. INT iCount = LoadString(g_hInstance,IDS_MBTFORMAT,rgcTitle,200 - 1);
  170. iCount = LoadString(g_hInstance,IDS_MBMFORMAT,rgcFmt,200 - 1);
  171. if (0 == iCount) goto LblNoBox;
  172. swprintf(rgcMsg,rgcFmt,rgcModel);
  173. INT iDrive = PathGetDriveNumber(rgcModel);
  174. int iRet = MessageBox(c_hDlg,rgcMsg,rgcTitle,MB_YESNO);
  175. if (IDYES == iRet)
  176. {
  177. dwError = SHFormatDrive(c_hDlg,iDrive,SHFMT_ID_DEFAULT,0);
  178. if (0 == bResult) bResult = TRUE;
  179. }
  180. }
  181. LblNoBox:
  182. uMode = SetErrorMode(uMode);
  183. return bResult;
  184. }
  185. //
  186. // On save, create file if
  187. // absent. Return handle on success, NULL on fail. FileName will be in
  188. // c_rgcFileName.
  189. //
  190. HANDLE GetInputFile(void) {
  191. HANDLE hFile = INVALID_HANDLE_VALUE;
  192. DWORD dwErr;
  193. WIN32_FILE_ATTRIBUTE_DATA stAttributes = {0};
  194. #ifdef LOUDLY
  195. OutputDebugString(L"GetInputFile() opening input file ");
  196. OutputDebugString(pszFileName);
  197. OutputDebugString(L"\n");
  198. #endif
  199. if (FileMediumIsPresent(pszFileName)) {
  200. g_iSectorSize = GetDriveSectorSize(pszFileName);
  201. if (0 == g_iSectorSize) return NULL;
  202. if (GetFileAttributesEx(pszFileName,GetFileExInfoStandard,&stAttributes))
  203. {
  204. // file exists and we have a size for it.
  205. g_iFileSize = stAttributes.nFileSizeLow;
  206. }
  207. else
  208. {
  209. dwErr = GetLastError();
  210. if (dwErr == ERROR_FILE_NOT_FOUND)
  211. RMessageBox(c_hDlg,IDS_MBTWRONGDISK ,IDS_MBMWRONGDISK ,MB_ICONEXCLAMATION);
  212. else
  213. {
  214. #ifdef LOUDLY
  215. {
  216. WCHAR rgs[200] = {0};
  217. swprintf(rgs,L"GetFileAttributesEx() failed, error = %x\n",dwErr);
  218. OutputDebugString(rgs);
  219. }
  220. #endif
  221. RMessageBox(c_hDlg,IDS_MBTDISKERROR ,IDS_MBMDISKERROR ,MB_ICONEXCLAMATION);
  222. }
  223. g_hFile = NULL;
  224. return NULL;
  225. } // end GetFileAttributes
  226. hFile = CreateFileW(pszFileName,
  227. GENERIC_READ,
  228. 0,
  229. NULL,
  230. OPEN_EXISTING,
  231. FILE_FLAG_NO_BUFFERING,
  232. NULL);
  233. if (INVALID_HANDLE_VALUE == hFile) {
  234. dwErr = GetLastError();
  235. if (dwErr == ERROR_FILE_NOT_FOUND)
  236. RMessageBox(c_hDlg,IDS_MBTWRONGDISK ,IDS_MBMWRONGDISK ,MB_ICONEXCLAMATION);
  237. else
  238. RMessageBox(c_hDlg,IDS_MBTDISKERROR ,IDS_MBMDISKERROR ,MB_ICONEXCLAMATION);
  239. }
  240. }
  241. else {
  242. RMessageBox(c_hDlg,IDS_MBTNODISK ,IDS_MBMNODISK ,MB_ICONEXCLAMATION);
  243. }
  244. if ((NULL == hFile) || (INVALID_HANDLE_VALUE == hFile)) {
  245. g_hFile = NULL;
  246. return NULL;
  247. }
  248. g_hFile = hFile;
  249. return hFile;
  250. }
  251. void CloseInputFile(void)
  252. {
  253. #ifdef LOUDLY
  254. OutputDebugString(L"Input file closed\n");
  255. #endif
  256. if (g_hFile)
  257. {
  258. CloseHandle(g_hFile);
  259. g_hFile = NULL;
  260. }
  261. return;
  262. }
  263. HANDLE GetOutputFile(void) {
  264. //HANDLE hFile = INVALID_HANDLE_VALUE;
  265. HANDLE hFile = NULL;
  266. DWORD dwErr;
  267. if (FileMediumIsPresent(pszFileName)) {
  268. g_iSectorSize = GetDriveSectorSize(pszFileName);
  269. if (0 == g_iSectorSize) return NULL;
  270. hFile = CreateFileW(pszFileName,
  271. GENERIC_WRITE,
  272. 0,
  273. NULL,
  274. CREATE_NEW,
  275. FILE_FLAG_NO_BUFFERING,
  276. NULL);
  277. if ((NULL == hFile) || (INVALID_HANDLE_VALUE == hFile)) {
  278. dwErr = GetLastError();
  279. #ifdef LOUDLY
  280. TCHAR rgct[500];
  281. swprintf(rgct,L"File create returns %x\n",dwErr);
  282. OutputDebugString(rgct);
  283. #endif
  284. if ((dwErr == ERROR_FILE_EXISTS)) {
  285. if (IDYES != RMessageBox(c_hDlg,IDS_MBTOVERWRITE ,IDS_MBMOVERWRITE ,MB_YESNO)) {
  286. // Overwrite abandoned.
  287. g_hFile = NULL;
  288. return NULL;
  289. }
  290. else {
  291. SetFileAttributes(pszFileName,FILE_ATTRIBUTE_NORMAL);
  292. hFile = CreateFileW(pszFileName,
  293. GENERIC_WRITE,
  294. 0,
  295. NULL,
  296. CREATE_ALWAYS,
  297. FILE_FLAG_NO_BUFFERING,
  298. NULL);
  299. #ifdef LOUDLY
  300. dwErr = GetLastError();
  301. swprintf(rgct,L"File create failed %x\n",dwErr);
  302. OutputDebugString(rgct);
  303. #endif
  304. }
  305. } // end if already exists error
  306. } // end if NULL == hFile
  307. }
  308. else {
  309. RMessageBox(c_hDlg,IDS_MBTNODISK ,IDS_MBMNODISK ,MB_ICONEXCLAMATION);
  310. }
  311. if (INVALID_HANDLE_VALUE == hFile) {
  312. g_hFile = NULL;
  313. return NULL;
  314. }
  315. #ifdef LOUDLY
  316. OutputDebugString(L"File successfully created\n");
  317. #endif
  318. g_hFile = hFile;
  319. return hFile;
  320. }
  321. /*
  322. DWORD ReadPrivateData(PWSTR,LPBYTE *,INT *)
  323. DWORD WritePrivateData(PWSTR,LPBYTE,INT)
  324. These functions read or write a reasonably short block of data to a disk
  325. device, avoiding buffering of the data. This allows the data to be wiped
  326. by the client before the buffers are released.
  327. The DWORD return value is that which would return from GetLastError() and
  328. can be handled accordingly.
  329. ReadPrivateData() returns a malloc'd pointer which must be freed by the client. It
  330. also returns the count of bytes read from the medium to the INT *. The file is
  331. closed following the read operation before the function returns.
  332. WritePrivateData() writes a count of bytes from LPBYTE to the disk. When it returns,
  333. the buffer used to do so has been flushed and the file is closed.
  334. */
  335. /*
  336. prgb = byte ptr to data returned from the read
  337. piCount = size of active data field within the buffer
  338. Note that even if the read fails (file not found, read error, etc.) the buffer
  339. ptr is still valid.
  340. */
  341. //ReadFile(c_hFile,c_pPrivate,c_cbPrivate,&c_cbPrivate,NULL) return bytes read
  342. INT ReadPrivateData(BYTE **prgb,INT *piCount)
  343. {
  344. LPVOID lpv;
  345. DWORD dwBytesRead;
  346. if (NULL == prgb) return 0;
  347. if (NULL == piCount) return 0;
  348. if (g_hFile)
  349. {
  350. lpv = CreateFileBuffer(g_iFileSize,g_iSectorSize);
  351. if (NULL == lpv)
  352. {
  353. *prgb = 0; // indicate no need to free this buffer
  354. *piCount = 0;
  355. return 0;
  356. }
  357. *prgb = (BYTE *)lpv; // even if no data, gotta free using VirtualFree()
  358. *piCount = 0;
  359. if (0 == ReadFile(g_hFile,lpv,g_iBufferSize,&dwBytesRead,NULL)) return 0;
  360. *piCount = g_iFileSize;
  361. #ifdef LOUDLY
  362. OutputDebugString(L"ReadPrivateData success\n");
  363. #endif
  364. return g_iFileSize;
  365. }
  366. return 0;
  367. }
  368. /*
  369. Write data to file at g_rgwczFileName
  370. Convert size to multiple of sector size
  371. Alloc buffer
  372. Copy data to buffer
  373. Write data
  374. Scrub Buffer, release
  375. return 0
  376. */
  377. BOOL WritePrivateData(BYTE *lpData,INT icbData) {
  378. DWORD dwcb = 0;
  379. LPVOID lpv;
  380. if (NULL == g_hFile) return FALSE;
  381. if (NULL == lpData) return FALSE;
  382. if (0 == icbData) return FALSE;
  383. if (g_hFile)
  384. {
  385. g_iFileSize = icbData;
  386. lpv = CreateFileBuffer(g_iFileSize,g_iSectorSize);
  387. if (NULL == lpv)
  388. {
  389. return FALSE;
  390. }
  391. ZeroMemory(lpv,g_iBufferSize);
  392. memcpy(lpv,lpData,icbData);
  393. WriteFile(g_hFile,lpv,g_iBufferSize,&dwcb,NULL);
  394. VirtualFree(lpv,g_iBufferSize,MEM_RELEASE);
  395. }
  396. // ret TRUE iff file write succeeds and count of bytes is correct
  397. #ifdef LOUDLY
  398. if (dwcb) OutputDebugString(L"WritePrivateData succeeded\n");
  399. else OutputDebugString(L"WritePrivateData failed ***\n");
  400. #endif
  401. if (dwcb != g_iBufferSize) return FALSE;
  402. else return TRUE;
  403. }