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.

849 lines
20 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, pcszVolumeLabel, -1,
  138. szAnsiVolumeLabel, ARRAYSIZE(szAnsiVolumeLabel), 0, 0);
  139. if ( cchVolumeLabel == 0 )
  140. {
  141. bUnicode = TRUE;
  142. }
  143. else
  144. {
  145. WCHAR szWideVolumeLabel[MAX_PATH];
  146. cchChars = MultiByteToWideChar(CP_ACP, 0, szAnsiVolumeLabel, -1,
  147. szWideVolumeLabel, ARRAYSIZE(szWideVolumeLabel));
  148. if ( cchChars == 0 || lstrcmp(pcszVolumeLabel,szWideVolumeLabel) != 0 )
  149. {
  150. bUnicode = TRUE;
  151. }
  152. }
  153. if ( bUnicode )
  154. {
  155. UINT ucbDataSize;
  156. /* (+ 1) for null terminator. */
  157. ucbDataSize = SIZEOF(IVOLUMEIDW) + cchVolumeLabel;
  158. ucbDataSize = ALIGN_WORD_CNT(ucbDataSize);
  159. ucbDataSize += (lstrlen(pcszVolumeLabel) + 1) * SIZEOF(TCHAR);
  160. *pucbIVolumeIDLen = ucbDataSize;
  161. }
  162. else
  163. {
  164. /* (+ 1) for null terminator. */
  165. *pucbIVolumeIDLen = SIZEOF(IVOLUMEIDA) +
  166. cchVolumeLabel;
  167. }
  168. #else
  169. /* (+ 1) for null terminator. */
  170. *pucbIVolumeIDLen = SIZEOF(**ppivolid) +
  171. (lstrlen(pcszVolumeLabel) + 1) * SIZEOF(TCHAR);
  172. #endif
  173. bResult = AllocateMemory(*pucbIVolumeIDLen, ppivolid);
  174. if (bResult)
  175. {
  176. (*ppivolid)->ucbSize = *pucbIVolumeIDLen;
  177. (*ppivolid)->uDriveType = uDriveType;
  178. (*ppivolid)->dwSerialNumber = dwSerialNumber;
  179. /* Append volume label. */
  180. #ifdef UNICODE
  181. if ( bUnicode )
  182. {
  183. (*ppivolid)->ucbVolumeLabelOffset = SIZEOF(IVOLUMEIDW);
  184. (*ppivolid)->ucbVolumeLabelOffsetW = ALIGN_WORD_CNT(
  185. SIZEOF(IVOLUMEIDW)+cchVolumeLabel);
  186. lstrcpy(IVOLID_Volume_Label_PtrW(*ppivolid), pcszVolumeLabel);
  187. }
  188. else
  189. {
  190. (*ppivolid)->ucbVolumeLabelOffset = SIZEOF(IVOLUMEIDA);
  191. }
  192. lstrcpyA(IVOLID_Volume_Label_PtrA(*ppivolid), szAnsiVolumeLabel);
  193. #else
  194. lstrcpy(IVOLID_Volume_Label_Ptr(*ppivolid), pcszVolumeLabel);
  195. #endif
  196. }
  197. ASSERT(! bResult ||
  198. (IS_VALID_STRUCT_PTR(*ppivolid, CIVOLUMEID) &&
  199. EVAL(*pucbIVolumeIDLen == GetVolumeIDLen((PCVOLUMEID)*ppivolid))));
  200. return(bResult);
  201. }
  202. /*
  203. ** IsPathOnVolume()
  204. **
  205. **
  206. **
  207. ** Arguments:
  208. **
  209. ** Returns:
  210. **
  211. ** Side Effects: none
  212. */
  213. PRIVATE_CODE BOOL IsPathOnVolume(LPCTSTR pcszDrivePath, PCIVOLUMEID pcivolid,
  214. PBOOL pbOnVolume)
  215. {
  216. BOOL bResult;
  217. PVOLUMEID pvolid;
  218. UINT ucbVolumeIDLen;
  219. ASSERT(IsDrivePath(pcszDrivePath));
  220. ASSERT(IS_VALID_STRUCT_PTR(pcivolid, CIVOLUMEID));
  221. ASSERT(IS_VALID_WRITE_PTR(pcivolid, CIVOLUMEID));
  222. bResult = CreateVolumeID(pcszDrivePath, &pvolid, &ucbVolumeIDLen);
  223. if (bResult)
  224. {
  225. *pbOnVolume = (CompareVolumeIDs(pvolid, (PCVOLUMEID)pcivolid)
  226. == CR_EQUAL);
  227. DestroyVolumeID(pvolid);
  228. }
  229. return(bResult);
  230. }
  231. /*
  232. ** CompareUINTs()
  233. **
  234. **
  235. **
  236. ** Arguments:
  237. **
  238. ** Returns:
  239. **
  240. ** Side Effects: none
  241. */
  242. PRIVATE_CODE COMPARISONRESULT CompareUINTs(UINT uFirst, UINT uSecond)
  243. {
  244. COMPARISONRESULT cr;
  245. /* Any UINTs are valid input. */
  246. if (uFirst < uSecond)
  247. cr = CR_FIRST_SMALLER;
  248. else if (uFirst > uSecond)
  249. cr = CR_FIRST_LARGER;
  250. else
  251. cr = CR_EQUAL;
  252. ASSERT(IsValidCOMPARISONRESULT(cr));
  253. return(cr);
  254. }
  255. #if defined(DEBUG) || defined (VSTF)
  256. /*
  257. ** IsValidPCIVOLUMEID()
  258. **
  259. **
  260. **
  261. ** Arguments:
  262. **
  263. ** Returns:
  264. **
  265. ** Side Effects: none
  266. */
  267. PRIVATE_CODE BOOL IsValidPCIVOLUMEID(PCIVOLUMEID pcivolid)
  268. {
  269. /* dwSerialNumber may be any value. */
  270. return(IS_VALID_READ_PTR(pcivolid, CIVOLUMEID) &&
  271. IS_VALID_READ_BUFFER_PTR(pcivolid, CIVOLUMEID, pcivolid->ucbSize) &&
  272. EVAL(IsValidDriveType(pcivolid->uDriveType)) &&
  273. EVAL(IsContained(pcivolid, pcivolid->ucbSize,
  274. IVOLID_Volume_Label_Ptr(pcivolid),
  275. lstrlen(IVOLID_Volume_Label_Ptr(pcivolid))*SIZEOF(TCHAR))));
  276. }
  277. #endif
  278. /****************************** Public Functions *****************************/
  279. /*
  280. ** CreateVolumeID()
  281. **
  282. **
  283. **
  284. ** Arguments:
  285. **
  286. ** Returns:
  287. **
  288. ** Side Effects: none
  289. */
  290. PUBLIC_CODE BOOL CreateVolumeID(LPCTSTR pcszDrivePath, PVOLUMEID *ppvolid,
  291. PUINT pucbVolumeIDLen)
  292. {
  293. BOOL bResult;
  294. /* "C:\" + null terminator. */
  295. TCHAR rgchRootPath[3 + 1];
  296. TCHAR rgchVolumeLabel[MAX_PATH_LEN];
  297. DWORD dwSerialNumber;
  298. ASSERT(IsDrivePath(pcszDrivePath));
  299. ASSERT(IS_VALID_WRITE_PTR(ppvolid, PVOLUMEID));
  300. ASSERT(IS_VALID_WRITE_PTR(pucbVolumeIDLen, UINT));
  301. /* Get volume's label and serial number. */
  302. MyLStrCpyN(rgchRootPath, pcszDrivePath, ARRAYSIZE(rgchRootPath));
  303. bResult = GetVolumeInformation(rgchRootPath, rgchVolumeLabel,
  304. ARRAYSIZE(rgchVolumeLabel), &dwSerialNumber,
  305. NULL, NULL, NULL, 0);
  306. if (bResult)
  307. /* Wrap them up. */
  308. bResult = UnifyIVolumeIDInfo(GetDriveType(rgchRootPath), dwSerialNumber,
  309. rgchVolumeLabel, (PIVOLUMEID *)ppvolid,
  310. pucbVolumeIDLen);
  311. ASSERT(! bResult ||
  312. IS_VALID_STRUCT_PTR((PCIVOLUMEID)*ppvolid, CIVOLUMEID));
  313. return(bResult);
  314. }
  315. /*
  316. ** DestroyVolumeID()
  317. **
  318. **
  319. **
  320. ** Arguments:
  321. **
  322. ** Returns:
  323. **
  324. ** Side Effects: none
  325. */
  326. PUBLIC_CODE void DestroyVolumeID(PVOLUMEID pvolid)
  327. {
  328. ASSERT(IS_VALID_STRUCT_PTR(pvolid, CVOLUMEID));
  329. FreeMemory(pvolid);
  330. return;
  331. }
  332. /*
  333. ** CompareVolumeIDs()
  334. **
  335. **
  336. **
  337. ** Arguments:
  338. **
  339. ** Returns:
  340. **
  341. ** Side Effects: none
  342. **
  343. ** Volume ID data is compared in the following order:
  344. ** 1) drive type
  345. ** 2) volume serial number
  346. **
  347. ** N.b., volume labels are ignored.
  348. */
  349. PUBLIC_CODE COMPARISONRESULT CompareVolumeIDs(PCVOLUMEID pcvolidFirst,
  350. PCVOLUMEID pcvolidSecond)
  351. {
  352. COMPARISONRESULT cr;
  353. ASSERT(IS_VALID_STRUCT_PTR(pcvolidFirst, CVOLUMEID));
  354. ASSERT(IS_VALID_STRUCT_PTR(pcvolidSecond, CVOLUMEID));
  355. /* Compare VOLUMEIDs piece by piece. */
  356. cr = CompareUINTs(((PCIVOLUMEID)pcvolidFirst)->uDriveType,
  357. ((PCIVOLUMEID)pcvolidSecond)->uDriveType);
  358. if (cr == CR_EQUAL)
  359. cr = CompareDWORDs(((PCIVOLUMEID)pcvolidFirst)->dwSerialNumber,
  360. ((PCIVOLUMEID)pcvolidSecond)->dwSerialNumber);
  361. return(cr);
  362. }
  363. /*
  364. ** SearchForLocalPath()
  365. **
  366. **
  367. **
  368. ** Arguments:
  369. **
  370. ** Returns:
  371. **
  372. ** Side Effects: none
  373. */
  374. PUBLIC_CODE BOOL SearchForLocalPath(PCVOLUMEID pcvolid, LPCTSTR pcszFullPath,
  375. DWORD dwInFlags, LPTSTR pszFoundPathBuf, int cchMax)
  376. {
  377. BOOL bResult;
  378. BOOL bAvailable;
  379. #if defined(DEBUG) && defined(UNICODE)
  380. WCHAR szWideVolumeLabel[MAX_PATH];
  381. LPWSTR pszWideVolumeLabel;
  382. #endif
  383. ASSERT(IS_VALID_STRUCT_PTR(pcvolid, CVOLUMEID));
  384. ASSERT(IsFullPath(pcszFullPath));
  385. ASSERT(FLAGS_ARE_VALID(dwInFlags, ALL_SFLP_IFLAGS));
  386. ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszFoundPathBuf, STR, cchMax));
  387. #if defined(DEBUG) && defined(UNICODE)
  388. if (((PCIVOLUMEID)pcvolid)->ucbVolumeLabelOffset == SIZEOF(IVOLUMEIDA))
  389. {
  390. pszWideVolumeLabel = szWideVolumeLabel;
  391. MultiByteToWideChar(CP_ACP, 0, IVOLID_Volume_Label_PtrA((PCIVOLUMEID)pcvolid), -1,
  392. szWideVolumeLabel, ARRAYSIZE(szWideVolumeLabel));
  393. }
  394. else
  395. {
  396. pszWideVolumeLabel = IVOLID_Volume_Label_Ptr((PCIVOLUMEID)pcvolid);
  397. }
  398. #endif
  399. /* Were we given a local path to check first? */
  400. if (IsLocalDrivePath(pcszFullPath))
  401. /* Yes. Check it. */
  402. bResult = IsPathOnVolume(pcszFullPath, (PCIVOLUMEID)pcvolid,
  403. &bAvailable);
  404. else
  405. {
  406. /* No. */
  407. bAvailable = FALSE;
  408. bResult = TRUE;
  409. }
  410. if (bResult)
  411. {
  412. /* Did we find the volume? */
  413. if (bAvailable)
  414. {
  415. /* Yes. */
  416. ASSERT(lstrlen(pcszFullPath) < MAX_PATH_LEN);
  417. lstrcpyn(pszFoundPathBuf, pcszFullPath, cchMax);
  418. }
  419. else
  420. {
  421. /*
  422. * No. Should we search other matching local devices for the volume?
  423. */
  424. if (IS_FLAG_SET(dwInFlags, SFLP_IFL_LOCAL_SEARCH))
  425. {
  426. TCHAR chOriginalDrive;
  427. UINT uDrive;
  428. DWORD dwLogicalDrives;
  429. /* Yes. */
  430. #ifdef UNICODE
  431. WARNING_OUT((TEXT("SearchForLocalPath(): Searching for local volume \"%s\", as requested."),
  432. pszWideVolumeLabel));
  433. #else
  434. WARNING_OUT((TEXT("SearchForLocalPath(): Searching for local volume \"%s\", as requested."),
  435. IVOLID_Volume_Label_Ptr((PCIVOLUMEID)pcvolid)));
  436. #endif
  437. ASSERT(IsCharAlpha(*pcszFullPath));
  438. chOriginalDrive = *pcszFullPath;
  439. ASSERT(lstrlen(pcszFullPath) < MAX_PATH_LEN);
  440. lstrcpyn(pszFoundPathBuf, pcszFullPath, cchMax);
  441. /* Get bit mask of local logical drives. */
  442. dwLogicalDrives = GetLogicalDrives();
  443. for (uDrive = 0; uDrive < MAX_LOCAL_DRIVES; uDrive++)
  444. {
  445. if (IS_FLAG_SET(dwLogicalDrives, (1 << uDrive)))
  446. {
  447. TCHAR chDrive;
  448. chDrive = (TCHAR)(TEXT('A') + uDrive);
  449. ASSERT(IsCharAlpha(chDrive));
  450. if (chDrive != chOriginalDrive)
  451. {
  452. TCHAR rgchLocalRootPath[DRIVE_ROOT_PATH_LEN];
  453. lstrcpyn(rgchLocalRootPath, TEXT("A:\\"), ARRAYSIZE(rgchLocalRootPath));
  454. rgchLocalRootPath[0] = chDrive;
  455. /*
  456. * Does this drive's type match the target volume's drive
  457. * type?
  458. */
  459. if (GetDriveType(rgchLocalRootPath) == ((PCIVOLUMEID)pcvolid)->uDriveType)
  460. {
  461. /* Yes. Check the volume. */
  462. TRACE_OUT((TEXT("SearchForLocalPath(): Checking local root path %s."),
  463. rgchLocalRootPath));
  464. bResult = IsPathOnVolume(rgchLocalRootPath,
  465. (PCIVOLUMEID)pcvolid,
  466. &bAvailable);
  467. if (bResult)
  468. {
  469. if (bAvailable)
  470. {
  471. ASSERT(lstrlen(pcszFullPath) < MAX_PATH_LEN);
  472. lstrcpyn(pszFoundPathBuf, pcszFullPath, cchMax);
  473. ASSERT(IsCharAlpha(*pszFoundPathBuf));
  474. *pszFoundPathBuf = chDrive;
  475. TRACE_OUT((TEXT("SearchForLocalPath(): Found matching volume on local path %s."),
  476. pszFoundPathBuf));
  477. break;
  478. }
  479. }
  480. else
  481. break;
  482. }
  483. }
  484. }
  485. }
  486. }
  487. else
  488. /* No. */
  489. #ifdef UNICODE
  490. WARNING_OUT((TEXT("SearchForLocalPath(): Not searching for local volume \"%s\", as requested."),
  491. pszWideVolumeLabel));
  492. #else
  493. WARNING_OUT((TEXT("SearchForLocalPath(): Not searching for local volume \"%s\", as requested."),
  494. IVOLID_Volume_Label_Ptr((PCIVOLUMEID)pcvolid)));
  495. #endif
  496. }
  497. }
  498. ASSERT(! bResult ||
  499. ! bAvailable ||
  500. IsLocalDrivePath(pszFoundPathBuf));
  501. return(bResult && bAvailable);
  502. }
  503. /*
  504. ** GetVolumeIDLen()
  505. **
  506. **
  507. **
  508. ** Arguments:
  509. **
  510. ** Returns:
  511. **
  512. ** Side Effects: none
  513. */
  514. PUBLIC_CODE UINT GetVolumeIDLen(PCVOLUMEID pcvolid)
  515. {
  516. ASSERT(IS_VALID_STRUCT_PTR(pcvolid, CVOLUMEID));
  517. return(((PCIVOLUMEID)pcvolid)->ucbSize);
  518. }
  519. /*
  520. ** GetVolumeSerialNumber()
  521. **
  522. **
  523. **
  524. ** Arguments:
  525. **
  526. ** Returns:
  527. **
  528. ** Side Effects: none
  529. */
  530. PUBLIC_CODE BOOL GetVolumeSerialNumber(PCVOLUMEID pcvolid,
  531. PCDWORD *ppcdwSerialNumber)
  532. {
  533. ASSERT(IS_VALID_STRUCT_PTR(pcvolid, CVOLUMEID));
  534. ASSERT(IS_VALID_WRITE_PTR(ppcdwSerialNumber, PCDWORD));
  535. *ppcdwSerialNumber = &(((PCIVOLUMEID)pcvolid)->dwSerialNumber);
  536. ASSERT(IS_VALID_READ_PTR(*ppcdwSerialNumber, CDWORD));
  537. return(TRUE);
  538. }
  539. /*
  540. ** GetVolumeDriveType()
  541. **
  542. **
  543. **
  544. ** Arguments:
  545. **
  546. ** Returns:
  547. **
  548. ** Side Effects: none
  549. */
  550. PUBLIC_CODE BOOL GetVolumeDriveType(PCVOLUMEID pcvolid, PCUINT *ppcuDriveType)
  551. {
  552. ASSERT(IS_VALID_STRUCT_PTR(pcvolid, CVOLUMEID));
  553. ASSERT(IS_VALID_WRITE_PTR(ppcuDriveType, PCUINT));
  554. *ppcuDriveType = &(((PCIVOLUMEID)pcvolid)->uDriveType);
  555. ASSERT(IS_VALID_READ_PTR(*ppcuDriveType, CUINT));
  556. return(TRUE);
  557. }
  558. /*
  559. ** GetVolumeLabel()
  560. **
  561. **
  562. **
  563. ** Arguments:
  564. **
  565. ** Returns:
  566. **
  567. ** Side Effects: none
  568. */
  569. PUBLIC_CODE BOOL GetVolumeLabel(PCVOLUMEID pcvolid, LPCSTR *ppcszVolumeLabel)
  570. {
  571. ASSERT(IS_VALID_STRUCT_PTR(pcvolid, CVOLUMEID));
  572. ASSERT(IS_VALID_WRITE_PTR(ppcszVolumeLabel, LPCTSTR));
  573. *ppcszVolumeLabel = IVOLID_Volume_Label_PtrA((PCIVOLUMEID)pcvolid);
  574. ASSERT(IS_VALID_STRING_PTRA(*ppcszVolumeLabel, CSTR));
  575. return(TRUE);
  576. }
  577. #ifdef UNICODE
  578. /*
  579. ** GetVolumeLabelW()
  580. **
  581. **
  582. **
  583. ** Arguments:
  584. **
  585. ** Returns:
  586. **
  587. ** Side Effects: none
  588. */
  589. PUBLIC_CODE BOOL GetVolumeLabelW(PCVOLUMEID pcvolid, LPCWSTR *ppcszVolumeLabel)
  590. {
  591. ASSERT(IS_VALID_STRUCT_PTR(pcvolid, CVOLUMEID));
  592. ASSERT(IS_VALID_WRITE_PTR(ppcszVolumeLabel, LPCTSTR));
  593. if (((PCIVOLUMEID)pcvolid)->ucbVolumeLabelOffset == SIZEOF(IVOLUMEIDW))
  594. {
  595. *ppcszVolumeLabel = IVOLID_Volume_Label_PtrW((PCIVOLUMEID)pcvolid);
  596. ASSERT(IS_VALID_STRING_PTR(*ppcszVolumeLabel, CSTR));
  597. }
  598. else
  599. {
  600. *ppcszVolumeLabel = NULL;
  601. }
  602. return(TRUE);
  603. }
  604. #endif
  605. /*
  606. ** CompareDWORDs()
  607. **
  608. **
  609. **
  610. ** Arguments:
  611. **
  612. ** Returns:
  613. **
  614. ** Side Effects: none
  615. */
  616. PUBLIC_CODE COMPARISONRESULT CompareDWORDs(DWORD dwFirst, DWORD dwSecond)
  617. {
  618. COMPARISONRESULT cr;
  619. /* Any DWORDs are valid input. */
  620. if (dwFirst < dwSecond)
  621. cr = CR_FIRST_SMALLER;
  622. else if (dwFirst > dwSecond)
  623. cr = CR_FIRST_LARGER;
  624. else
  625. cr = CR_EQUAL;
  626. ASSERT(IsValidCOMPARISONRESULT(cr));
  627. return(cr);
  628. }
  629. #if defined(DEBUG) || defined (VSTF)
  630. /*
  631. ** IsValidPCVOLUMEID()
  632. **
  633. **
  634. **
  635. ** Arguments:
  636. **
  637. ** Returns:
  638. **
  639. ** Side Effects: none
  640. */
  641. PUBLIC_CODE BOOL IsValidPCVOLUMEID(PCVOLUMEID pcvolid)
  642. {
  643. return(IS_VALID_STRUCT_PTR((PCIVOLUMEID)pcvolid, CIVOLUMEID));
  644. }
  645. #endif
  646. #ifdef DEBUG
  647. /*
  648. ** DumpVolumeID()
  649. **
  650. **
  651. **
  652. ** Arguments:
  653. **
  654. ** Returns:
  655. **
  656. ** Side Effects: none
  657. */
  658. PUBLIC_CODE void DumpVolumeID(PCVOLUMEID pcvolid)
  659. {
  660. ASSERT(IS_VALID_STRUCT_PTR(pcvolid, CVOLUMEID));
  661. PLAIN_TRACE_OUT((TEXT("%s%s[local volume ID] ucbSize = %#x"),
  662. INDENT_STRING,
  663. INDENT_STRING,
  664. ((PCIVOLUMEID)pcvolid)->ucbSize));
  665. PLAIN_TRACE_OUT((TEXT("%s%s[local volume ID] drive type %u"),
  666. INDENT_STRING,
  667. INDENT_STRING,
  668. ((PCIVOLUMEID)pcvolid)->uDriveType));
  669. PLAIN_TRACE_OUT((TEXT("%s%s[local volume ID] serial number %#08lx"),
  670. INDENT_STRING,
  671. INDENT_STRING,
  672. ((PCIVOLUMEID)pcvolid)->dwSerialNumber));
  673. PLAIN_TRACE_OUT((TEXT("%s%s[local volume ID] label \"%s\""),
  674. INDENT_STRING,
  675. INDENT_STRING,
  676. IVOLID_Volume_Label_Ptr((PCIVOLUMEID)pcvolid)));
  677. return;
  678. }
  679. #endif