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.

360 lines
9.3 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1998 - 1998.
  5. //
  6. // File: fileutil.cxx
  7. //
  8. // Contents: Utility functions for file migration
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 07-Sep-99 PhilipLa Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "common.hxx"
  18. #include "fileutil.hxx"
  19. #include <tchar.h>
  20. #define LINEBUFSIZE 1024
  21. DWORD StatePrintfA (HANDLE h, CHAR *szFormat, ...)
  22. {
  23. CHAR szBuffer[LINEBUFSIZE];
  24. #if 0
  25. #ifdef UNICODE
  26. WCHAR wszFormat[LINEBUFSIZE];
  27. //Convert to Unicode
  28. UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
  29. if (0 == MultiByteToWideChar(uCodePage,
  30. 0,
  31. szFormat,
  32. -1,
  33. wszFormat,
  34. LINEBUFSIZE))
  35. {
  36. return GetLastError();
  37. }
  38. ptsFormat = wszFormat;
  39. #else
  40. ptsFormat = szFormat;
  41. #endif
  42. #endif
  43. va_list va;
  44. ULONG ulWritten;
  45. ULONG ulLen;
  46. va_start (va, szFormat);
  47. ulLen = FormatMessageA(FORMAT_MESSAGE_FROM_STRING,
  48. szFormat,
  49. 0,
  50. 0,
  51. szBuffer,
  52. LINEBUFSIZE,
  53. &va);
  54. va_end(va);
  55. if (FALSE == WriteFile (h, szBuffer, ulLen, &ulWritten, NULL))
  56. return GetLastError();
  57. else
  58. {
  59. if (ulWritten != ulLen) // incomplete write
  60. return ERROR_WRITE_FAULT; // last error may not be set
  61. }
  62. return ERROR_SUCCESS;
  63. }
  64. BOOL MatchString(const TCHAR *ptsPattern,
  65. const TCHAR *ptsString,
  66. const BOOL bRequireNullPatMatch)
  67. {
  68. ULONG iPat = 0;
  69. ULONG iStr = 0;
  70. TCHAR tcPat;
  71. TCHAR tcStr;
  72. if (ptsPattern[0] == 0)
  73. {
  74. //No pattern to match
  75. if (bRequireNullPatMatch == FALSE)
  76. return TRUE;
  77. if ( ptsString[0] == 0)
  78. return TRUE;
  79. return FALSE;
  80. }
  81. //Special case: Empty string, * as pattern
  82. if (ptsString[0] == 0 &&
  83. ptsPattern[0] == TEXT('*') &&
  84. ptsPattern[1] == 0)
  85. {
  86. return TRUE;
  87. }
  88. while (ptsString[iStr])
  89. {
  90. tcPat = (TCHAR)_totlower(ptsPattern[iPat]);
  91. tcStr = (TCHAR)_totlower(ptsString[iStr]);
  92. if (tcPat == 0)
  93. {
  94. //Reached end of pattern, return FALSE;
  95. return FALSE;
  96. }
  97. if (tcPat == TEXT('?'))
  98. {
  99. // Never match '\'
  100. if (tcStr == TEXT('\\'))
  101. {
  102. return FALSE;
  103. }
  104. //Match any single character in the string and continue.
  105. iPat++;
  106. iStr++;
  107. }
  108. else if (tcPat != TEXT('*'))
  109. {
  110. //Match character
  111. if (tcPat != tcStr)
  112. {
  113. return FALSE;
  114. }
  115. iPat++;
  116. iStr++;
  117. }
  118. else
  119. {
  120. while (ptsPattern[iPat + 1] == TEXT('*'))
  121. {
  122. //Skip consecutive *s
  123. iPat++;
  124. }
  125. //If * all the way to the end, return true.
  126. if (ptsPattern[iPat + 1] == 0)
  127. return TRUE;
  128. // Lookahead one
  129. tcPat = (TCHAR)_totlower(ptsPattern[iPat + 1]);
  130. if ((tcPat == tcStr) ||
  131. (tcPat == TEXT('?')))
  132. {
  133. // Next character matches, continue with expression
  134. if (MatchString(ptsPattern + iPat + 1, ptsString + iStr, bRequireNullPatMatch))
  135. return TRUE;
  136. }
  137. // Eat another character with the '*' pattern
  138. iStr++;
  139. }
  140. }
  141. if (!ptsPattern[iPat] && !ptsString[iStr])
  142. return TRUE;
  143. // If only ?s and *s left in pattern, then call it a match
  144. if ( _tcsspnp(ptsPattern+iPat, TEXT("?*")) == NULL )
  145. return TRUE;
  146. return FALSE;
  147. }
  148. BOOL IsPatternMatchFull(const TCHAR *ptsPatternFull,
  149. const TCHAR *ptsPath,
  150. const TCHAR *ptsFilename)
  151. {
  152. TCHAR tsPatternPath[MAX_PATH + 1];
  153. TCHAR tsPatternFile[MAX_PATH + 1];
  154. TCHAR tsPatternExt[MAX_PATH + 1];
  155. DeconstructFilename(ptsPatternFull,
  156. tsPatternPath,
  157. tsPatternFile,
  158. tsPatternExt);
  159. return IsPatternMatch(tsPatternPath,
  160. tsPatternFile,
  161. tsPatternExt,
  162. ptsPath,
  163. ptsFilename);
  164. }
  165. BOOL IsPatternMatch(const TCHAR *ptsPatternDir,
  166. const TCHAR *ptsPatternFile,
  167. const TCHAR *ptsPatternExt,
  168. const TCHAR *ptsPath,
  169. const TCHAR *ptsFilename)
  170. {
  171. BOOL fRet;
  172. TCHAR tsFilePath[MAX_PATH];
  173. TCHAR tsFileName[MAX_PATH];
  174. TCHAR tsFileExt[MAX_PATH];
  175. BOOL bRequireNullMatch = FALSE;
  176. DeconstructFilename(ptsFilename,
  177. NULL,
  178. tsFileName,
  179. tsFileExt);
  180. //Special case: Directories have a ptsFilename of NULL, but shouldn't
  181. //match on *.*
  182. if ((ptsFilename == NULL) &&
  183. (ptsPatternDir[0] == 0))
  184. {
  185. //Return FALSE;
  186. fRet = FALSE;
  187. }
  188. else
  189. {
  190. if ((ptsPatternFile == NULL) && (ptsPatternExt == NULL) &&
  191. (tsFileName[0] == 0) && (tsFileExt[0] == 0))
  192. {
  193. //Directory only
  194. fRet = MatchString(ptsPatternDir,
  195. ptsPath,
  196. FALSE);
  197. }
  198. else
  199. {
  200. // If filename or extension is specified in the pattern,
  201. // match a null file piece only if pattern is null too.
  202. // i.e.: ".txt" and "*."
  203. if ( ptsPatternFile[0] != 0 || ptsPatternExt[0] != 0 )
  204. bRequireNullMatch = TRUE;
  205. fRet = (MatchString(ptsPatternDir,
  206. ptsPath,
  207. FALSE) &&
  208. MatchString(ptsPatternFile,
  209. tsFileName,
  210. bRequireNullMatch) &&
  211. MatchString(ptsPatternExt,
  212. tsFileExt,
  213. bRequireNullMatch));
  214. }
  215. }
  216. return fRet;
  217. }
  218. BOOL DeconstructFilename(const TCHAR *ptsString,
  219. TCHAR *ptsPath,
  220. TCHAR *ptsName,
  221. TCHAR *ptsExt)
  222. {
  223. const TCHAR *ptsLastSlash;
  224. const TCHAR *ptsLastDot;
  225. ptsLastSlash = (ptsString) ? _tcsrchr(ptsString, TEXT('\\')) : NULL;
  226. if (ptsLastSlash == NULL)
  227. {
  228. if (ptsPath)
  229. ptsPath[0] = 0;
  230. ptsLastSlash = ptsString;
  231. }
  232. else
  233. {
  234. if (ptsPath)
  235. {
  236. if (ptsLastSlash - ptsString + 1 > MAX_PATH)
  237. {
  238. if (DebugOutput)
  239. {
  240. Win32Printf(LogFile,
  241. "Error: ptsString too long %*s\r\n",
  242. ptsLastSlash - ptsString + 1,
  243. ptsString);
  244. }
  245. ptsPath[0] = 0;
  246. return FALSE;
  247. }
  248. _tcsncpy(ptsPath, ptsString, ptsLastSlash - ptsString + 1);
  249. ptsPath[ptsLastSlash - ptsString + 1] = 0;
  250. }
  251. ptsLastSlash++;
  252. }
  253. ptsLastDot = (ptsLastSlash) ? _tcsrchr(ptsLastSlash, TEXT('.')) : NULL;
  254. if (ptsLastDot == NULL)
  255. {
  256. if (ptsExt)
  257. ptsExt[0] = 0;
  258. if (ptsName)
  259. {
  260. if (ptsLastSlash)
  261. {
  262. if (_tcslen(ptsLastSlash) > MAX_PATH)
  263. {
  264. if (DebugOutput)
  265. {
  266. Win32Printf(LogFile, "Error: ptsLastSlash too long %s\r\n", ptsLastSlash);
  267. }
  268. ptsName[0] = 0;
  269. return FALSE;
  270. }
  271. _tcscpy(ptsName, ptsLastSlash);
  272. }
  273. else
  274. {
  275. ptsName[0] = 0;
  276. }
  277. }
  278. }
  279. else
  280. {
  281. if (ptsExt)
  282. {
  283. if (_tcslen(ptsLastDot+1) > MAX_PATH)
  284. {
  285. if (DebugOutput)
  286. {
  287. Win32Printf(LogFile, "Error: ptsLastDot too long %s\r\n", ptsLastDot+1);
  288. }
  289. ptsExt[0] = 0;
  290. return FALSE;
  291. }
  292. _tcscpy(ptsExt, ptsLastDot + 1);
  293. }
  294. if (ptsName)
  295. {
  296. if (ptsLastDot - ptsLastSlash > MAX_PATH)
  297. {
  298. if (DebugOutput)
  299. {
  300. Win32Printf(LogFile,
  301. "Error: ptsLastSlash Too Long %*s\r\n",
  302. ptsLastDot - ptsLastSlash,
  303. ptsLastSlash);
  304. }
  305. ptsName[0] = 0;
  306. return FALSE;
  307. }
  308. _tcsncpy(ptsName, ptsLastSlash, ptsLastDot - ptsLastSlash);
  309. ptsName[ptsLastDot - ptsLastSlash] = 0;
  310. }
  311. }
  312. return TRUE;
  313. }