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.

645 lines
13 KiB

  1. /*
  2. * comc.c - Shared routines.
  3. */
  4. /* Headers
  5. **********/
  6. #include "project.h"
  7. #pragma hdrstop
  8. /****************************** Public Functions *****************************/
  9. /*
  10. ** CatPath()
  11. **
  12. ** Appends a filename to a path string.
  13. **
  14. ** Arguments: pszPath - path string that file name is to be appended to
  15. ** pcszSubPath - path to append
  16. **
  17. ** Returns: void
  18. **
  19. ** Side Effects: none
  20. **
  21. ** N.b., truncates path to MAX_PATH_LEN characters in length.
  22. **
  23. ** Examples:
  24. **
  25. ** input path input file name output path
  26. ** ---------- --------------- -----------
  27. ** c:\ foo c:\foo
  28. ** c: foo c:foo
  29. ** c:\foo\bar\ goo c:\foo\bar\goo
  30. ** c:\foo\bar\ \goo c:\foo\bar\goo
  31. ** c:\foo\bar\ goo\shoe c:\foo\bar\goo\shoe
  32. ** c:\foo\bar\ \goo\shoe\ c:\foo\bar\goo\shoe\
  33. ** foo\bar\ goo foo\bar\goo
  34. ** <empty string> <empty string> <empty string>
  35. ** <empty string> foo foo
  36. ** foo <empty string> foo
  37. ** fred bird fred\bird
  38. */
  39. PUBLIC_CODE void CatPath(LPTSTR pszPath, LPCTSTR pcszSubPath, int cchMax)
  40. {
  41. LPTSTR pcsz;
  42. LPTSTR pcszLast;
  43. ASSERT(IS_VALID_STRING_PTR(pszPath, STR));
  44. ASSERT(IS_VALID_STRING_PTR(pcszSubPath, CSTR));
  45. ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszPath, STR, cchMax));
  46. /* Find last character in path string. */
  47. for (pcsz = pcszLast = pszPath; *pcsz; pcsz = CharNext(pcsz))
  48. pcszLast = pcsz;
  49. if (IS_SLASH(*pcszLast) && IS_SLASH(*pcszSubPath))
  50. pcszSubPath++;
  51. else if (! IS_SLASH(*pcszLast) && ! IS_SLASH(*pcszSubPath))
  52. {
  53. if (*pcszLast && *pcszLast != COLON && *pcszSubPath && ((lstrlen(pszPath) + 1) < cchMax))
  54. *pcsz++ = TEXT('\\');
  55. }
  56. MyLStrCpyN(pcsz, pcszSubPath, cchMax - (int)(pcsz - pszPath));
  57. ASSERT(IS_VALID_STRING_PTR(pszPath, STR));
  58. return;
  59. }
  60. /*
  61. ** MapIntToComparisonResult()
  62. **
  63. **
  64. **
  65. ** Arguments:
  66. **
  67. ** Returns:
  68. **
  69. ** Side Effects: none
  70. */
  71. PUBLIC_CODE COMPARISONRESULT MapIntToComparisonResult(int nResult)
  72. {
  73. COMPARISONRESULT cr;
  74. /* Any integer is valid input. */
  75. if (nResult < 0)
  76. cr = CR_FIRST_SMALLER;
  77. else if (nResult > 0)
  78. cr = CR_FIRST_LARGER;
  79. else
  80. cr = CR_EQUAL;
  81. return(cr);
  82. }
  83. /*
  84. ** MyLStrCpyN()
  85. **
  86. ** Like lstrcpyn(), but the copy is limited to ucb bytes. The destination
  87. ** string is always null-terminated.
  88. **
  89. ** Arguments: pszDest - pointer to destination buffer
  90. ** pcszSrc - pointer to source string
  91. ** ncb - maximum number of bytes to copy, including null
  92. ** terminator
  93. **
  94. ** Returns: void
  95. **
  96. ** Side Effects: none
  97. **
  98. ** N.b., this function behaves quite differently than strncpy()! It does not
  99. ** pad out the destination buffer with null characters, and it always null
  100. ** terminates the destination string.
  101. */
  102. PUBLIC_CODE void MyLStrCpyN(LPTSTR pszDest, LPCTSTR pcszSrc, int ncch)
  103. {
  104. ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszDest, STR, ncch * sizeof(TCHAR)));
  105. ASSERT(IS_VALID_STRING_PTR(pcszSrc, CSTR));
  106. ASSERT(ncch > 0);
  107. while (ncch > 1)
  108. {
  109. ncch--;
  110. *pszDest = *pcszSrc;
  111. if (*pcszSrc)
  112. {
  113. pszDest++;
  114. pcszSrc++;
  115. }
  116. else
  117. break;
  118. }
  119. if (ncch == 1)
  120. *pszDest = TEXT('\0');
  121. ASSERT(IS_VALID_STRING_PTR(pszDest, STR));
  122. ASSERT(lstrlen(pszDest) < ncch);
  123. ASSERT(lstrlen(pszDest) <= lstrlen(pcszSrc));
  124. return;
  125. }
  126. #ifdef DEBUG
  127. /*
  128. ** IsStringContained()
  129. **
  130. **
  131. **
  132. ** Arguments:
  133. **
  134. ** Returns:
  135. **
  136. ** Side Effects: none
  137. */
  138. PUBLIC_CODE BOOL IsStringContained(LPCTSTR pcszBigger, LPCTSTR pcszSuffix)
  139. {
  140. ASSERT(IS_VALID_STRING_PTR(pcszBigger, CSTR));
  141. ASSERT(IS_VALID_STRING_PTR(pcszSuffix, CSTR));
  142. return(pcszSuffix >= pcszBigger &&
  143. pcszSuffix <= pcszBigger + lstrlen(pcszBigger));
  144. }
  145. #endif
  146. #if defined(_SYNCENG_) || defined(_LINKINFO_)
  147. /*
  148. ** DeleteLastPathElement()
  149. **
  150. **
  151. **
  152. ** Arguments:
  153. **
  154. ** Returns:
  155. **
  156. ** Side Effects: none
  157. */
  158. PUBLIC_CODE void DeleteLastPathElement(LPTSTR pszPath)
  159. {
  160. LPTSTR psz;
  161. LPTSTR pszLastSep;
  162. ASSERT(IS_VALID_STRING_PTR(pszPath, STR));
  163. psz = pszPath;
  164. pszLastSep = psz;
  165. while (*psz)
  166. {
  167. if (*psz == TEXT('\\'))
  168. pszLastSep = psz;
  169. psz = CharNext(psz);
  170. }
  171. /*
  172. * Now truncate the path at the last separator found, or the beginning of
  173. * the path if no path separators were found.
  174. */
  175. *pszLastSep = TEXT('\0');
  176. ASSERT(IS_VALID_STRING_PTR(pszPath, STR));
  177. return;
  178. }
  179. /*
  180. ** GetDefaultRegKeyValue()
  181. **
  182. **
  183. **
  184. ** Arguments:
  185. **
  186. ** Returns:
  187. **
  188. ** Side Effects: none
  189. */
  190. PUBLIC_CODE LONG GetDefaultRegKeyValue(HKEY hkeyParent, LPCTSTR pcszSubKey,
  191. LPTSTR pszBuf, PDWORD pdwcbBufLen)
  192. {
  193. LONG lResult;
  194. HKEY hkeySubKey;
  195. ASSERT(IS_VALID_HANDLE(hkeyParent, KEY));
  196. ASSERT(IS_VALID_STRING_PTR(pcszSubKey, CSTR));
  197. ASSERT(! pszBuf ||
  198. IS_VALID_WRITE_BUFFER_PTR(pszBuf, STR, *pdwcbBufLen));
  199. lResult = RegOpenKeyEx(hkeyParent, pcszSubKey, 0, KEY_QUERY_VALUE,
  200. &hkeySubKey);
  201. if (lResult == ERROR_SUCCESS)
  202. {
  203. DWORD dwValueType;
  204. lResult = RegQueryValueEx(hkeySubKey, NULL, NULL, &dwValueType,
  205. (PBYTE)pszBuf, pdwcbBufLen);
  206. if (lResult == ERROR_SUCCESS)
  207. {
  208. ASSERT(dwValueType == REG_SZ);
  209. /* (+ 1) for null terminator. */
  210. ASSERT(! pszBuf ||
  211. (DWORD)(lstrlen(pszBuf) + 1) * sizeof(TCHAR) == *pdwcbBufLen);
  212. TRACE_OUT((TEXT("GetDefaultRegKeyValue(): Default key value for subkey %s is \"%s\"."),
  213. pcszSubKey,
  214. pszBuf));
  215. }
  216. else
  217. TRACE_OUT((TEXT("GetDefaultRegKeyValue(): RegQueryValueEx() for subkey %s failed, returning %ld."),
  218. pcszSubKey,
  219. lResult));
  220. EVAL(RegCloseKey(hkeySubKey) == ERROR_SUCCESS);
  221. }
  222. else
  223. TRACE_OUT((TEXT("GetDefaultRegKeyValue(): RegOpenKeyEx() for subkey %s failed, returning %ld."),
  224. pcszSubKey,
  225. lResult));
  226. return(lResult);
  227. }
  228. /*
  229. ** StringCopy()
  230. **
  231. **
  232. **
  233. ** Arguments:
  234. **
  235. ** Returns: TWINRESULT
  236. **
  237. ** Side Effects: none
  238. */
  239. PUBLIC_CODE BOOL StringCopy(LPCTSTR pcszSrc, LPTSTR *ppszCopy)
  240. {
  241. BOOL bResult;
  242. ASSERT(IS_VALID_STRING_PTR(pcszSrc, CSTR));
  243. ASSERT(IS_VALID_WRITE_PTR(ppszCopy, LPTSTR));
  244. /* (+ 1) for null terminator. */
  245. bResult = AllocateMemory((lstrlen(pcszSrc) + 1) * sizeof(TCHAR), ppszCopy);
  246. if (bResult)
  247. lstrcpy(*ppszCopy, pcszSrc); // allocated dynamically above
  248. ASSERT(! bResult ||
  249. IS_VALID_STRING_PTR(*ppszCopy, STR));
  250. return(bResult);
  251. }
  252. /*
  253. ** ComparePathStrings()
  254. **
  255. **
  256. **
  257. ** Arguments:
  258. **
  259. ** Returns:
  260. **
  261. ** Side Effects: none
  262. */
  263. PUBLIC_CODE COMPARISONRESULT ComparePathStrings(LPCTSTR pcszFirst, LPCTSTR pcszSecond)
  264. {
  265. ASSERT(IS_VALID_STRING_PTR(pcszFirst, CSTR));
  266. ASSERT(IS_VALID_STRING_PTR(pcszSecond, CSTR));
  267. return(MapIntToComparisonResult(lstrcmpi(pcszFirst, pcszSecond)));
  268. }
  269. /*
  270. ** MyStrChr()
  271. **
  272. **
  273. **
  274. ** Arguments:
  275. **
  276. ** Returns:
  277. **
  278. ** Side Effects: none
  279. */
  280. PUBLIC_CODE BOOL MyStrChr(LPCTSTR pcsz, TCHAR chTarget, LPCTSTR *ppcszTarget)
  281. {
  282. LPCTSTR pcszFound;
  283. ASSERT(IS_VALID_STRING_PTR(pcsz, CSTR));
  284. ASSERT(! ppcszTarget || IS_VALID_WRITE_PTR(ppcszTarget, LPCTSTR));
  285. /* This works correctly if chTarget is the null terminator '\0'. */
  286. while (*pcsz && *pcsz != chTarget)
  287. pcsz = CharNext(pcsz);
  288. if (*pcsz == chTarget)
  289. pcszFound = pcsz;
  290. else
  291. pcszFound = NULL;
  292. if (ppcszTarget)
  293. *ppcszTarget = pcszFound;
  294. return(pcszFound != NULL);
  295. }
  296. /*
  297. ** PathExists()
  298. **
  299. **
  300. **
  301. ** Arguments:
  302. **
  303. ** Returns:
  304. **
  305. ** Side Effects: none
  306. */
  307. PUBLIC_CODE BOOL PathExists(LPCTSTR pcszPath)
  308. {
  309. DWORD dwErrMode;
  310. BOOL fResult;
  311. ASSERT(IS_VALID_STRING_PTR(pcszPath, CSTR));
  312. dwErrMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  313. fResult = (GetFileAttributes(pcszPath) != -1);
  314. SetErrorMode(dwErrMode);
  315. return fResult;
  316. }
  317. /*
  318. ** IsDrivePath()
  319. **
  320. ** Determines whether or not a path is in "c:\" form.
  321. **
  322. ** Arguments: pcszPath - path to examine
  323. **
  324. ** Returns: TRUE if path is in "c:\" form. FALSE if not.
  325. **
  326. ** Side Effects: none
  327. */
  328. PUBLIC_CODE BOOL IsDrivePath(LPCTSTR pcszFullPath)
  329. {
  330. BOOL bResult;
  331. ASSERT(IsFullPath(pcszFullPath));
  332. if (lstrlen(pcszFullPath) >= 3 &&
  333. IsCharAlpha(pcszFullPath[0]) &&
  334. pcszFullPath[1] == COLON &&
  335. IS_SLASH(pcszFullPath[2]))
  336. bResult = TRUE;
  337. else
  338. bResult = FALSE;
  339. return(bResult);
  340. }
  341. #if defined(DEBUG) || defined(VSTF)
  342. /*
  343. ** IsValidDriveType()
  344. **
  345. **
  346. **
  347. ** Arguments:
  348. **
  349. ** Returns:
  350. **
  351. ** Side Effects: none
  352. */
  353. PUBLIC_CODE BOOL IsValidDriveType(UINT uDriveType)
  354. {
  355. BOOL bResult;
  356. switch (uDriveType)
  357. {
  358. case DRIVE_UNKNOWN:
  359. case DRIVE_NO_ROOT_DIR:
  360. case DRIVE_REMOVABLE:
  361. case DRIVE_FIXED:
  362. case DRIVE_REMOTE:
  363. case DRIVE_CDROM:
  364. case DRIVE_RAMDISK:
  365. bResult = TRUE;
  366. break;
  367. default:
  368. ERROR_OUT((TEXT("IsValidDriveType(): Invalid drive type %u."),
  369. uDriveType));
  370. bResult = FALSE;
  371. break;
  372. }
  373. return(bResult);
  374. }
  375. /*
  376. ** IsValidPathSuffix()
  377. **
  378. **
  379. **
  380. ** Arguments:
  381. **
  382. ** Returns:
  383. **
  384. ** Side Effects: none
  385. **
  386. ** A path suffix should not begin or end with a slash.
  387. */
  388. PUBLIC_CODE BOOL IsValidPathSuffix(LPCTSTR pcszPathSuffix)
  389. {
  390. return(IS_VALID_STRING_PTR(pcszPathSuffix, CSTR) &&
  391. EVAL(lstrlen(pcszPathSuffix) < MAX_PATH_LEN) &&
  392. EVAL(! IS_SLASH(*pcszPathSuffix)) &&
  393. EVAL(! IS_SLASH(*CharPrev(pcszPathSuffix, pcszPathSuffix + lstrlen(pcszPathSuffix)))));
  394. }
  395. #endif /* DEBUG || VSTF */
  396. #ifdef DEBUG
  397. /*
  398. ** IsRootPath()
  399. **
  400. **
  401. **
  402. ** Arguments:
  403. **
  404. ** Returns:
  405. **
  406. ** Side Effects: none
  407. */
  408. PUBLIC_CODE BOOL IsRootPath(LPCTSTR pcszFullPath)
  409. {
  410. TCHAR rgchCanonicalPath[MAX_PATH_LEN];
  411. DWORD dwOutFlags;
  412. TCHAR rgchNetResource[MAX_PATH_LEN];
  413. LPTSTR pszRootPathSuffix;
  414. ASSERT(IsFullPath(pcszFullPath));
  415. return(GetCanonicalPathInfo(pcszFullPath, rgchCanonicalPath, &dwOutFlags,
  416. rgchNetResource, &pszRootPathSuffix) &&
  417. ! *pszRootPathSuffix);
  418. }
  419. /*
  420. ** IsTrailingSlashCanonicalized()
  421. **
  422. **
  423. **
  424. ** Arguments:
  425. **
  426. ** Returns:
  427. **
  428. ** Side Effects: none
  429. */
  430. PUBLIC_CODE BOOL IsTrailingSlashCanonicalized(LPCTSTR pcszFullPath)
  431. {
  432. BOOL bResult;
  433. BOOL bSlashLast;
  434. LPCTSTR pcszLastPathChar;
  435. ASSERT(IsFullPath(pcszFullPath));
  436. /* Make sure that the path only ends in a slash for root paths. */
  437. pcszLastPathChar = CharPrev(pcszFullPath, pcszFullPath + lstrlen(pcszFullPath));
  438. ASSERT(pcszLastPathChar >= pcszFullPath);
  439. bSlashLast = IS_SLASH(*pcszLastPathChar);
  440. /* Is this a root path? */
  441. if (IsRootPath(pcszFullPath))
  442. bResult = bSlashLast;
  443. else
  444. bResult = ! bSlashLast;
  445. return(bResult);
  446. }
  447. /*
  448. ** IsFullPath()
  449. **
  450. **
  451. **
  452. ** Arguments:
  453. **
  454. ** Returns:
  455. **
  456. ** Side Effects: none
  457. */
  458. PUBLIC_CODE BOOL IsFullPath(LPCTSTR pcszPath)
  459. {
  460. BOOL bResult = FALSE;
  461. TCHAR rgchFullPath[MAX_PATH_LEN];
  462. if (IS_VALID_STRING_PTR(pcszPath, CSTR) &&
  463. EVAL(lstrlen(pcszPath) < MAX_PATH_LEN))
  464. {
  465. DWORD dwPathLen;
  466. LPTSTR pszFileName;
  467. dwPathLen = GetFullPathName(pcszPath, ARRAYSIZE(rgchFullPath), rgchFullPath,
  468. &pszFileName);
  469. if (EVAL(dwPathLen > 0) &&
  470. EVAL(dwPathLen < ARRAYSIZE(rgchFullPath)))
  471. bResult = EVAL(ComparePathStrings(pcszPath, rgchFullPath) == CR_EQUAL);
  472. }
  473. return(bResult);
  474. }
  475. /*
  476. ** IsCanonicalPath()
  477. **
  478. **
  479. **
  480. ** Arguments:
  481. **
  482. ** Returns:
  483. **
  484. ** Side Effects: none
  485. */
  486. PUBLIC_CODE BOOL IsCanonicalPath(LPCTSTR pcszPath)
  487. {
  488. return(EVAL(IsFullPath(pcszPath)) &&
  489. EVAL(IsTrailingSlashCanonicalized(pcszPath)));
  490. }
  491. /*
  492. ** IsValidCOMPARISONRESULT()
  493. **
  494. **
  495. **
  496. ** Arguments:
  497. **
  498. ** Returns:
  499. **
  500. ** Side Effects: none
  501. */
  502. PUBLIC_CODE BOOL IsValidCOMPARISONRESULT(COMPARISONRESULT cr)
  503. {
  504. BOOL bResult;
  505. switch (cr)
  506. {
  507. case CR_FIRST_SMALLER:
  508. case CR_EQUAL:
  509. case CR_FIRST_LARGER:
  510. bResult = TRUE;
  511. break;
  512. default:
  513. WARNING_OUT((TEXT("IsValidCOMPARISONRESULT(): Unknown COMPARISONRESULT %d."),
  514. cr));
  515. bResult = FALSE;
  516. break;
  517. }
  518. return(bResult);
  519. }
  520. #endif /* DEBUG */
  521. #endif /* _SYNCENG_ || _LINKINFO_ */