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.

853 lines
19 KiB

  1. /*
  2. * volumeid.c - Volume ID ADT module.
  3. */
  4. /* Headers
  5. **********/
  6. #include "project.h"
  7. #pragma hdrstop
  8. #include "volumeid.h"
  9. /* Constants
  10. ************/
  11. /* local root path constants */
  12. #define MAX_LOCAL_DRIVES (TEXT('z') - TEXT('a') + 1)
  13. /* Macros
  14. *********/
  15. /* macros for accessing IVOLUMEID data */
  16. #define IVOLID_Volume_Label_PtrA(pivolid) \
  17. ((LPSTR)(((PBYTE)(pivolid)) + (pivolid)->ucbVolumeLabelOffset))
  18. #ifdef UNICODE
  19. #define IVOLID_Volume_Label_PtrW(pivolid) \
  20. ((LPTSTR)(((PBYTE)(pivolid)) + (pivolid)->ucbVolumeLabelOffsetW))
  21. #endif
  22. #ifdef UNICODE
  23. #define IVOLID_Volume_Label_Ptr(pivolid) IVOLID_Volume_Label_PtrW(pivolid)
  24. #else
  25. #define IVOLID_Volume_Label_Ptr(pivolid) IVOLID_Volume_Label_PtrA(pivolid)
  26. #endif
  27. /* Types
  28. ********/
  29. /*
  30. @doc INTERNAL
  31. @struct IVOLUMEID | Internal definition of relocatable volume ID structure.
  32. An <t ILINKINFO> structure may contain an IVOLUMEID structure. An IVOLUMEID
  33. structure consists of a header described as below, followed by
  34. variable-length data.
  35. */
  36. typedef struct _ivolumeidA
  37. {
  38. /*
  39. @field UINT | ucbSize | Length of IVOLUMEID structure in bytes, including
  40. ucbSize field.
  41. */
  42. UINT ucbSize;
  43. /*
  44. @field UINT | uDriveType | The volume's host drive type, as returned by
  45. GetDriveType()
  46. */
  47. UINT uDriveType;
  48. /* @field DWORD | dwSerialNumber | The volume's serial number. */
  49. DWORD dwSerialNumber;
  50. /*
  51. @field UINT | ucbVolumeLabelOffset | Offset in bytes of volume label
  52. string from base of structure.
  53. */
  54. UINT ucbVolumeLabelOffset;
  55. }
  56. IVOLUMEIDA;
  57. DECLARE_STANDARD_TYPES(IVOLUMEIDA);
  58. #ifdef UNICODE
  59. typedef struct _ivolumeidW
  60. {
  61. /*
  62. @field UINT | ucbSize | Length of IVOLUMEID structure in bytes, including
  63. ucbSize field.
  64. */
  65. UINT ucbSize;
  66. /*
  67. @field UINT | uDriveType | The volume's host drive type, as returned by
  68. GetDriveType()
  69. */
  70. UINT uDriveType;
  71. /* @field DWORD | dwSerialNumber | The volume's serial number. */
  72. DWORD dwSerialNumber;
  73. /*
  74. @field UINT | ucbVolumeLabelOffset | Offset in bytes of volume label
  75. string from base of structure.
  76. */
  77. UINT ucbVolumeLabelOffset;
  78. /*
  79. This member is for storing the unicode version of the string
  80. */
  81. UINT ucbVolumeLabelOffsetW;
  82. }
  83. IVOLUMEIDW;
  84. DECLARE_STANDARD_TYPES(IVOLUMEIDW);
  85. #endif
  86. #ifdef UNICODE
  87. #define IVOLUMEID IVOLUMEIDW
  88. #define PIVOLUMEID PIVOLUMEIDW
  89. #define CIVOLUMEID CIVOLUMEIDW
  90. #define PCIVOLUMEID PCIVOLUMEIDW
  91. #else
  92. #define IVOLUMEID IVOLUMEIDA
  93. #define PIVOLUMEID PIVOLUMEIDA
  94. #define CIVOLUMEID CIVOLUMEIDA
  95. #define PCIVOLUMEID PCIVOLUMEIDA
  96. #endif
  97. /***************************** Private Functions *****************************/
  98. /* Module Prototypes
  99. ********************/
  100. PRIVATE_CODE BOOL UnifyIVolumeIDInfo(UINT, DWORD, LPCTSTR, PIVOLUMEID *, PUINT);
  101. PRIVATE_CODE BOOL IsPathOnVolume(LPCTSTR, PCIVOLUMEID, PBOOL);
  102. PRIVATE_CODE COMPARISONRESULT CompareUINTs(UINT, UINT);
  103. #if defined(DEBUG) || defined (VSTF)
  104. PRIVATE_CODE BOOL IsValidPCIVOLUMEID(PCIVOLUMEID);
  105. #endif
  106. /*
  107. ** UnifyIVolumeIDInfo()
  108. **
  109. **
  110. **
  111. ** Arguments:
  112. **
  113. ** Returns:
  114. **
  115. ** Side Effects: none
  116. */
  117. PRIVATE_CODE BOOL UnifyIVolumeIDInfo(UINT uDriveType, DWORD dwSerialNumber,
  118. LPCTSTR pcszVolumeLabel, PIVOLUMEID *ppivolid,
  119. PUINT pucbIVolumeIDLen)
  120. {
  121. BOOL bResult;
  122. #ifdef UNICODE
  123. CHAR szAnsiVolumeLabel[MAX_PATH];
  124. BOOL bUnicode;
  125. UINT cchVolumeLabel;
  126. UINT cchChars;
  127. #endif
  128. /* dwSerialNumber may be any value. */
  129. ASSERT(IsValidDriveType(uDriveType));
  130. ASSERT(IS_VALID_STRING_PTR(pcszVolumeLabel, CSTR));
  131. ASSERT(IS_VALID_WRITE_PTR(ppivolid, PIVOLUMEID));
  132. ASSERT(IS_VALID_WRITE_PTR(pucbIVolumeIDLen, UINT));
  133. /* Assume we won't overflow *pucbIVolumeIDLen here. */
  134. #ifdef UNICODE
  135. /* Determine whether we need a full fledged UNICODE volume ID */
  136. bUnicode = FALSE;
  137. cchVolumeLabel = WideCharToMultiByte(CP_ACP, 0,
  138. pcszVolumeLabel, -1,
  139. szAnsiVolumeLabel, MAX_PATH,
  140. 0, 0);
  141. if ( cchVolumeLabel == 0 )
  142. {
  143. bUnicode = TRUE;
  144. }
  145. else
  146. {
  147. WCHAR szWideVolumeLabel[MAX_PATH];
  148. cchChars = MultiByteToWideChar(CP_ACP, 0,
  149. szAnsiVolumeLabel, -1,
  150. szWideVolumeLabel, MAX_PATH);
  151. if ( cchChars == 0 || lstrcmp(pcszVolumeLabel,szWideVolumeLabel) != 0 )
  152. {
  153. bUnicode = TRUE;
  154. }
  155. }
  156. if ( bUnicode )
  157. {
  158. UINT ucbDataSize;
  159. /* (+ 1) for null terminator. */
  160. ucbDataSize = SIZEOF(IVOLUMEIDW) + cchVolumeLabel;
  161. ucbDataSize = ALIGN_WORD_CNT(ucbDataSize);
  162. ucbDataSize += (lstrlen(pcszVolumeLabel) + 1) * SIZEOF(TCHAR);
  163. *pucbIVolumeIDLen = ucbDataSize;
  164. }
  165. else
  166. {
  167. /* (+ 1) for null terminator. */
  168. *pucbIVolumeIDLen = SIZEOF(IVOLUMEIDA) +
  169. cchVolumeLabel;
  170. }
  171. #else
  172. /* (+ 1) for null terminator. */
  173. *pucbIVolumeIDLen = SIZEOF(**ppivolid) +
  174. (lstrlen(pcszVolumeLabel) + 1) * SIZEOF(TCHAR);
  175. #endif
  176. bResult = AllocateMemory(*pucbIVolumeIDLen, ppivolid);
  177. if (bResult)
  178. {
  179. (*ppivolid)->ucbSize = *pucbIVolumeIDLen;
  180. (*ppivolid)->uDriveType = uDriveType;
  181. (*ppivolid)->dwSerialNumber = dwSerialNumber;
  182. /* Append volume label. */
  183. #ifdef UNICODE
  184. if ( bUnicode )
  185. {
  186. (*ppivolid)->ucbVolumeLabelOffset = SIZEOF(IVOLUMEIDW);
  187. (*ppivolid)->ucbVolumeLabelOffsetW = ALIGN_WORD_CNT(
  188. SIZEOF(IVOLUMEIDW)+cchVolumeLabel);
  189. lstrcpy(IVOLID_Volume_Label_PtrW(*ppivolid), pcszVolumeLabel);
  190. }
  191. else
  192. {
  193. (*ppivolid)->ucbVolumeLabelOffset = SIZEOF(IVOLUMEIDA);
  194. }
  195. lstrcpyA(IVOLID_Volume_Label_PtrA(*ppivolid), szAnsiVolumeLabel);
  196. #else
  197. lstrcpy(IVOLID_Volume_Label_Ptr(*ppivolid), pcszVolumeLabel);
  198. #endif
  199. }
  200. ASSERT(! bResult ||
  201. (IS_VALID_STRUCT_PTR(*ppivolid, CIVOLUMEID) &&
  202. EVAL(*pucbIVolumeIDLen == GetVolumeIDLen((PCVOLUMEID)*ppivolid))));
  203. return(bResult);
  204. }
  205. /*
  206. ** IsPathOnVolume()
  207. **
  208. **
  209. **
  210. ** Arguments:
  211. **
  212. ** Returns:
  213. **
  214. ** Side Effects: none
  215. */
  216. PRIVATE_CODE BOOL IsPathOnVolume(LPCTSTR pcszDrivePath, PCIVOLUMEID pcivolid,
  217. PBOOL pbOnVolume)
  218. {
  219. BOOL bResult;
  220. PVOLUMEID pvolid;
  221. UINT ucbVolumeIDLen;
  222. ASSERT(IsDrivePath(pcszDrivePath));
  223. ASSERT(IS_VALID_STRUCT_PTR(pcivolid, CIVOLUMEID));
  224. ASSERT(IS_VALID_WRITE_PTR(pcivolid, CIVOLUMEID));
  225. bResult = CreateVolumeID(pcszDrivePath, &pvolid, &ucbVolumeIDLen);
  226. if (bResult)
  227. {
  228. *pbOnVolume = (CompareVolumeIDs(pvolid, (PCVOLUMEID)pcivolid)
  229. == CR_EQUAL);
  230. DestroyVolumeID(pvolid);
  231. }
  232. return(bResult);
  233. }
  234. /*
  235. ** CompareUINTs()
  236. **
  237. **
  238. **
  239. ** Arguments:
  240. **
  241. ** Returns:
  242. **
  243. ** Side Effects: none
  244. */
  245. PRIVATE_CODE COMPARISONRESULT CompareUINTs(UINT uFirst, UINT uSecond)
  246. {
  247. COMPARISONRESULT cr;
  248. /* Any UINTs are valid input. */
  249. if (uFirst < uSecond)
  250. cr = CR_FIRST_SMALLER;
  251. else if (uFirst > uSecond)
  252. cr = CR_FIRST_LARGER;
  253. else
  254. cr = CR_EQUAL;
  255. ASSERT(IsValidCOMPARISONRESULT(cr));
  256. return(cr);
  257. }
  258. #if defined(DEBUG) || defined (VSTF)
  259. /*
  260. ** IsValidPCIVOLUMEID()
  261. **
  262. **
  263. **
  264. ** Arguments:
  265. **
  266. ** Returns:
  267. **
  268. ** Side Effects: none
  269. */
  270. PRIVATE_CODE BOOL IsValidPCIVOLUMEID(PCIVOLUMEID pcivolid)
  271. {
  272. /* dwSerialNumber may be any value. */
  273. return(IS_VALID_READ_PTR(pcivolid, CIVOLUMEID) &&
  274. IS_VALID_READ_BUFFER_PTR(pcivolid, CIVOLUMEID, pcivolid->ucbSize) &&
  275. EVAL(IsValidDriveType(pcivolid->uDriveType)) &&
  276. EVAL(IsContained(pcivolid, pcivolid->ucbSize,
  277. IVOLID_Volume_Label_Ptr(pcivolid),
  278. lstrlen(IVOLID_Volume_Label_Ptr(pcivolid))*SIZEOF(TCHAR))));
  279. }
  280. #endif
  281. /****************************** Public Functions *****************************/
  282. /*
  283. ** CreateVolumeID()
  284. **
  285. **
  286. **
  287. ** Arguments:
  288. **
  289. ** Returns:
  290. **
  291. ** Side Effects: none
  292. */
  293. PUBLIC_CODE BOOL CreateVolumeID(LPCTSTR pcszDrivePath, PVOLUMEID *ppvolid,
  294. PUINT pucbVolumeIDLen)
  295. {
  296. BOOL bResult;
  297. /* "C:\" + null terminator. */
  298. TCHAR rgchRootPath[3 + 1];
  299. TCHAR rgchVolumeLabel[MAX_PATH_LEN];
  300. DWORD dwSerialNumber;
  301. ASSERT(IsDrivePath(pcszDrivePath));
  302. ASSERT(IS_VALID_WRITE_PTR(ppvolid, PVOLUMEID));
  303. ASSERT(IS_VALID_WRITE_PTR(pucbVolumeIDLen, UINT));
  304. /* Get volume's label and serial number. */
  305. MyLStrCpyN(rgchRootPath, pcszDrivePath, ARRAYSIZE(rgchRootPath));
  306. bResult = GetVolumeInformation(rgchRootPath, rgchVolumeLabel,
  307. ARRAYSIZE(rgchVolumeLabel), &dwSerialNumber,
  308. NULL, NULL, NULL, 0);
  309. if (bResult)
  310. /* Wrap them up. */
  311. bResult = UnifyIVolumeIDInfo(GetDriveType(rgchRootPath), dwSerialNumber,
  312. rgchVolumeLabel, (PIVOLUMEID *)ppvolid,
  313. pucbVolumeIDLen);
  314. ASSERT(! bResult ||
  315. IS_VALID_STRUCT_PTR((PCIVOLUMEID)*ppvolid, CIVOLUMEID));
  316. return(bResult);
  317. }
  318. /*
  319. ** DestroyVolumeID()
  320. **
  321. **
  322. **
  323. ** Arguments:
  324. **
  325. ** Returns:
  326. **
  327. ** Side Effects: none
  328. */
  329. PUBLIC_CODE void DestroyVolumeID(PVOLUMEID pvolid)
  330. {
  331. ASSERT(IS_VALID_STRUCT_PTR(pvolid, CVOLUMEID));
  332. FreeMemory(pvolid);
  333. return;
  334. }
  335. /*
  336. ** CompareVolumeIDs()
  337. **
  338. **
  339. **
  340. ** Arguments:
  341. **
  342. ** Returns:
  343. **
  344. ** Side Effects: none
  345. **
  346. ** Volume ID data is compared in the following order:
  347. ** 1) drive type
  348. ** 2) volume serial number
  349. **
  350. ** N.b., volume labels are ignored.
  351. */
  352. PUBLIC_CODE COMPARISONRESULT CompareVolumeIDs(PCVOLUMEID pcvolidFirst,
  353. PCVOLUMEID pcvolidSecond)
  354. {
  355. COMPARISONRESULT cr;
  356. ASSERT(IS_VALID_STRUCT_PTR(pcvolidFirst, CVOLUMEID));
  357. ASSERT(IS_VALID_STRUCT_PTR(pcvolidSecond, CVOLUMEID));
  358. /* Compare VOLUMEIDs piece by piece. */
  359. cr = CompareUINTs(((PCIVOLUMEID)pcvolidFirst)->uDriveType,
  360. ((PCIVOLUMEID)pcvolidSecond)->uDriveType);
  361. if (cr == CR_EQUAL)
  362. cr = CompareDWORDs(((PCIVOLUMEID)pcvolidFirst)->dwSerialNumber,
  363. ((PCIVOLUMEID)pcvolidSecond)->dwSerialNumber);
  364. return(cr);
  365. }
  366. /*
  367. ** SearchForLocalPath()
  368. **
  369. **
  370. **
  371. ** Arguments:
  372. **
  373. ** Returns:
  374. **
  375. ** Side Effects: none
  376. */
  377. PUBLIC_CODE BOOL SearchForLocalPath(PCVOLUMEID pcvolid, LPCTSTR pcszFullPath,
  378. DWORD dwInFlags, LPTSTR pszFoundPathBuf)
  379. {
  380. BOOL bResult;
  381. BOOL bAvailable;
  382. #if defined(DEBUG) && defined(UNICODE)
  383. WCHAR szWideVolumeLabel[MAX_PATH];
  384. LPWSTR pszWideVolumeLabel;
  385. #endif
  386. ASSERT(IS_VALID_STRUCT_PTR(pcvolid, CVOLUMEID));
  387. ASSERT(IsFullPath(pcszFullPath));
  388. ASSERT(FLAGS_ARE_VALID(dwInFlags, ALL_SFLP_IFLAGS));
  389. ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszFoundPathBuf, STR, MAX_PATH_LEN));
  390. #if defined(DEBUG) && defined(UNICODE)
  391. if (((PCIVOLUMEID)pcvolid)->ucbVolumeLabelOffset == SIZEOF(IVOLUMEIDA))
  392. {
  393. pszWideVolumeLabel = szWideVolumeLabel;
  394. MultiByteToWideChar(CP_ACP, 0,
  395. IVOLID_Volume_Label_PtrA((PCIVOLUMEID)pcvolid), -1,
  396. szWideVolumeLabel, MAX_PATH);
  397. }
  398. else
  399. {
  400. pszWideVolumeLabel = IVOLID_Volume_Label_Ptr((PCIVOLUMEID)pcvolid);
  401. }
  402. #endif
  403. /* Were we given a local path to check first? */
  404. if (IsLocalDrivePath(pcszFullPath))
  405. /* Yes. Check it. */
  406. bResult = IsPathOnVolume(pcszFullPath, (PCIVOLUMEID)pcvolid,
  407. &bAvailable);
  408. else
  409. {
  410. /* No. */
  411. bAvailable = FALSE;
  412. bResult = TRUE;
  413. }
  414. if (bResult)
  415. {
  416. /* Did we find the volume? */
  417. if (bAvailable)
  418. {
  419. /* Yes. */
  420. ASSERT(lstrlen(pcszFullPath) < MAX_PATH_LEN);
  421. lstrcpy(pszFoundPathBuf, pcszFullPath);
  422. }
  423. else
  424. {
  425. /*
  426. * No. Should we search other matching local devices for the volume?
  427. */
  428. if (IS_FLAG_SET(dwInFlags, SFLP_IFL_LOCAL_SEARCH))
  429. {
  430. TCHAR chOriginalDrive;
  431. UINT uDrive;
  432. DWORD dwLogicalDrives;
  433. /* Yes. */
  434. #ifdef UNICODE
  435. WARNING_OUT((TEXT("SearchForLocalPath(): Searching for local volume \"%s\", as requested."),
  436. pszWideVolumeLabel));
  437. #else
  438. WARNING_OUT((TEXT("SearchForLocalPath(): Searching for local volume \"%s\", as requested."),
  439. IVOLID_Volume_Label_Ptr((PCIVOLUMEID)pcvolid)));
  440. #endif
  441. ASSERT(IsCharAlpha(*pcszFullPath));
  442. chOriginalDrive = *pcszFullPath;
  443. ASSERT(lstrlen(pcszFullPath) < MAX_PATH_LEN);
  444. lstrcpy(pszFoundPathBuf, pcszFullPath);
  445. /* Get bit mask of local logical drives. */
  446. dwLogicalDrives = GetLogicalDrives();
  447. for (uDrive = 0; uDrive < MAX_LOCAL_DRIVES; uDrive++)
  448. {
  449. if (IS_FLAG_SET(dwLogicalDrives, (1 << uDrive)))
  450. {
  451. TCHAR chDrive;
  452. chDrive = (TCHAR)(TEXT('A') + uDrive);
  453. ASSERT(IsCharAlpha(chDrive));
  454. if (chDrive != chOriginalDrive)
  455. {
  456. TCHAR rgchLocalRootPath[DRIVE_ROOT_PATH_LEN];
  457. lstrcpy(rgchLocalRootPath, TEXT("A:\\"));
  458. rgchLocalRootPath[0] = chDrive;
  459. /*
  460. * Does this drive's type match the target volume's drive
  461. * type?
  462. */
  463. if (GetDriveType(rgchLocalRootPath) == ((PCIVOLUMEID)pcvolid)->uDriveType)
  464. {
  465. /* Yes. Check the volume. */
  466. TRACE_OUT((TEXT("SearchForLocalPath(): Checking local root path %s."),
  467. rgchLocalRootPath));
  468. bResult = IsPathOnVolume(rgchLocalRootPath,
  469. (PCIVOLUMEID)pcvolid,
  470. &bAvailable);
  471. if (bResult)
  472. {
  473. if (bAvailable)
  474. {
  475. ASSERT(lstrlen(pcszFullPath) < MAX_PATH_LEN);
  476. lstrcpy(pszFoundPathBuf, pcszFullPath);
  477. ASSERT(IsCharAlpha(*pszFoundPathBuf));
  478. *pszFoundPathBuf = chDrive;
  479. TRACE_OUT((TEXT("SearchForLocalPath(): Found matching volume on local path %s."),
  480. pszFoundPathBuf));
  481. break;
  482. }
  483. }
  484. else
  485. break;
  486. }
  487. }
  488. }
  489. }
  490. }
  491. else
  492. /* No. */
  493. #ifdef UNICODE
  494. WARNING_OUT((TEXT("SearchForLocalPath(): Not searching for local volume \"%s\", as requested."),
  495. pszWideVolumeLabel));
  496. #else
  497. WARNING_OUT((TEXT("SearchForLocalPath(): Not searching for local volume \"%s\", as requested."),
  498. IVOLID_Volume_Label_Ptr((PCIVOLUMEID)pcvolid)));
  499. #endif
  500. }
  501. }
  502. ASSERT(! bResult ||
  503. ! bAvailable ||
  504. IsLocalDrivePath(pszFoundPathBuf));
  505. return(bResult && bAvailable);
  506. }
  507. /*
  508. ** GetVolumeIDLen()
  509. **
  510. **
  511. **
  512. ** Arguments:
  513. **
  514. ** Returns:
  515. **
  516. ** Side Effects: none
  517. */
  518. PUBLIC_CODE UINT GetVolumeIDLen(PCVOLUMEID pcvolid)
  519. {
  520. ASSERT(IS_VALID_STRUCT_PTR(pcvolid, CVOLUMEID));
  521. return(((PCIVOLUMEID)pcvolid)->ucbSize);
  522. }
  523. /*
  524. ** GetVolumeSerialNumber()
  525. **
  526. **
  527. **
  528. ** Arguments:
  529. **
  530. ** Returns:
  531. **
  532. ** Side Effects: none
  533. */
  534. PUBLIC_CODE BOOL GetVolumeSerialNumber(PCVOLUMEID pcvolid,
  535. PCDWORD *ppcdwSerialNumber)
  536. {
  537. ASSERT(IS_VALID_STRUCT_PTR(pcvolid, CVOLUMEID));
  538. ASSERT(IS_VALID_WRITE_PTR(ppcdwSerialNumber, PCDWORD));
  539. *ppcdwSerialNumber = &(((PCIVOLUMEID)pcvolid)->dwSerialNumber);
  540. ASSERT(IS_VALID_READ_PTR(*ppcdwSerialNumber, CDWORD));
  541. return(TRUE);
  542. }
  543. /*
  544. ** GetVolumeDriveType()
  545. **
  546. **
  547. **
  548. ** Arguments:
  549. **
  550. ** Returns:
  551. **
  552. ** Side Effects: none
  553. */
  554. PUBLIC_CODE BOOL GetVolumeDriveType(PCVOLUMEID pcvolid, PCUINT *ppcuDriveType)
  555. {
  556. ASSERT(IS_VALID_STRUCT_PTR(pcvolid, CVOLUMEID));
  557. ASSERT(IS_VALID_WRITE_PTR(ppcuDriveType, PCUINT));
  558. *ppcuDriveType = &(((PCIVOLUMEID)pcvolid)->uDriveType);
  559. ASSERT(IS_VALID_READ_PTR(*ppcuDriveType, CUINT));
  560. return(TRUE);
  561. }
  562. /*
  563. ** GetVolumeLabel()
  564. **
  565. **
  566. **
  567. ** Arguments:
  568. **
  569. ** Returns:
  570. **
  571. ** Side Effects: none
  572. */
  573. PUBLIC_CODE BOOL GetVolumeLabel(PCVOLUMEID pcvolid, LPCSTR *ppcszVolumeLabel)
  574. {
  575. ASSERT(IS_VALID_STRUCT_PTR(pcvolid, CVOLUMEID));
  576. ASSERT(IS_VALID_WRITE_PTR(ppcszVolumeLabel, LPCTSTR));
  577. *ppcszVolumeLabel = IVOLID_Volume_Label_PtrA((PCIVOLUMEID)pcvolid);
  578. ASSERT(IS_VALID_STRING_PTRA(*ppcszVolumeLabel, CSTR));
  579. return(TRUE);
  580. }
  581. #ifdef UNICODE
  582. /*
  583. ** GetVolumeLabelW()
  584. **
  585. **
  586. **
  587. ** Arguments:
  588. **
  589. ** Returns:
  590. **
  591. ** Side Effects: none
  592. */
  593. PUBLIC_CODE BOOL GetVolumeLabelW(PCVOLUMEID pcvolid, LPCWSTR *ppcszVolumeLabel)
  594. {
  595. ASSERT(IS_VALID_STRUCT_PTR(pcvolid, CVOLUMEID));
  596. ASSERT(IS_VALID_WRITE_PTR(ppcszVolumeLabel, LPCTSTR));
  597. if (((PCIVOLUMEID)pcvolid)->ucbVolumeLabelOffset == SIZEOF(IVOLUMEIDW))
  598. {
  599. *ppcszVolumeLabel = IVOLID_Volume_Label_PtrW((PCIVOLUMEID)pcvolid);
  600. ASSERT(IS_VALID_STRING_PTR(*ppcszVolumeLabel, CSTR));
  601. }
  602. else
  603. {
  604. *ppcszVolumeLabel = NULL;
  605. }
  606. return(TRUE);
  607. }
  608. #endif
  609. /*
  610. ** CompareDWORDs()
  611. **
  612. **
  613. **
  614. ** Arguments:
  615. **
  616. ** Returns:
  617. **
  618. ** Side Effects: none
  619. */
  620. PUBLIC_CODE COMPARISONRESULT CompareDWORDs(DWORD dwFirst, DWORD dwSecond)
  621. {
  622. COMPARISONRESULT cr;
  623. /* Any DWORDs are valid input. */
  624. if (dwFirst < dwSecond)
  625. cr = CR_FIRST_SMALLER;
  626. else if (dwFirst > dwSecond)
  627. cr = CR_FIRST_LARGER;
  628. else
  629. cr = CR_EQUAL;
  630. ASSERT(IsValidCOMPARISONRESULT(cr));
  631. return(cr);
  632. }
  633. #if defined(DEBUG) || defined (VSTF)
  634. /*
  635. ** IsValidPCVOLUMEID()
  636. **
  637. **
  638. **
  639. ** Arguments:
  640. **
  641. ** Returns:
  642. **
  643. ** Side Effects: none
  644. */
  645. PUBLIC_CODE BOOL IsValidPCVOLUMEID(PCVOLUMEID pcvolid)
  646. {
  647. return(IS_VALID_STRUCT_PTR((PCIVOLUMEID)pcvolid, CIVOLUMEID));
  648. }
  649. #endif
  650. #ifdef DEBUG
  651. /*
  652. ** DumpVolumeID()
  653. **
  654. **
  655. **
  656. ** Arguments:
  657. **
  658. ** Returns:
  659. **
  660. ** Side Effects: none
  661. */
  662. PUBLIC_CODE void DumpVolumeID(PCVOLUMEID pcvolid)
  663. {
  664. ASSERT(IS_VALID_STRUCT_PTR(pcvolid, CVOLUMEID));
  665. PLAIN_TRACE_OUT((TEXT("%s%s[local volume ID] ucbSize = %#x"),
  666. INDENT_STRING,
  667. INDENT_STRING,
  668. ((PCIVOLUMEID)pcvolid)->ucbSize));
  669. PLAIN_TRACE_OUT((TEXT("%s%s[local volume ID] drive type %u"),
  670. INDENT_STRING,
  671. INDENT_STRING,
  672. ((PCIVOLUMEID)pcvolid)->uDriveType));
  673. PLAIN_TRACE_OUT((TEXT("%s%s[local volume ID] serial number %#08lx"),
  674. INDENT_STRING,
  675. INDENT_STRING,
  676. ((PCIVOLUMEID)pcvolid)->dwSerialNumber));
  677. PLAIN_TRACE_OUT((TEXT("%s%s[local volume ID] label \"%s\""),
  678. INDENT_STRING,
  679. INDENT_STRING,
  680. IVOLID_Volume_Label_Ptr((PCIVOLUMEID)pcvolid)));
  681. return;
  682. }
  683. #endif