PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/Visual Studio 2010/CppVDSFormatVolume/CppVDSFormatVolume.cpp

#
C++ | 484 lines | 394 code | 53 blank | 37 comment | 47 complexity | c75dfb2fb0dfcc780fea1a2baf7a3286 MD5 | raw file
  1. /****************************** Module Header ******************************\
  2. Module Name: CppVDSFormatVolume.cpp
  3. Project: CppVDSFormatVolume (VDS Format Volume)
  4. Copyright (c) Microsoft Corporation.
  5. Demonstrates how to use VDS to format volumes.
  6. This source is subject to the Microsoft Public License.
  7. See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
  8. All other rights reserved.
  9. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
  10. EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  11. WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
  12. \***************************************************************************/
  13. #include <windows.h>
  14. #include <winioctl.h>
  15. #include <stdio.h>
  16. #define DEFIND_GUID
  17. #include <initguid.h>
  18. #include <vds.h>
  19. // Turn off do..while(TRUE) warnings.
  20. #pragma warning(disable: 4127)
  21. #define SAFE_RELEASE(x) if (x) { x->Release(); x = NULL; }
  22. #define SAFE_FREE(x) if (x) { CoTaskMemFree(x); }
  23. #define GUID_LEN 50
  24. wchar_t *HealthString[] =
  25. {
  26. L"UNKNOWN",
  27. L"HEALTHY",
  28. L"REBUILDING",
  29. L"STALE",
  30. L"FAILING",
  31. L"FAILING_REDUNDANCY",
  32. L"FAILED_REDUNDANCY",
  33. L"FAILED_REDUNDANCY_FAILING",
  34. L"FAILED"
  35. };
  36. wchar_t *TypeString[] =
  37. {
  38. L"UNKNOWN",
  39. L"SIMPLE",
  40. L"SPAN",
  41. L"STRIPE",
  42. L"MIRROR",
  43. L"PARITY"
  44. };
  45. wchar_t *StatusString[] =
  46. {
  47. L"UNKNOWN",
  48. L"ONLINE",
  49. L"NOT_READY",
  50. L"NO_MEDIA",
  51. L"FAILED"
  52. };
  53. wchar_t *TransitionStateString[] =
  54. {
  55. L"UNKNOWN",
  56. L"STABLE",
  57. L"EXTENDING",
  58. L"SHRINKING",
  59. L"RECONFIGING"
  60. };
  61. wchar_t *FileSystemString[] =
  62. {
  63. L"UNKNOWN",
  64. L"RAW",
  65. L"FAT",
  66. L"FAT32",
  67. L"NTFS",
  68. L"CDFS",
  69. L"UDF"
  70. };
  71. wchar_t *ExtentTypeString[] =
  72. {
  73. L"UNKNOWN",
  74. L"FREE",
  75. L"DATA",
  76. L"OEM",
  77. L"ESP",
  78. L"MSR",
  79. L"LMD",
  80. L"UNUSABLE"
  81. };
  82. void usage()
  83. {
  84. printf("CppVDSFormatVolume.exe [-options]...\n");
  85. printf(" -v <volume number (decimal)> REQUIRED INPUT\n");
  86. printf(" -t <target file system type: NTFS, FAT32, etc.> UPPER CASE ONLY, REQUIRED INPUT\n");
  87. printf(" e.g.: format -v 3 -t NTFS\n");
  88. }
  89. int wmain(int argc, wchar_t *argv[])
  90. {
  91. HRESULT hr, AsyncHr;
  92. IEnumVdsObject *pEnum = NULL;
  93. IEnumVdsObject *pEnumPack = NULL;
  94. IEnumVdsObject *pEnumVolume = NULL;
  95. IVdsAsync *pAsync = NULL;
  96. VDS_ASYNC_OUTPUT AsyncOut;
  97. VDS_FILE_SYSTEM_TYPE FileSystemType;
  98. wchar_t buffer[500];
  99. int VolumeNumber = -1;
  100. int cargc = 1;
  101. BOOL opt_v = FALSE, opt_t = FALSE;
  102. wchar_t cmd;
  103. wchar_t szFsType[8];
  104. wchar_t szVolumeWin32Name[40];
  105. if (argc < 2)
  106. {
  107. usage();
  108. return 0;
  109. }
  110. cargc = 1;
  111. while (--argc > 0 && argv[cargc][0] == L'-')
  112. {
  113. cmd = argv[cargc++][1];
  114. //wprintf(L"cmd = %c\n", cmd);
  115. switch (cmd)
  116. {
  117. case L'v':
  118. case L'V':
  119. opt_v = TRUE;
  120. //wprintf(L"d = %s\n", argv[cargc]);
  121. swscanf_s(argv[cargc], L"%d", &VolumeNumber);
  122. cargc++, --argc; // Inc/decrement if there is a parameter
  123. swprintf_s(szVolumeWin32Name, _countof(szVolumeWin32Name),
  124. L"\\\\?\\GLOBALROOT\\Device\\HarddiskVolume%d", VolumeNumber);
  125. break;
  126. case L't':
  127. case L'T':
  128. //wprintf(L"t = %s\n", argv[cargc]);
  129. swscanf_s(argv[cargc], L"%s", szFsType, _countof(szFsType));
  130. // toupper
  131. cargc++, --argc; // inc/decrement if there is a parameter
  132. if (wcsncmp(szFsType, L"FAT32", 5) == 0)
  133. {
  134. opt_t = TRUE;
  135. FileSystemType = VDS_FST_FAT32;
  136. //printf("got FAT32 ..\n");
  137. }
  138. else if (wcsncmp(szFsType, L"NTFS", 4) == 0)
  139. {
  140. opt_t = TRUE;
  141. FileSystemType = VDS_FST_NTFS;
  142. //printf("got NTFS ..\n");
  143. }
  144. break;
  145. default:
  146. usage();
  147. break;
  148. }
  149. }
  150. if (!opt_v || !opt_t)
  151. {
  152. printf("insufficient input...\n");
  153. usage();
  154. return 0;
  155. }
  156. wprintf(L"ok to format volume %s, fs = %s? [y/n]\n",
  157. szVolumeWin32Name,
  158. szFsType);
  159. char c = (char) getchar();
  160. switch (c)
  161. {
  162. case 'y':
  163. case 'Y': break;
  164. default:
  165. printf("cancelling...\n");
  166. return 0;
  167. break;
  168. }
  169. printf("and off we go...\n");
  170. if (FAILED(CoInitialize(NULL)))
  171. {
  172. printf("CoInitialize() failed err=%d.\n", GetLastError());
  173. return 0;
  174. }
  175. hr = CoInitializeSecurity(
  176. NULL,
  177. -1,
  178. NULL,
  179. NULL,
  180. RPC_C_AUTHN_LEVEL_CONNECT,
  181. RPC_C_IMP_LEVEL_IMPERSONATE,
  182. NULL,
  183. 0,
  184. NULL
  185. );
  186. if (FAILED(hr))
  187. {
  188. printf("CoInitializeSecurity failed: hr=%X.\n", hr);
  189. return 0;
  190. }
  191. // Create a loader instance
  192. IVdsServiceLoader *pLoader;
  193. hr = CoCreateInstance(CLSID_VdsLoader,
  194. NULL,
  195. CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
  196. IID_IVdsServiceLoader,
  197. (void **)&pLoader
  198. );
  199. if (FAILED(hr))
  200. {
  201. printf("\nCoCreateInstance failed: hr=%X\n", hr);
  202. return 0;
  203. }
  204. // Load the service on the machine.
  205. IVdsService *pService;
  206. hr = pLoader->LoadService(L"", &pService);
  207. SAFE_RELEASE(pLoader);
  208. if (FAILED(hr))
  209. {
  210. printf("\nLoadService failed: hr=%X\n", hr);
  211. return 0;
  212. }
  213. // call QueryProviders
  214. hr = pService->QueryProviders(VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum);
  215. if (FAILED(hr))
  216. {
  217. printf("\nQueryProviders(VDS_QUERY_SOFTWARE_PROVIDERS) failed: hr=%X\n", hr);
  218. goto _bailout;
  219. }
  220. IUnknown *pUnk;
  221. IVdsProvider *pProvider;
  222. ULONG ulFetched = 0;
  223. int iProviderNumber = 1;
  224. BOOL fVolumeFound = FALSE;
  225. do
  226. {
  227. hr = pEnum->Next(1, &pUnk, &ulFetched);
  228. if (hr == S_FALSE)
  229. {
  230. break;
  231. }
  232. if (FAILED(hr))
  233. {
  234. printf("\npEnum->Next() failed: hr=%X\n", hr);
  235. goto _bailout;
  236. }
  237. // Get IVdsProvider
  238. hr = pUnk->QueryInterface(IID_IVdsProvider, (void **)&pProvider);
  239. SAFE_RELEASE(pUnk);
  240. if (FAILED(hr))
  241. {
  242. printf(" pUnk->QueryInterface(IVdsProvider) failed: hr=%X\n", hr);
  243. goto _bailout;
  244. }
  245. VDS_PROVIDER_PROP provProp;
  246. hr = pProvider->GetProperties(&provProp);
  247. if (SUCCEEDED(hr))
  248. {
  249. wprintf(L"Provider #: %ld name: %s\n", iProviderNumber++, provProp.pwszName);
  250. }
  251. // Get IVdsSwProvider
  252. IVdsSwProvider *pSwProvider;
  253. hr = pProvider->QueryInterface(IID_IVdsSwProvider, (void **)&pSwProvider);
  254. SAFE_RELEASE(pProvider);
  255. if (FAILED(hr))
  256. {
  257. printf(" pProvider->QueryInterface(IVdsSwProvider) failed: hr=%X\n", hr);
  258. goto _bailout;
  259. }
  260. // Enumerate packs associated with the software provider
  261. hr = pSwProvider->QueryPacks(&pEnumPack);
  262. SAFE_RELEASE(pSwProvider);
  263. if (FAILED(hr))
  264. {
  265. printf(" pSwProvider->QueryPacks() failed: hr=%X\n", hr);
  266. goto _bailout;
  267. }
  268. IUnknown *pPackUnk;
  269. ULONG ulFetchedPack;
  270. int iPackNumber = 1;
  271. // Enumerate the packs
  272. do
  273. {
  274. hr = pEnumPack->Next(1, &pPackUnk, &ulFetchedPack);
  275. if (hr == S_FALSE)
  276. {
  277. break;
  278. }
  279. if (FAILED(hr))
  280. {
  281. printf(" pEnumPack->Next() failed: hr=%X\n", hr);
  282. goto _bailout;
  283. }
  284. printf("Pack #: %ld\n", iPackNumber++);
  285. // Get IVdsPack
  286. IVdsPack *pPack;
  287. hr = pPackUnk->QueryInterface(IID_IVdsPack, (void **)&pPack);
  288. SAFE_RELEASE(pPackUnk);
  289. if (FAILED(hr))
  290. {
  291. printf(" pPackUnk->QueryInterface() failed: hr=%X\n", hr);
  292. goto _bailout;
  293. }
  294. // Get the volume enumerator to list volumes associated with the pack
  295. hr = pPack->QueryVolumes(&pEnumVolume);
  296. SAFE_RELEASE(pPack);
  297. if (FAILED(hr))
  298. {
  299. printf(" pPack->QueryVolumes() failed: hr=%X\n", hr);
  300. goto _bailout;
  301. }
  302. IUnknown *pVolumeUnk;
  303. ULONG ulFetchedVolume;
  304. int iVolumeNumber = 1;
  305. // Enumerate the volumes in the pack
  306. do
  307. {
  308. hr = pEnumVolume->Next(1, &pVolumeUnk, &ulFetchedVolume);
  309. if (hr == S_FALSE)
  310. {
  311. break; // end of enumeration
  312. }
  313. if (FAILED(hr))
  314. {
  315. printf("\n pEnumVolume->Next() failed: hr=%X\n", hr);
  316. goto _bailout;
  317. }
  318. printf("Volume #: %ld\n", iVolumeNumber++);
  319. // Get IVdsVolume
  320. IVdsVolume *pVolume;
  321. hr = pVolumeUnk->QueryInterface(IID_IVdsVolume, (void **)&pVolume);
  322. SAFE_RELEASE(pVolumeUnk);
  323. if (FAILED(hr))
  324. {
  325. printf(" pVolumeUnk->QueryInterface() failed: hr=%X\n", hr);
  326. goto _bailout;
  327. }
  328. // Get volume properties
  329. VDS_VOLUME_PROP VolumeProp;
  330. hr = pVolume->GetProperties(&VolumeProp);
  331. if (SUCCEEDED(hr))
  332. {
  333. StringFromGUID2(VolumeProp.id, buffer, GUID_LEN);
  334. wprintf(L" Volume Id: %s\n", buffer);
  335. wprintf(L" Type: %s\n", TypeString[VolumeProp.type - VDS_VT_SIMPLE + 1]);
  336. wprintf(L" Status: %s\n", StatusString[VolumeProp.status]);
  337. wprintf(L" Health: %s\n", HealthString[VolumeProp.health]);
  338. wprintf(L" TransitionState: %s\n", TransitionStateString[VolumeProp.TransitionState]);
  339. wprintf(L" Size: %I64u\n", VolumeProp.ullSize);
  340. wprintf(L" Flags: %lx\n", VolumeProp.ulFlags);
  341. wprintf(L" Recommended file system: %s\n", FileSystemString[VolumeProp.RecommendedFileSystemType]);
  342. wprintf(L" Win32 name: %s\n", VolumeProp.pwszName);
  343. int ret = wcscmp(szVolumeWin32Name,VolumeProp.pwszName);
  344. if (ret != 0)
  345. {
  346. SAFE_RELEASE(pVolume);
  347. continue;
  348. }
  349. wprintf(L"found the volume - name %s\n", VolumeProp.pwszName);
  350. fVolumeFound = TRUE;
  351. CoTaskMemFree(VolumeProp.pwszName);
  352. }
  353. // Get IVdsVolumeMF
  354. IVdsVolumeMF3 *pVolumeMF3;
  355. hr = pVolume->QueryInterface(IID_IVdsVolumeMF3, (void **)&pVolumeMF3);
  356. if (FAILED(hr))
  357. {
  358. printf(" pVolume->QueryInterface(IVdsVolumeMF3) failed: hr=%X\n", hr);
  359. }
  360. else
  361. {
  362. //printf("success IVdsVolumeMF3 ...\n");
  363. USHORT Revision = 1;
  364. ULONG UnitAllocationSize = 0;
  365. wchar_t Label[] = L"VDSTest";
  366. ULONG Options = VDS_FSOF_QUICK;
  367. #if 0
  368. typedef enum {
  369. VDS_FSOF_NONE = 0x00000000,
  370. VDS_FSOF_FORCE = 0x00000001,
  371. VDS_FSOF_QUICK = 0x00000002,
  372. VDS_FSOF_COMPRESSION = 0x00000004,
  373. VDS_FSOF_DUPLICATE_METADATA = 0x00000008
  374. } VDS_FORMAT_OPTION_FLAGS;
  375. #endif
  376. ::memset(&AsyncOut, 0, sizeof(VDS_ASYNC_OUTPUT));
  377. hr = pVolumeMF3->FormatEx2(szFsType,
  378. Revision,
  379. UnitAllocationSize,
  380. Label,
  381. (DWORD) Options,
  382. &pAsync);
  383. hr = pAsync->Wait(&AsyncHr, &AsyncOut);
  384. if (FAILED(hr))
  385. {
  386. printf("pAsync->Wait hr failed: %X\n", hr);
  387. }
  388. else if (FAILED(AsyncHr))
  389. {
  390. switch(AsyncHr)
  391. {
  392. case VDS_E_VOLUME_NOT_ONLINE:
  393. printf("IDS_FORMAT_OFFLINE\n");
  394. break;
  395. default:
  396. printf("pAsync->Wait AsyncHr failed: %X\n", AsyncHr);
  397. break;
  398. }
  399. }
  400. else
  401. {
  402. // The volume is formatted successfully.
  403. printf("format complete.\n");
  404. }
  405. }
  406. SAFE_RELEASE(pVolume);
  407. SAFE_RELEASE(pVolumeMF3);
  408. } while (TRUE);
  409. SAFE_RELEASE(pEnumVolume);
  410. } while (TRUE);
  411. SAFE_RELEASE(pEnumPack);
  412. } while (TRUE);
  413. SAFE_RELEASE(pEnum);
  414. SAFE_RELEASE(pService);
  415. if (!fVolumeFound)
  416. {
  417. printf("cannot find the volume.\n");
  418. }
  419. CoUninitialize();
  420. return 0;
  421. _bailout:
  422. SAFE_RELEASE(pEnum);
  423. SAFE_RELEASE(pEnumPack);
  424. SAFE_RELEASE(pEnumVolume);
  425. SAFE_RELEASE(pService);
  426. CoUninitialize();
  427. return 0;
  428. }