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.

374 lines
8.2 KiB

  1. /*
  2. * util.c - Miscellaneous utility functions module.
  3. */
  4. /* Headers
  5. **********/
  6. #include "project.h"
  7. #pragma hdrstop
  8. #include <uastrfnc.h> // for ualstrcpyn (used on unaligned UNICODE strings)
  9. /****************************** Public Functions *****************************/
  10. /*
  11. ** NotifyShell()
  12. **
  13. ** Notifies the Shell of an event.
  14. **
  15. ** Arguments: pcszPath - path string related to event
  16. ** nse - event
  17. **
  18. ** Returns: void
  19. **
  20. ** Side Effects: none
  21. */
  22. PUBLIC_CODE void NotifyShell(LPCTSTR pcszPath, NOTIFYSHELLEVENT nse)
  23. {
  24. /*
  25. * N.b., these events must match the enumerated NOTIFYSHELLEVENT values in
  26. * util.h.
  27. */
  28. static const LONG SrgclShellEvents[] =
  29. {
  30. SHCNE_CREATE,
  31. SHCNE_DELETE,
  32. SHCNE_MKDIR,
  33. SHCNE_RMDIR,
  34. SHCNE_UPDATEITEM,
  35. SHCNE_UPDATEDIR
  36. };
  37. #ifdef DEBUG
  38. static const LPCTSTR SrgpcszShellEvents[] =
  39. {
  40. TEXT("create item"),
  41. TEXT("delete item"),
  42. TEXT("create folder"),
  43. TEXT("delete folder"),
  44. TEXT("update item"),
  45. TEXT("update folder")
  46. };
  47. #endif
  48. ASSERT(IS_VALID_STRING_PTR(pcszPath, CSTR));
  49. ASSERT(nse < ARRAY_ELEMENTS(SrgclShellEvents));
  50. ASSERT(nse < ARRAY_ELEMENTS(SrgpcszShellEvents));
  51. TRACE_OUT((TEXT("NotifyShell(): Sending %s notification for %s."),
  52. SrgpcszShellEvents[nse],
  53. pcszPath));
  54. SHChangeNotify(SrgclShellEvents[nse], SHCNF_PATH, pcszPath, NULL);
  55. }
  56. /*
  57. ** ComparePathStringsByHandle()
  58. **
  59. **
  60. **
  61. ** Arguments:
  62. **
  63. ** Returns:
  64. **
  65. ** Side Effects: none
  66. */
  67. PUBLIC_CODE COMPARISONRESULT ComparePathStringsByHandle(HSTRING hsFirst,
  68. HSTRING hsSecond)
  69. {
  70. ASSERT(IS_VALID_HANDLE(hsFirst, STRING));
  71. ASSERT(IS_VALID_HANDLE(hsSecond, STRING));
  72. return(CompareStringsI(hsFirst, hsSecond));
  73. }
  74. /*
  75. ** MyLStrCmpNI()
  76. **
  77. **
  78. **
  79. ** Arguments:
  80. **
  81. ** Returns:
  82. **
  83. ** Side Effects: none
  84. */
  85. PUBLIC_CODE COMPARISONRESULT MyLStrCmpNI(LPCTSTR pcsz1, LPCTSTR pcsz2, int ncbLen)
  86. {
  87. int n = 0;
  88. ASSERT(IS_VALID_STRING_PTR(pcsz1, CSTR));
  89. ASSERT(IS_VALID_STRING_PTR(pcsz2, CSTR));
  90. ASSERT(ncbLen >= 0);
  91. while (ncbLen > 0 &&
  92. ! (n = PtrToUlong(CharLower((LPTSTR)(ULONG_PTR)*pcsz1))
  93. - PtrToUlong(CharLower((LPTSTR)(ULONG_PTR)*pcsz2))) &&
  94. *pcsz1)
  95. {
  96. pcsz1++;
  97. pcsz2++;
  98. ncbLen--;
  99. }
  100. return(MapIntToComparisonResult(n));
  101. }
  102. /*
  103. /*
  104. ** ComposePath()
  105. **
  106. ** Composes a path string given a folder and a filename.
  107. **
  108. ** Arguments: pszBuffer - path string that is created
  109. ** pcszFolder - path string of the folder
  110. ** pcszName - path to append
  111. **
  112. ** Returns: void
  113. **
  114. ** Side Effects: none
  115. **
  116. ** N.b., truncates path to MAX_PATH_LEN bytes in length.
  117. */
  118. PUBLIC_CODE void ComposePath(LPTSTR pszBuffer, LPCTSTR pcszFolder, LPCTSTR pcszName, int cchMax)
  119. {
  120. ASSERT(IS_VALID_STRING_PTR(pszBuffer, STR));
  121. ASSERT(IS_VALID_STRING_PTR(pcszFolder, CSTR));
  122. ASSERT(IS_VALID_STRING_PTR(pcszName, CSTR));
  123. ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszBuffer, STR, cchMax));
  124. //
  125. // REARCHITECT - BobDay - We should figure out who needs this unaligned thing
  126. // and remove it from here. The function prototype doesn't mention any
  127. // unaligned stuff so we must have a bug somewhere.
  128. // Consider adding a debug check here for an unaligned pcszFolder pointer
  129. // and assert when it occurs so we can debug it.
  130. //
  131. ualstrcpyn(pszBuffer, pcszFolder, cchMax);
  132. CatPath(pszBuffer, pcszName, cchMax);
  133. ASSERT(IS_VALID_STRING_PTR(pszBuffer, STR));
  134. return;
  135. }
  136. /*
  137. ** ExtractFileName()
  138. **
  139. ** Extracts the file name from a path name.
  140. **
  141. ** Arguments: pcszPathName - path string from which to extract file name
  142. **
  143. ** Returns: Pointer to file name in path string.
  144. **
  145. ** Side Effects: none
  146. */
  147. PUBLIC_CODE LPCTSTR ExtractFileName(LPCTSTR pcszPathName)
  148. {
  149. LPCTSTR pcszLastComponent;
  150. LPCTSTR pcsz;
  151. ASSERT(IS_VALID_STRING_PTR(pcszPathName, CSTR));
  152. for (pcszLastComponent = pcsz = pcszPathName;
  153. *pcsz;
  154. pcsz = CharNext(pcsz))
  155. {
  156. if (IS_SLASH(*pcsz) || *pcsz == COLON)
  157. pcszLastComponent = CharNext(pcsz);
  158. }
  159. ASSERT(IS_VALID_STRING_PTR(pcszLastComponent, CSTR));
  160. return(pcszLastComponent);
  161. }
  162. /*
  163. ** ExtractExtension()
  164. **
  165. ** Extracts the extension from a file.
  166. **
  167. ** Arguments: pcszName - name whose extension is to be extracted
  168. **
  169. ** Returns: If the name contains an extension, a pointer to the period at
  170. ** the beginning of the extension is returned. If the name has
  171. ** no extension, a pointer to the name's null terminator is
  172. ** returned.
  173. **
  174. ** Side Effects: none
  175. */
  176. PUBLIC_CODE LPCTSTR ExtractExtension(LPCTSTR pcszName)
  177. {
  178. LPCTSTR pcszLastPeriod;
  179. ASSERT(IS_VALID_STRING_PTR(pcszName, CSTR));
  180. /* Make sure we have an isolated file name. */
  181. pcszName = ExtractFileName(pcszName);
  182. pcszLastPeriod = NULL;
  183. while (*pcszName)
  184. {
  185. if (*pcszName == PERIOD)
  186. pcszLastPeriod = pcszName;
  187. pcszName = CharNext(pcszName);
  188. }
  189. if (! pcszLastPeriod)
  190. {
  191. /* Point at null terminator. */
  192. pcszLastPeriod = pcszName;
  193. ASSERT(! *pcszLastPeriod);
  194. }
  195. else
  196. /* Point at period at beginning of extension. */
  197. ASSERT(*pcszLastPeriod == PERIOD);
  198. ASSERT(IS_VALID_STRING_PTR(pcszLastPeriod, CSTR));
  199. return(pcszLastPeriod);
  200. }
  201. /*
  202. ** GetHashBucketIndex()
  203. **
  204. ** Calculates the hash bucket index for a string.
  205. **
  206. ** Arguments: pcsz - pointer to string whose hash bucket index is to be
  207. ** calculated
  208. ** hbc - number of hash buckets in string table
  209. **
  210. ** Returns: Hash bucket index for string.
  211. **
  212. ** Side Effects: none
  213. **
  214. ** The hashing function used is the sum of the byte values in the string modulo
  215. ** the number of buckets in the hash table.
  216. */
  217. PUBLIC_CODE HASHBUCKETCOUNT GetHashBucketIndex(LPCTSTR pcsz,
  218. HASHBUCKETCOUNT hbc)
  219. {
  220. ULONG ulSum;
  221. ASSERT(IS_VALID_STRING_PTR(pcsz, CSTR));
  222. ASSERT(hbc > 0);
  223. /* Don't worry about overflow here. */
  224. for (ulSum = 0; *pcsz; pcsz++)
  225. ulSum += *pcsz;
  226. return((HASHBUCKETCOUNT)(ulSum % hbc));
  227. }
  228. /*
  229. ** RegKeyExists()
  230. **
  231. **
  232. **
  233. ** Arguments:
  234. **
  235. ** Returns:
  236. **
  237. ** Side Effects: none
  238. */
  239. PUBLIC_CODE BOOL RegKeyExists(HKEY hkeyParent, LPCTSTR pcszSubKey)
  240. {
  241. BOOL bResult;
  242. HKEY hkeySubKey;
  243. ASSERT(IS_VALID_HANDLE(hkeyParent, KEY));
  244. ASSERT(IS_VALID_STRING_PTR(pcszSubKey, CSTR));
  245. bResult = (RegOpenKeyEx(hkeyParent, pcszSubKey, 0, KEY_QUERY_VALUE,
  246. &hkeySubKey)
  247. == ERROR_SUCCESS);
  248. if (bResult)
  249. EVAL(RegCloseKey(hkeySubKey) == ERROR_SUCCESS);
  250. return(bResult);
  251. }
  252. /*
  253. ** CopyLinkInfo()
  254. **
  255. ** Copies LinkInfo into local memory.
  256. **
  257. ** Arguments: pcliSrc - source LinkInfo
  258. ** ppliDest - pointer to PLINKINFO to be filled in with pointer
  259. ** to local copy
  260. **
  261. ** Returns: TRUE if successful. FALSE if not.
  262. **
  263. ** Side Effects: none
  264. */
  265. PUBLIC_CODE BOOL CopyLinkInfo(PCLINKINFO pcliSrc, PLINKINFO *ppliDest)
  266. {
  267. BOOL bResult;
  268. DWORD dwcbSize;
  269. ASSERT(IS_VALID_STRUCT_PTR(pcliSrc, CLINKINFO));
  270. ASSERT(IS_VALID_WRITE_PTR(ppliDest, PLINKINFO));
  271. dwcbSize = *(PDWORD)pcliSrc;
  272. bResult = AllocateMemory(dwcbSize, ppliDest);
  273. if (bResult)
  274. CopyMemory(*ppliDest, pcliSrc, dwcbSize);
  275. ASSERT(! bResult ||
  276. IS_VALID_STRUCT_PTR(*ppliDest, CLINKINFO));
  277. return(bResult);
  278. }
  279. #if defined(DEBUG) || defined(VSTF)
  280. /*
  281. ** IsValidPCLINKINFO()
  282. **
  283. **
  284. **
  285. ** Arguments:
  286. **
  287. ** Returns:
  288. **
  289. ** Side Effects: none
  290. */
  291. PUBLIC_CODE BOOL IsValidPCLINKINFO(PCLINKINFO pcli)
  292. {
  293. BOOL bResult;
  294. if (IS_VALID_READ_BUFFER_PTR(pcli, CDWORD, sizeof(DWORD)) &&
  295. IS_VALID_READ_BUFFER_PTR(pcli, CLINKINFO, (UINT)*(PDWORD)pcli))
  296. bResult = TRUE;
  297. else
  298. bResult = FALSE;
  299. return(bResult);
  300. }
  301. #endif