/Visual Studio 2010/CppVDSQueryVolumes/CppVDSQueryVolumes.cpp

# · C++ · 492 lines · 383 code · 69 blank · 40 comment · 45 complexity · c796fa0e12e253ce56ab0384891e9ab3 MD5 · raw file

  1. /****************************** Module Header ******************************\
  2. Module Name: CppVDSQueryVolumes.cpp
  3. Project: CppVDSQueryVolumes (VDS Query Volumes)
  4. Copyright (c) Microsoft Corporation.
  5. Demonstrates volumes enumeration on a system using VDS, also lists volume
  6. properties.
  7. This source is subject to the Microsoft Public License.
  8. See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
  9. All other rights reserved.
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
  11. EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  12. WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
  13. \***************************************************************************/
  14. #include <windows.h>
  15. #include <winioctl.h>
  16. #include <stdio.h>
  17. #define DEFIND_GUID
  18. #include <initguid.h>
  19. #include <vds.h>
  20. // Turn off do..while(TRUE) warnings.
  21. #pragma warning(disable:4127)
  22. #define SAFE_RELEASE(x) if (x) { x->Release(); x = NULL; }
  23. #define SAFE_FREE(x) if (x) { CoTaskMemFree(x); }
  24. #define GUID_LEN 50
  25. wchar_t *HealthString[] =
  26. {
  27. L"UNKNOWN",
  28. L"HEALTHY",
  29. L"REBUILDING",
  30. L"STALE",
  31. L"FAILING",
  32. L"FAILING_REDUNDANCY",
  33. L"FAILED_REDUNDANCY",
  34. L"FAILED_REDUNDANCY_FAILING",
  35. L"FAILED"
  36. };
  37. wchar_t *TypeString[] =
  38. {
  39. L"UNKNOWN",
  40. L"SIMPLE",
  41. L"SPAN",
  42. L"STRIPE",
  43. L"MIRROR",
  44. L"PARITY"
  45. };
  46. wchar_t *StatusString[] =
  47. {
  48. L"UNKNOWN",
  49. L"ONLINE",
  50. L"NOT_READY",
  51. L"NO_MEDIA",
  52. L"FAILED"
  53. };
  54. wchar_t *TransitionStateString[] =
  55. {
  56. L"UNKNOWN",
  57. L"STABLE",
  58. L"EXTENDING",
  59. L"SHRINKING",
  60. L"RECONFIGING"
  61. };
  62. wchar_t *FileSystemString[] =
  63. {
  64. L"UNKNOWN",
  65. L"RAW",
  66. L"FAT",
  67. L"FAT32",
  68. L"NTFS",
  69. L"CDFS",
  70. L"UDF"
  71. };
  72. wchar_t *ExtentTypeString[] =
  73. {
  74. L"UNKNOWN",
  75. L"FREE",
  76. L"DATA",
  77. L"OEM",
  78. L"ESP",
  79. L"MSR",
  80. L"LMD",
  81. L"UNUSABLE"
  82. };
  83. void ListVolumeDisks(IVdsVolume *pVolume)
  84. {
  85. HRESULT hr;
  86. IEnumVdsObject *pEnumPlex = NULL;
  87. wchar_t buffer[500];
  88. printf("\n\t... dumping disk extents ...\n");
  89. hr = pVolume->QueryPlexes(&pEnumPlex);
  90. IUnknown *pPlexUnk;
  91. ULONG ulFetchedPlex;
  92. VDS_VOLUME_PLEX_PROP PlexProp;
  93. do
  94. {
  95. hr = pEnumPlex->Next(1, &pPlexUnk, &ulFetchedPlex);
  96. if (hr == S_FALSE)
  97. {
  98. break; // End of enumeration
  99. }
  100. if (FAILED(hr))
  101. {
  102. goto _bailout;
  103. }
  104. // Get IVdsVolumePlex
  105. IVdsVolumePlex *pPlex;
  106. hr = pPlexUnk->QueryInterface(IID_IVdsVolumePlex, (void **)&pPlex);
  107. if (FAILED(hr))
  108. {
  109. SAFE_RELEASE(pPlex);
  110. goto _bailout;
  111. }
  112. // Get plex properties
  113. hr = pPlex->GetProperties(&PlexProp);
  114. if (FAILED(hr))
  115. {
  116. SAFE_RELEASE(pPlex);
  117. goto _bailout;
  118. }
  119. //
  120. // Get extents on the plex
  121. VDS_DISK_EXTENT *pExtents;
  122. LONG lExtentsCount;
  123. hr = pPlex->QueryExtents(&pExtents, &lExtentsCount);
  124. SAFE_RELEASE(pPlex);
  125. if (FAILED(hr))
  126. {
  127. goto _bailout;
  128. }
  129. printf("\tNumber of extents: %ld\n", lExtentsCount);
  130. for (int i = 0; i < lExtentsCount; i++)
  131. {
  132. printf("\n\t\tExtent #%d:\n", i + 1);
  133. StringFromGUID2( pExtents[i].diskId, buffer, 500);
  134. wprintf(L"\t\tDisk Id: %ws\n", buffer);
  135. printf("\t\ttype: %ws\n",
  136. pExtents[i].type==VDS_DET_UNUSABLE?ExtentTypeString[7] :
  137. ExtentTypeString[pExtents[i].type]
  138. );
  139. printf("\t\tOffset: %I64d\n", pExtents[i].ullOffset);
  140. printf("\t\tSize: %I64d\n", pExtents[i].ullSize);
  141. StringFromGUID2( pExtents[i].volumeId, buffer, 500);
  142. wprintf(L"\t\tVolume Id: %ws\n", buffer);
  143. StringFromGUID2( pExtents[i].plexId, buffer, 500);
  144. wprintf(L"\t\tPlex Id: %ws\n", buffer);
  145. printf("\t\tMember Id: %ld\n", pExtents[i].memberIdx);
  146. }
  147. SAFE_FREE( pExtents );
  148. } while (TRUE);
  149. SAFE_RELEASE( pEnumPlex );
  150. _bailout:
  151. return;
  152. }
  153. int wmain(int argc, wchar_t *argv[])
  154. {
  155. UNREFERENCED_PARAMETER(argc);
  156. UNREFERENCED_PARAMETER(argv);
  157. HRESULT hr;
  158. IEnumVdsObject *pEnum = NULL;
  159. IEnumVdsObject *pEnumPack = NULL;
  160. IEnumVdsObject *pEnumVolume = NULL;
  161. wchar_t buffer[500];
  162. if (FAILED(CoInitialize(NULL)))
  163. {
  164. printf("CoInitialize() failed err=%d.\n", GetLastError());
  165. return 0;
  166. }
  167. // Create a loader instance
  168. IVdsServiceLoader *pLoader;
  169. hr = CoCreateInstance(CLSID_VdsLoader,
  170. NULL,
  171. CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
  172. IID_IVdsServiceLoader,
  173. (void **)&pLoader);
  174. if (FAILED(hr))
  175. {
  176. printf("CoCreateInstance failed: hr=%X\n", hr);
  177. return 0;
  178. }
  179. // Load the service on the machine.
  180. IVdsService *pService;
  181. hr = pLoader->LoadService(NULL, &pService);
  182. pLoader->Release();
  183. pLoader = NULL;
  184. if (FAILED(hr))
  185. {
  186. printf("LoadService failed: hr=%X\n", hr);
  187. return 0;
  188. }
  189. // Call QueryProviders
  190. hr = pService->QueryProviders(VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum);
  191. if (FAILED(hr))
  192. {
  193. printf("QueryProviders(VDS_QUERY_SOFTWARE_PROVIDERS) failed: hr=%X\n", hr);
  194. goto _bailout;
  195. }
  196. IUnknown *pUnk;
  197. IVdsProvider *pProvider;
  198. ULONG ulFetched = 0;
  199. int iProviderNumber = 1;
  200. // Enumerate the VDS software providers
  201. do
  202. {
  203. hr = pEnum->Next(1, &pUnk, &ulFetched);
  204. // S_FALSE indicates there are no more providers in the list
  205. if (hr == S_FALSE)
  206. {
  207. break;
  208. }
  209. if (FAILED(hr))
  210. {
  211. printf("\npEnum->Next() failed: hr=%X\n", hr);
  212. goto _bailout;
  213. }
  214. // Get IVdsProvider
  215. hr = pUnk->QueryInterface(IID_IVdsProvider, (void **)&pProvider);
  216. SAFE_RELEASE(pUnk);
  217. if (FAILED(hr))
  218. {
  219. printf("\tpUnk->QueryInterface(IVdsProvider) failed: hr=%X\n", hr);
  220. goto _bailout;
  221. }
  222. VDS_PROVIDER_PROP provProp;
  223. hr = pProvider->GetProperties(&provProp);
  224. if (SUCCEEDED(hr))
  225. {
  226. printf("Provider #: %ld name: %ws\n", iProviderNumber++, provProp.pwszName);
  227. }
  228. // Get IVdsSwProvider
  229. IVdsSwProvider *pSwProvider;
  230. hr = pProvider->QueryInterface(IID_IVdsSwProvider, (void **)&pSwProvider);
  231. SAFE_RELEASE(pProvider);
  232. if (FAILED(hr))
  233. {
  234. printf("\t\tpProvider->QueryInterface(IVdsSwProvider) failed: hr=%X\n", hr);
  235. goto _bailout;
  236. }
  237. // Enumerate packs associated with the software provider
  238. hr = pSwProvider->QueryPacks(&pEnumPack);
  239. SAFE_RELEASE(pSwProvider);
  240. if (FAILED(hr))
  241. {
  242. printf("\t\tpSwProvider->QueryPacks() failed: hr=%X\n", hr);
  243. goto _bailout;
  244. }
  245. IUnknown *pPackUnk;
  246. ULONG ulFetchedPack;
  247. int iPackNumber = 1;
  248. // Enumerate the packs
  249. do
  250. {
  251. hr = pEnumPack->Next(1, &pPackUnk, &ulFetchedPack);
  252. if (hr == S_FALSE)
  253. {
  254. break;
  255. }
  256. if (FAILED(hr))
  257. {
  258. printf("\t\t\tpEnumPack->Next() failed: hr=%X\n", hr);
  259. goto _bailout;
  260. }
  261. printf("Pack #: %ld\n", iPackNumber++ );
  262. // Get IVdsPack
  263. IVdsPack *pPack;
  264. hr = pPackUnk->QueryInterface(IID_IVdsPack, (void **)&pPack);
  265. SAFE_RELEASE(pPackUnk);
  266. if (FAILED(hr))
  267. {
  268. printf( "\n\n\npPackUnk->QueryInterface() failed: hr=%X\n", hr);
  269. goto _bailout;
  270. }
  271. // Get the volume enumerator to list volumes associated with the pack
  272. hr = pPack->QueryVolumes( &pEnumVolume );
  273. SAFE_RELEASE(pPack);
  274. if (FAILED(hr))
  275. {
  276. printf( "\n\n\npPack->QueryVolumes() failed: hr=%X\n", hr);
  277. goto _bailout;
  278. }
  279. IUnknown *pVolumeUnk;
  280. ULONG ulFetchedVolume;
  281. int iVolumeNumber = 1;
  282. // Enumerate the volumes in the pack
  283. do
  284. {
  285. hr = pEnumVolume->Next(1, &pVolumeUnk, &ulFetchedVolume);
  286. if (hr == S_FALSE)
  287. {
  288. break; // End of enumeration
  289. }
  290. if (FAILED(hr))
  291. {
  292. printf("\t\t\tpEnumVolume->Next() failed: hr=%X\n", hr);
  293. goto _bailout;
  294. }
  295. printf("Volume #: %ld\n", iVolumeNumber++ );
  296. // Get IVdsVolume
  297. IVdsVolume *pVolume;
  298. hr = pVolumeUnk->QueryInterface(IID_IVdsVolume, (void **)&pVolume);
  299. SAFE_RELEASE(pVolumeUnk);
  300. if (FAILED(hr))
  301. {
  302. printf( "\t\t\tpVolumeUnk->QueryInterface() failed: hr=%X\n", hr);
  303. goto _bailout;
  304. }
  305. // Get volume properties
  306. VDS_VOLUME_PROP VolumeProp;
  307. hr = pVolume->GetProperties(&VolumeProp);
  308. if (SUCCEEDED(hr))
  309. {
  310. StringFromGUID2(VolumeProp.id, buffer, GUID_LEN);
  311. wprintf(L"\tVolume Id: %ws\n", buffer);
  312. printf("\tType: %ws\n", TypeString[VolumeProp.type - VDS_VT_SIMPLE + 1]);
  313. printf("\tStatus: %ws\n", StatusString[VolumeProp.status]);
  314. printf("\tHealth: %ws\n", HealthString[VolumeProp.health]);
  315. printf("\tTransitionState: %ws\n", TransitionStateString[VolumeProp.TransitionState]);
  316. printf("\tSize: %I64u\n", VolumeProp.ullSize);
  317. printf("\tFlags: %lx\n", VolumeProp.ulFlags);
  318. printf("\tRecommended file system: %ws\n", FileSystemString[VolumeProp.RecommendedFileSystemType]);
  319. wprintf(L"\tWin32 name: %s\n", VolumeProp.pwszName);
  320. CoTaskMemFree(VolumeProp.pwszName);
  321. }
  322. ListVolumeDisks(pVolume);
  323. // Get IVdsVolumeMF
  324. IVdsVolumeMF *pVolumeMF;
  325. hr = pVolume->QueryInterface(IID_IVdsVolumeMF, (void **)&pVolumeMF);
  326. if (FAILED(hr))
  327. {
  328. printf("\t\tpVolume->QueryInterface(IVdsVolumeMF) failed: hr=%X\n", hr);
  329. }
  330. else
  331. {
  332. // Get file system properties
  333. VDS_FILE_SYSTEM_PROP FileSysProp;
  334. hr = pVolumeMF->GetFileSystemProperties(&FileSysProp);
  335. if (FAILED(hr))
  336. {
  337. printf( " GetFileSystemProperties failed: hr=%X\n", hr);
  338. }
  339. else
  340. if (SUCCEEDED(hr))
  341. {
  342. printf("\tFile System: %ws\n", FileSystemString[FileSysProp.type]);
  343. printf("\tFlags: %X\n", FileSysProp.ulFlags);
  344. printf("\tAllocationUnitSize: %lu\n", FileSysProp.ulAllocationUnitSize);
  345. printf("\tTotalAllocationUnits: %I64u\n", FileSysProp.ullTotalAllocationUnits);
  346. printf("\tAvailableAllocationUnits: %I64u\n", FileSysProp.ullAvailableAllocationUnits);
  347. wprintf(L"\tLabel: %s\n", FileSysProp.pwszLabel);
  348. }
  349. // Get access paths
  350. LPWSTR *pwszPathArray;
  351. LONG lNumberOfAccessPaths;
  352. hr = pVolumeMF->QueryAccessPaths(&pwszPathArray, &lNumberOfAccessPaths);
  353. if (FAILED(hr))
  354. {
  355. printf("\t\tpVolumeMF->QueryAccessPaths failed: hr=%X\n", hr);
  356. SAFE_RELEASE(pVolumeMF);
  357. continue;
  358. }
  359. printf("\tNumber of access paths: %ld\n", lNumberOfAccessPaths);
  360. for (int i=0; i<lNumberOfAccessPaths; i++)
  361. {
  362. wprintf(L"\t %s\n", pwszPathArray[i]);
  363. SAFE_FREE(pwszPathArray[i]);
  364. }
  365. SAFE_FREE(pwszPathArray);
  366. // Get access paths properties
  367. VDS_REPARSE_POINT_PROP *pReparsePointProps = NULL;
  368. LONG lNumberOfReparsePointProps;
  369. hr = pVolumeMF->QueryReparsePoints(&pReparsePointProps, &lNumberOfReparsePointProps);
  370. if (FAILED(hr))
  371. {
  372. printf( "\t\tpVolumeMF->QueryReparsePoints failed: hr=%X\n", hr );
  373. }
  374. else if (SUCCEEDED(hr))
  375. {
  376. printf("\tNumber of reparse points: %d\n", lNumberOfReparsePointProps);
  377. for (LONG j = 0; j < lNumberOfReparsePointProps; j++)
  378. {
  379. StringFromGUID2(pReparsePointProps[j].SourceVolumeId, buffer, 500);
  380. wprintf(L"\t ( %ws, %s )\n", buffer, pReparsePointProps[j].pwszPath);
  381. SAFE_FREE( pReparsePointProps[j].pwszPath);
  382. }
  383. SAFE_FREE(pReparsePointProps);
  384. }
  385. }
  386. // Get IVdsVolumeMF
  387. IVdsVolumeMF2 *pVolumeMF2;
  388. hr = pVolume->QueryInterface(IID_IVdsVolumeMF2, (void **)&pVolumeMF2);
  389. if (FAILED(hr))
  390. {
  391. printf("\t\tpVolume->QueryInterface(IVdsVolumeMF2) failed: hr=%X\n", hr);
  392. goto _bailout;
  393. }
  394. LPWSTR pwszFileSystemTypeName;
  395. hr = pVolumeMF2->GetFileSystemTypeName(&pwszFileSystemTypeName);
  396. if (SUCCEEDED(hr))
  397. {
  398. printf("\tFile system type: %ws\n", pwszFileSystemTypeName);
  399. }
  400. SAFE_FREE(pwszFileSystemTypeName);
  401. SAFE_RELEASE(pVolume);
  402. SAFE_RELEASE(pVolumeMF);
  403. SAFE_RELEASE(pVolumeMF2);
  404. } while (TRUE);
  405. SAFE_RELEASE(pEnumVolume);
  406. } while (TRUE);
  407. SAFE_RELEASE( pEnumPack );
  408. } while (TRUE);
  409. SAFE_RELEASE(pEnum);
  410. SAFE_RELEASE(pService);
  411. CoUninitialize();
  412. return 0;
  413. _bailout:
  414. SAFE_RELEASE(pEnum);
  415. SAFE_RELEASE(pEnumPack);
  416. SAFE_RELEASE(pEnumVolume);
  417. SAFE_RELEASE(pService);
  418. CoUninitialize();
  419. return 0;
  420. }