Leaked source code of windows server 2003
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.

377 lines
8.4 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. format.cpp
  5. Abstract:
  6. Routines to format volumes, using file-system information passed
  7. in. Uses undocumented fmifs calls.
  8. Authors:
  9. Steve DeVos (Veritas) (v-stevde) 15-May-1998
  10. Guhan Suriyanarayanan (guhans) 21-Aug-1999
  11. Environment:
  12. User-mode only.
  13. Revision History:
  14. 15-May-1998 v-stevde Initial creation
  15. 21-Aug-1999 guhans Cleaned up and re-wrote this module.
  16. --*/
  17. #include "stdafx.h"
  18. #include <winioctl.h>
  19. #include "fmifs.h"
  20. #include "asr_fmt.h"
  21. #include "asr_dlg.h"
  22. BOOL g_bFormatInProgress = FALSE;
  23. BOOL g_bFormatSuccessful = FALSE;
  24. INT g_iFormatPercentComplete = 0;
  25. HINSTANCE g_hIfsDll = NULL;
  26. INT FormatVolumeThread(PASRFMT_VOLUME_INFO pVolume);
  27. PFMIFS_FORMATEX_ROUTINE g_FormatRoutineEx = NULL;
  28. BOOL
  29. FormatInitialise() {
  30. //
  31. // Loadlib if needed
  32. //
  33. if (!g_hIfsDll) {
  34. g_hIfsDll = LoadLibrary(L"fmifs.dll");
  35. if (!g_hIfsDll) {
  36. //
  37. // FMIFS not available
  38. //
  39. return FALSE;
  40. }
  41. g_FormatRoutineEx = (PFMIFS_FORMATEX_ROUTINE)GetProcAddress(g_hIfsDll, "FormatEx");
  42. if (!g_FormatRoutineEx) {
  43. return FALSE;
  44. }
  45. }
  46. return TRUE;
  47. }
  48. BOOL
  49. IsFsTypeOkay(
  50. IN PASRFMT_VOLUME_INFO pVolume,
  51. OUT PBOOL pIsLabelIntact
  52. )
  53. {
  54. WCHAR currentFSName[ASRFMT_CCH_FS_NAME];
  55. WCHAR szVolumeGuid[ASRFMT_CCH_VOLUME_GUID];
  56. WCHAR currentLabel[ASRFMT_CCH_VOLUME_LABEL];
  57. DWORD cchGuid = 0;
  58. BOOL fsOkay = TRUE,
  59. result = TRUE;
  60. ASSERT(pIsLabelIntact);
  61. ZeroMemory(currentFSName, sizeof(WCHAR) * ASRFMT_CCH_FS_NAME);
  62. *pIsLabelIntact = TRUE;
  63. if (wcslen(pVolume->szGuid) >= ASRFMT_CCH_VOLUME_GUID) {
  64. return TRUE; // something's wrong with this GUID
  65. }
  66. if ((wcslen(pVolume->szFsName) <= 0)) {
  67. return TRUE; // no check for RAW volumes
  68. }
  69. //
  70. // We don't want the "please insert floppy in drive A" messages ...
  71. //
  72. SetErrorMode(SEM_FAILCRITICALERRORS);
  73. //
  74. // GetVolumeInformation needs the volume guid in the dos-name-space, while the
  75. // the sif file has the volume guid in the nt-name-space. Convert
  76. // the name by changing the \??\ at the beginning to \\?\, and adding
  77. // a back-slash at the end.
  78. //
  79. cchGuid = wcslen(pVolume->szGuid);
  80. wcsncpy(szVolumeGuid, pVolume->szGuid, cchGuid);
  81. szVolumeGuid[1] = L'\\';
  82. szVolumeGuid[cchGuid] = L'\\'; // Trailing back-slash
  83. szVolumeGuid[cchGuid+1] = L'\0';
  84. fsOkay = TRUE;
  85. //
  86. // Call GetVolumeInfo to see if the FS is the same
  87. //
  88. result = GetVolumeInformation(szVolumeGuid,
  89. currentLabel, // lpVolumeNameBuffer
  90. ASRFMT_CCH_VOLUME_LABEL, // nVolumeNameSize
  91. NULL, // lpVolumeSerialNumber
  92. NULL, // lpMaximumComponentLength
  93. NULL, // lpFileSystemFlags
  94. currentFSName,
  95. ASRFMT_CCH_FS_NAME
  96. );
  97. if ((!result) ||
  98. wcscmp(currentFSName, pVolume->szFsName)
  99. ) {
  100. fsOkay = FALSE;
  101. *pIsLabelIntact = FALSE;
  102. }
  103. if (wcscmp(currentLabel, pVolume->szLabel)) {
  104. *pIsLabelIntact = FALSE;
  105. }
  106. /* if (fsOkay) {
  107. //
  108. //
  109. // Call FindFirst in root to see if drive is readable.
  110. // guhans: If drive is empty but formatted, this will still
  111. // say fsOkay = FALSE;
  112. //
  113. hFindData = FindFirstFile(szPath, &win32FindData);
  114. if (!hFindData || (INVALID_HANDLE_VALUE == hFindData)) {
  115. fsOkay = FALSE;
  116. }
  117. }
  118. */
  119. return fsOkay;
  120. }
  121. BOOL
  122. IsVolumeIntact(
  123. IN PASRFMT_VOLUME_INFO pVolume
  124. ){
  125. //
  126. // Call autochk to see if the FS is intact
  127. //
  128. return TRUE;
  129. }
  130. ///
  131. // Asynchronous function to launch the format routine.
  132. //
  133. BOOL
  134. FormatVolume(
  135. IN PASRFMT_VOLUME_INFO pVolume
  136. )
  137. {
  138. HANDLE hThread = NULL;
  139. //
  140. // Set the global flags
  141. //
  142. g_bFormatInProgress = TRUE;
  143. g_bFormatSuccessful = TRUE;
  144. g_iFormatPercentComplete = 0;
  145. //
  146. // Loadlib if needed
  147. //
  148. if (!g_hIfsDll && !FormatInitialise()) {
  149. g_bFormatSuccessful = FALSE;
  150. g_bFormatInProgress = FALSE;
  151. return FALSE;
  152. }
  153. hThread = CreateThread(
  154. NULL,
  155. 0,
  156. (LPTHREAD_START_ROUTINE) FormatVolumeThread,
  157. pVolume,
  158. 0,
  159. NULL
  160. );
  161. if (!hThread || (INVALID_HANDLE_VALUE == hThread)) {
  162. g_bFormatSuccessful = FALSE;
  163. g_bFormatInProgress = FALSE;
  164. return FALSE;
  165. }
  166. return TRUE;
  167. }
  168. BOOL
  169. FormatCleanup() {
  170. if (g_hIfsDll) {
  171. FreeLibrary(g_hIfsDll);
  172. g_hIfsDll = NULL;
  173. g_FormatRoutineEx = NULL;
  174. }
  175. return TRUE;
  176. }
  177. FmIfsCallback(
  178. IN FMIFS_PACKET_TYPE PacketType,
  179. IN DWORD PacketLength,
  180. IN PVOID PacketData
  181. )
  182. {
  183. switch (PacketType) {
  184. case FmIfsPercentCompleted:
  185. g_iFormatPercentComplete = ((PFMIFS_PERCENT_COMPLETE_INFORMATION)PacketData)->PercentCompleted ;
  186. break;
  187. case FmIfsFormattingDestination:
  188. case FmIfsInsertDisk:
  189. case FmIfsFormatReport:
  190. case FmIfsHiddenStatus:
  191. default:
  192. break;
  193. case FmIfsFinished:
  194. g_bFormatSuccessful = g_bFormatSuccessful &&
  195. ((PFMIFS_FINISHED_INFORMATION) PacketData)->Success;
  196. g_iFormatPercentComplete = 101;
  197. g_bFormatInProgress = FALSE;
  198. break;
  199. case FmIfsIncompatibleFileSystem:
  200. case FmIfsIncompatibleMedia:
  201. case FmIfsAccessDenied:
  202. case FmIfsMediaWriteProtected:
  203. case FmIfsCantLock:
  204. case FmIfsBadLabel:
  205. case FmIfsCantQuickFormat:
  206. case FmIfsIoError:
  207. case FmIfsVolumeTooSmall:
  208. case FmIfsVolumeTooBig:
  209. case FmIfsClusterSizeTooSmall:
  210. case FmIfsClusterSizeTooBig:
  211. g_bFormatSuccessful = FALSE;
  212. break;
  213. }
  214. return TRUE;
  215. }
  216. INT FormatVolumeThread(PASRFMT_VOLUME_INFO pVolume)
  217. {
  218. WCHAR szPath[ASRFMT_CCH_DEVICE_PATH + 1];
  219. swprintf(szPath, TEXT("\\\\?%s"), pVolume->szGuid+3);
  220. (g_FormatRoutineEx)(szPath,
  221. FmMediaUnknown,
  222. pVolume->szFsName,
  223. pVolume->szLabel,
  224. #if 0
  225. TRUE, // Quick Format for testing
  226. #else
  227. g_bQuickFormat,
  228. #endif
  229. pVolume->dwClusterSize,
  230. (FMIFS_CALLBACK) &FmIfsCallback
  231. );
  232. return TRUE;
  233. }
  234. VOID
  235. MountFileSystem(
  236. IN PASRFMT_VOLUME_INFO pVolume
  237. )
  238. /*++
  239. (based on code in base\fs\utils\hsm\wsb\wsbfmt.cpp)
  240. Routine Description:
  241. Ensures a filesystem is mounted at the given root:
  242. a) Opens the mount point and closes it.
  243. b) Does a FindFirstFile on the mount point
  244. The latter may sound redundant but is not because if we create the first
  245. FAT32 filesystem then just opening and closing is not enough
  246. Arguments:
  247. Return Value:
  248. none
  249. --*/
  250. {
  251. WCHAR szPath[ASRFMT_CCH_DEVICE_PATH + 1];
  252. HANDLE handle = NULL;
  253. WIN32_FIND_DATA win32FindData;
  254. if (!pVolume) {
  255. ASSERT(0 && L"pVolume is NULL");
  256. return;
  257. }
  258. if (!memcmp(pVolume->szDosPath, ASRFMT_WSZ_DOS_DEVICES_PREFIX, ASRFMT_CB_DOS_DEVICES_PREFIX)) {
  259. swprintf(szPath, L"\\\\?\\%ws", pVolume->szDosPath + wcslen(ASRFMT_WSZ_DOS_DEVICES_PREFIX));
  260. }
  261. else {
  262. swprintf(szPath, L"\\\\%ws", pVolume->szDosPath + 2);
  263. }
  264. handle = CreateFile(
  265. szPath,
  266. GENERIC_READ | GENERIC_WRITE,
  267. FILE_SHARE_READ | FILE_SHARE_WRITE,
  268. 0,
  269. OPEN_EXISTING,
  270. 0,
  271. 0
  272. );
  273. if ((handle) && (INVALID_HANDLE_VALUE != handle)) {
  274. CloseHandle(handle);
  275. }
  276. //
  277. // Try to find the first file, this will make sure that
  278. // the file system is mounted
  279. //
  280. if (!memcmp(pVolume->szDosPath, ASRFMT_WSZ_DOS_DEVICES_PREFIX, ASRFMT_CB_DOS_DEVICES_PREFIX)) {
  281. swprintf(szPath, L"\\\\?\\%ws\\*", pVolume->szDosPath + wcslen(ASRFMT_WSZ_DOS_DEVICES_PREFIX));
  282. }
  283. else {
  284. swprintf(szPath, L"\\\\%ws\\*", pVolume->szDosPath + 2);
  285. }
  286. handle = FindFirstFile(szPath, &win32FindData);
  287. if ((handle) && (INVALID_HANDLE_VALUE != handle)) {
  288. FindClose(handle);
  289. }
  290. }