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.

637 lines
16 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. wsbfmt.cpp
  5. Abstract:
  6. This module implements file-system formatting support routines
  7. Author:
  8. Ravisankar Pudipeddi [ravisp] 19, January 2000
  9. Revision History:
  10. --*/
  11. #include <stdafx.h>
  12. extern "C" {
  13. #include <ntdddisk.h>
  14. #include <fmifs.h>
  15. }
  16. #include <wsbfmt.h>
  17. #define MAX_FS_NAME_SIZE 256
  18. #define MAX_PARAMS 20
  19. #define INVALID_KEY 0
  20. typedef struct _FORMAT_PARAMS {
  21. PWSTR volumeSpec;
  22. PWSTR label;
  23. PWSTR fsName;
  24. LONG fsType;
  25. ULONG fsflags;
  26. ULONG allocationUnitSize; // Cluster size in Bytes
  27. HRESULT result;
  28. ULONG threadId;
  29. PFMIFS_ENABLECOMP_ROUTINE compressRoutine;
  30. PFMIFS_FORMAT_ROUTINE formatRoutine;
  31. PFMIFS_FORMATEX2_ROUTINE formatRoutineEx;
  32. BOOLEAN quick;
  33. BOOLEAN force;
  34. BOOLEAN cancel;
  35. } FORMAT_PARAMS, *PFORMAT_PARAMS;
  36. typedef struct _FM_ENTRY {
  37. ULONG key;
  38. PFORMAT_PARAMS val;
  39. } FM_ENTRY, *PFM_ENTRY;
  40. static FM_ENTRY formatParamsTable[MAX_PARAMS];
  41. static PFMIFS_FORMATEX2_ROUTINE FormatRoutineEx = NULL;
  42. static PFMIFS_FORMAT_ROUTINE FormatRoutine = NULL;
  43. static PFMIFS_SETLABEL_ROUTINE LabelRoutine = NULL;
  44. static PFMIFS_ENABLECOMP_ROUTINE CompressRoutine = NULL;
  45. static HINSTANCE IfsDllHandle = NULL;
  46. void MountFileSystem(PWSTR volumeSpec);
  47. HRESULT GetFormatParam(IN ULONG key, OUT PFORMAT_PARAMS *fp)
  48. /*++
  49. Routine Description:
  50. Returns the format parameter structure indexed by the
  51. supplied key
  52. Arguments:
  53. key - key indexing the format params
  54. fp - pointer to format params returned in this var.
  55. Return Value:
  56. S_OK if found
  57. S_FALSE if not
  58. --*/
  59. {
  60. HRESULT hr = S_FALSE;
  61. ULONG i;
  62. WsbTraceIn(OLESTR("GetFormatParam"), OLESTR(""));
  63. for (i = 0; i < MAX_PARAMS; i++) {
  64. if (formatParamsTable[i].key == key) {
  65. hr = S_OK;
  66. *fp = formatParamsTable[i].val;
  67. break;
  68. }
  69. }
  70. WsbTraceOut(OLESTR("GetFormatParam"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  71. return hr;
  72. }
  73. HRESULT SetFormatParam(IN ULONG key, IN PFORMAT_PARAMS fp)
  74. /*++
  75. Routine Description:
  76. Finds a free slot and stores the supplied format params,
  77. indexed by the key
  78. Arguments:
  79. key - key indexing the format params
  80. fp - pointer to format params
  81. Return Value:
  82. S_OK - Found a slot and stored the format params
  83. E_OUTOFMEMORY - Couldn't find a slot: too many formats in progress
  84. --*/
  85. {
  86. HRESULT hr = E_OUTOFMEMORY;
  87. ULONG i;
  88. WsbTraceIn(OLESTR("SetFormatParam"), OLESTR(""));
  89. for (i = 0; i < MAX_PARAMS; i++) {
  90. if (formatParamsTable[i].key == INVALID_KEY) {
  91. hr = S_OK;
  92. formatParamsTable[i].val = fp;
  93. formatParamsTable[i].key = key;
  94. break;
  95. }
  96. }
  97. WsbTraceOut(OLESTR("SetFormatParam"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  98. return hr;
  99. }
  100. HRESULT DeleteFormatParam(IN ULONG key)
  101. /*++
  102. Routine Description:
  103. Locates the format params indexed by the key, deletes all allocated structures
  104. and frees up the slot
  105. Arguments:
  106. key - key indexing the format params
  107. Return Value:
  108. S_OK - if format params found and deleted
  109. E_FAIL - if not
  110. --*/
  111. {
  112. PFORMAT_PARAMS formatParams;
  113. HRESULT hr = E_FAIL;
  114. ULONG i;
  115. WsbTraceIn(OLESTR("DeleteFormatParam"), OLESTR(""));
  116. for (i = 0; i < MAX_PARAMS; i++) {
  117. if (formatParamsTable[i].key == key) {
  118. hr = S_OK;
  119. formatParams = formatParamsTable[i].val;
  120. if (formatParams) {
  121. if (formatParams->volumeSpec) {
  122. delete [] formatParams->volumeSpec;
  123. }
  124. if (formatParams->label) {
  125. delete [] formatParams->label;
  126. }
  127. if (formatParams->fsName) {
  128. delete [] formatParams->fsName;
  129. }
  130. }
  131. formatParamsTable[i].key = INVALID_KEY;
  132. formatParamsTable[i].val = NULL;
  133. break;
  134. }
  135. }
  136. WsbTraceOut(OLESTR("DeleteFormatParam"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  137. return hr;
  138. }
  139. BOOL
  140. LoadIfsDll(void)
  141. /*++
  142. Routine Description:
  143. Loads the FMIFS DLL and stores the handle to it in IfsDllHandle
  144. Also sets the FormatXXX, LabelXXX, CompressXXX routines
  145. Arguments:
  146. None
  147. Return Value:
  148. TRUE if dll was loaded successfully
  149. FALSE if not
  150. --*/
  151. {
  152. BOOL retVal = TRUE;
  153. WsbTraceIn(OLESTR("LoadIfsDll"), OLESTR(""));
  154. if (IfsDllHandle != NULL) {
  155. // Library is already loaded and the routines needed
  156. // have been located.
  157. retVal = TRUE;
  158. goto exit;
  159. }
  160. IfsDllHandle = LoadLibrary(L"fmifs.dll");
  161. if (IfsDllHandle == (HANDLE)NULL) {
  162. // FMIFS not available.
  163. retVal = FALSE;
  164. goto exit;
  165. }
  166. // Library is loaded. Locate the two routines needed
  167. FormatRoutineEx = (PFMIFS_FORMATEX2_ROUTINE) GetProcAddress(IfsDllHandle, "FormatEx2");
  168. FormatRoutine = (PFMIFS_FORMAT_ROUTINE) GetProcAddress(IfsDllHandle, "Format");
  169. LabelRoutine = (PFMIFS_SETLABEL_ROUTINE) GetProcAddress(IfsDllHandle, "SetLabel");
  170. CompressRoutine = (PFMIFS_ENABLECOMP_ROUTINE) GetProcAddress(IfsDllHandle,
  171. "EnableVolumeCompression");
  172. if (!FormatRoutine || !LabelRoutine || !FormatRoutineEx) {
  173. // Couldn't find something, so shut down all access
  174. // to the library by ensuring FormatRoutine is NULL
  175. FreeLibrary(IfsDllHandle);
  176. FormatRoutine = NULL;
  177. FormatRoutineEx = NULL;
  178. LabelRoutine = NULL;
  179. retVal = FALSE;
  180. }
  181. exit:
  182. WsbTraceOut(OLESTR("LoadIfsDll"), OLESTR("result = <%ls>"), WsbBoolAsString(retVal));
  183. return retVal;
  184. }
  185. void
  186. UnloadIfsDll(void)
  187. /*++
  188. Routine Description:
  189. Unloads the FMIFS dll
  190. Arguments:
  191. none
  192. Return Value:
  193. TRUE if unloaded
  194. --*/
  195. {
  196. WsbTraceIn(OLESTR("UnloadIfsDll"), OLESTR(""));
  197. if (IfsDllHandle != (HANDLE) NULL) {
  198. FreeLibrary(IfsDllHandle);
  199. FormatRoutine = NULL;
  200. FormatRoutineEx = NULL;
  201. IfsDllHandle = NULL;
  202. LabelRoutine = NULL;
  203. }
  204. WsbTraceOut(OLESTR("UnloadIfsDll"), OLESTR(""));
  205. }
  206. BOOL
  207. FmIfsCallback(IN FMIFS_PACKET_TYPE PacketType,
  208. IN ULONG PacketLength,
  209. IN PVOID PacketData)
  210. /*++
  211. Routine Description:
  212. This routine gets callbacks from fmifs.dll regarding
  213. progress and status of the ongoing format
  214. Arguments:
  215. [PacketType] -- an fmifs packet type
  216. [PacketLength] -- length of the packet data
  217. [PacketData] -- data associated with the packet
  218. Return Value:
  219. TRUE if the fmifs activity should continue, FALSE if the
  220. activity should halt immediately.
  221. --*/
  222. {
  223. BOOL ret = TRUE;
  224. WCHAR driveName[256];
  225. PFORMAT_PARAMS formatParams;
  226. UNREFERENCED_PARAMETER(PacketLength);
  227. WsbTraceIn(OLESTR("FmIfsCallback"), OLESTR(""));
  228. if (GetFormatParam(GetCurrentThreadId(), &formatParams) != S_OK) {
  229. formatParams->result = E_FAIL;
  230. goto exit;
  231. }
  232. //
  233. // Cancel if needed
  234. //
  235. if (formatParams->cancel) {
  236. formatParams->result = E_ABORT;
  237. } else {
  238. switch (PacketType) {
  239. case FmIfsPercentCompleted:
  240. if (((PFMIFS_PERCENT_COMPLETE_INFORMATION)
  241. PacketData)->PercentCompleted % 10 == 0) {
  242. WsbTrace(L"FmIfsPercentCompleted: %d%%\n",
  243. ((PFMIFS_PERCENT_COMPLETE_INFORMATION)
  244. PacketData)->PercentCompleted);
  245. }
  246. break;
  247. case FmIfsFormatReport:
  248. WsbTrace(OLESTR("Format total kB: %d available kB %d\n"),
  249. ((PFMIFS_FORMAT_REPORT_INFORMATION)PacketData)->KiloBytesTotalDiskSpace,
  250. ((PFMIFS_FORMAT_REPORT_INFORMATION)PacketData)->KiloBytesAvailable);
  251. break;
  252. case FmIfsIncompatibleFileSystem:
  253. formatParams->result = WSB_E_INCOMPATIBLE_FILE_SYSTEM;
  254. break;
  255. case FmIfsInsertDisk:
  256. break;
  257. case FmIfsFormattingDestination:
  258. break;
  259. case FmIfsIncompatibleMedia:
  260. formatParams->result = WSB_E_BAD_MEDIA;
  261. break;
  262. case FmIfsAccessDenied:
  263. formatParams->result = E_ACCESSDENIED;
  264. break;
  265. case FmIfsMediaWriteProtected:
  266. formatParams->result = WSB_E_WRITE_PROTECTED;
  267. break;
  268. case FmIfsCantLock:
  269. formatParams->result = WSB_E_CANT_LOCK;
  270. break;
  271. case FmIfsBadLabel:
  272. formatParams->result = WSB_E_BAD_LABEL;
  273. break;
  274. case FmIfsCantQuickFormat:
  275. formatParams->result = WSB_E_CANT_QUICK_FORMAT;
  276. break;
  277. case FmIfsIoError:
  278. formatParams->result = WSB_E_IO_ERROR;
  279. break;
  280. case FmIfsVolumeTooSmall:
  281. formatParams->result = WSB_E_VOLUME_TOO_SMALL;
  282. break;
  283. case FmIfsVolumeTooBig:
  284. formatParams->result = WSB_E_VOLUME_TOO_BIG;
  285. break;
  286. case FmIfsClusterSizeTooSmall:
  287. formatParams->result = E_FAIL;
  288. break;
  289. case FmIfsClusterSizeTooBig:
  290. formatParams->result = E_FAIL;
  291. break;
  292. case FmIfsClustersCountBeyond32bits:
  293. formatParams->result = E_FAIL;
  294. break;
  295. case FmIfsFinished:
  296. if (formatParams->result == S_OK) {
  297. ret = ((PFMIFS_FINISHED_INFORMATION) PacketData)->Success;
  298. if (ret) {
  299. MountFileSystem(formatParams->volumeSpec);
  300. WsbTrace(OLESTR("Format finished for %S filesystem on %S label %S\n"),
  301. formatParams->fsName, formatParams->volumeSpec, formatParams->label );
  302. if ((formatParams->compressRoutine != NULL) && !wcscmp(formatParams->fsName , L"NTFS") && (formatParams->fsflags & WSBFMT_ENABLE_VOLUME_COMPRESSION)) {
  303. swprintf(driveName, L"%s\\", formatParams->volumeSpec);
  304. (formatParams->compressRoutine)(driveName, COMPRESSION_FORMAT_DEFAULT);
  305. }
  306. } else {
  307. WsbTrace(OLESTR("Format finished failure with ret = %d\n"),ret);
  308. formatParams->result = WSB_E_FORMAT_FAILED;
  309. }
  310. ret = FALSE;
  311. }
  312. break;
  313. default:
  314. break;
  315. }
  316. }
  317. exit:
  318. if (formatParams->result != S_OK) {
  319. ret = FALSE;
  320. }
  321. WsbTraceOut(OLESTR("FmIfsCallback"), OLESTR("result = <%ls>"), WsbBoolAsString(ret));
  322. return ret;
  323. }
  324. void
  325. MountFileSystem(PWSTR mountPoint)
  326. /*++
  327. Routine Description:
  328. Ensures a filesystem is mounted at the given root:
  329. a) Opens the mount point and closes it.
  330. b) Does a FindFirstFile on the mount point
  331. The latter may sound redundant but is not because if we create the first
  332. FAT32 filesystem then just opening and closing is not enough
  333. Arguments:
  334. mountPoint - path name to the root of filesystem to be mounted
  335. Return Value:
  336. none
  337. --*/
  338. {
  339. WCHAR buffer[1024];
  340. HANDLE handle;
  341. WIN32_FIND_DATA fileData;
  342. WsbTraceIn(OLESTR("MountFileSystem"), OLESTR(""));
  343. handle = CreateFile(mountPoint, GENERIC_READ | GENERIC_WRITE,
  344. FILE_SHARE_READ | FILE_SHARE_WRITE,
  345. 0, OPEN_EXISTING, 0, 0);
  346. if (handle != INVALID_HANDLE_VALUE)
  347. CloseHandle(handle);
  348. swprintf(buffer,L"%s\\*.*",mountPoint);
  349. /*
  350. * Go ahead and try to find the first file, this will make sure that
  351. * the file system is mounted
  352. */
  353. handle = FindFirstFile(buffer, &fileData);
  354. if (handle != INVALID_HANDLE_VALUE) {
  355. FindClose(handle);
  356. }
  357. WsbTraceOut(OLESTR("MountFileSystem"), OLESTR(""));
  358. }
  359. void
  360. FormatVolume(IN PFORMAT_PARAMS params)
  361. /*++
  362. Routine Description:
  363. This routine format the volume described by params
  364. Arguments:
  365. params - pointer to the FORMAT_PARAMS describing the volume,
  366. file system to be formatted to, quick/force etc.
  367. Return Value:
  368. None.
  369. params->result contains the result of this operation
  370. --*/
  371. {
  372. FMIFS_FORMATEX2_PARAM exParam;
  373. HRESULT hr = S_OK;
  374. WsbTraceIn(OLESTR("FormatVolume"), OLESTR(""));
  375. /*
  376. * Get the object corresponding to the storage Id and
  377. * and notify all clients that the region has changed
  378. * i.e. there is a format in progress on that region
  379. */
  380. memset(&exParam, 0, sizeof(exParam));
  381. exParam.Major = 1;
  382. exParam.Minor = 0;
  383. if (params->quick) {
  384. exParam.Flags |= FMIFS_FORMAT_QUICK;
  385. }
  386. if (params->force) {
  387. exParam.Flags |= FMIFS_FORMAT_FORCE;
  388. }
  389. exParam.LabelString = params->label;
  390. exParam.ClusterSize = params->allocationUnitSize;
  391. (params->formatRoutineEx)(params->volumeSpec,
  392. FmMediaUnknown,
  393. params->fsName,
  394. &exParam,
  395. (FMIFS_CALLBACK)&FmIfsCallback);
  396. if (params->result == NULL) {
  397. /* Format is successful so we lock unlock the filesystem */
  398. MountFileSystem(params->volumeSpec);
  399. }
  400. DeleteFormatParam(params->threadId);
  401. WsbTraceOut(OLESTR("FormatVolume"), OLESTR(""));
  402. }
  403. HRESULT
  404. FormatPartition(IN PWSTR volumeSpec,
  405. IN LONG fsType,
  406. IN PWSTR label,
  407. IN ULONG fsflags,
  408. IN BOOLEAN quick,
  409. IN BOOLEAN force,
  410. IN ULONG allocationUnitSize)
  411. /*++
  412. Routine Description:
  413. Entry point for formatting a volume.
  414. No defaults are assumed and all parameters need to be supplied
  415. Arguments:
  416. volumeSpec - Drive letter or name of volume
  417. fsType - One of FSTYPE_FAT, FSTYPE_FAT32, FSTYE_NTFS
  418. label - Volume label to be assigned to the partition/volume
  419. fsflags - Flags describing desired characteristics
  420. quick - If TRUE, a quick format is attempted
  421. force - If TRUE a force format is done
  422. allocationUnitSize -
  423. cluster size
  424. Return Value:
  425. Result of the operation
  426. --*/
  427. {
  428. FORMAT_PARAMS params;
  429. WsbTraceIn(OLESTR("FormatPartition"), OLESTR(""));
  430. if (fsType > 0 && !LoadIfsDll()) // fsType is +ve for FAT, FAT32 and NTFS which are supported by fmifs
  431. {
  432. // could not load the Dll
  433. WsbTrace(OLESTR("Can't load fmifs.dll\n"));
  434. return E_FAIL;
  435. }
  436. params.volumeSpec = new WCHAR[wcslen(volumeSpec) + 1];
  437. if (params.volumeSpec == NULL) {
  438. return E_OUTOFMEMORY;
  439. }
  440. params.label = new WCHAR[wcslen(label) + 1];
  441. if (params.label == NULL) {
  442. delete [] params.volumeSpec;
  443. return E_OUTOFMEMORY;
  444. }
  445. params.fsName = new WCHAR[MAX_FS_NAME_SIZE];
  446. if (params.fsName == NULL) {
  447. delete [] params.volumeSpec;
  448. delete [] params.label;
  449. return E_OUTOFMEMORY;
  450. }
  451. if (fsType > 0) {
  452. wcscpy(params.fsName, (fsType == FSTYPE_FAT ? L"FAT" :
  453. (fsType == FSTYPE_FAT32 ? L"FAT32" : L"NTFS")));
  454. }
  455. wcscpy(params.volumeSpec, volumeSpec);
  456. wcscpy(params.label, label);
  457. params.fsType = fsType;
  458. params.fsflags = fsflags;
  459. params.allocationUnitSize = allocationUnitSize;
  460. params.quick = quick;
  461. params.force = force;
  462. params.result = S_OK;
  463. params.cancel = FALSE;
  464. params.formatRoutine = FormatRoutine;
  465. params.formatRoutineEx = FormatRoutineEx;
  466. params.compressRoutine = CompressRoutine;
  467. params.threadId = GetCurrentThreadId();
  468. if (SetFormatParam(params.threadId, &params) != S_OK) {
  469. delete [] params.label;
  470. delete [] params.volumeSpec;
  471. delete [] params.fsName;
  472. return E_OUTOFMEMORY;
  473. };
  474. FormatVolume(&params);
  475. WsbTraceOut(OLESTR("FormatPartition"), OLESTR("result = <%ls>"), WsbHrAsString(params.result));
  476. return params.result;
  477. }