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.

426 lines
11 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: dir.cpp
  8. //
  9. // Contents: Directory functions
  10. //
  11. // Functions: I_RecursiveCreateDirectory
  12. //
  13. // History: 06-Aug-99 reidk created
  14. //--------------------------------------------------------------------------
  15. #include "global.hxx"
  16. #include "crypthlp.h"
  17. #include "unicode.h"
  18. #include <dbgdef.h>
  19. BOOL I_RecursiveCreateDirectory(
  20. IN LPCWSTR pwszDir,
  21. IN LPSECURITY_ATTRIBUTES lpSecurityAttributes
  22. )
  23. {
  24. BOOL fResult;
  25. DWORD dwAttr;
  26. DWORD dwErr;
  27. LPCWSTR pwsz;
  28. DWORD cch;
  29. WCHAR wch;
  30. LPWSTR pwszParent = NULL;
  31. dwAttr = GetFileAttributesU(pwszDir);
  32. if (0xFFFFFFFF != dwAttr) {
  33. if (FILE_ATTRIBUTE_DIRECTORY & dwAttr)
  34. return TRUE;
  35. goto InvalidDirectoryAttr;
  36. }
  37. dwErr = GetLastError();
  38. if (!(ERROR_PATH_NOT_FOUND == dwErr || ERROR_FILE_NOT_FOUND == dwErr))
  39. goto GetFileAttrError;
  40. if (CreateDirectoryU(
  41. pwszDir,
  42. lpSecurityAttributes
  43. )) {
  44. SetFileAttributesU(pwszDir, FILE_ATTRIBUTE_SYSTEM);
  45. return TRUE;
  46. }
  47. dwErr = GetLastError();
  48. if (!(ERROR_PATH_NOT_FOUND == dwErr || ERROR_FILE_NOT_FOUND == dwErr))
  49. goto CreateDirectoryError;
  50. // Peal off the last path name component
  51. cch = wcslen(pwszDir);
  52. pwsz = pwszDir + cch;
  53. while (L'\\' != *pwsz) {
  54. if (pwsz == pwszDir)
  55. // Path didn't have a \.
  56. goto BadDirectoryPath;
  57. pwsz--;
  58. }
  59. cch = (DWORD)(pwsz - pwszDir);
  60. if (0 == cch)
  61. // Detected leading \Path
  62. goto BadDirectoryPath;
  63. // Check for leading \\ or x:\.
  64. wch = *(pwsz - 1);
  65. if ((1 == cch && L'\\' == wch) || (2 == cch && L':' == wch))
  66. goto BadDirectoryPath;
  67. if (NULL == (pwszParent = (LPWSTR) PkiNonzeroAlloc((cch + 1) *
  68. sizeof(WCHAR))))
  69. goto OutOfMemory;
  70. memcpy(pwszParent, pwszDir, cch * sizeof(WCHAR));
  71. pwszParent[cch] = L'\0';
  72. if (!I_RecursiveCreateDirectory(pwszParent, lpSecurityAttributes))
  73. goto ErrorReturn;
  74. if (!CreateDirectoryU(
  75. pwszDir,
  76. lpSecurityAttributes
  77. )) {
  78. dwErr = GetLastError();
  79. goto CreateDirectory2Error;
  80. }
  81. SetFileAttributesU(pwszDir, FILE_ATTRIBUTE_SYSTEM);
  82. fResult = TRUE;
  83. CommonReturn:
  84. PkiFree(pwszParent);
  85. return fResult;
  86. ErrorReturn:
  87. fResult = FALSE;
  88. goto CommonReturn;
  89. SET_ERROR(InvalidDirectoryAttr, ERROR_FILE_INVALID)
  90. SET_ERROR_VAR(GetFileAttrError, dwErr)
  91. SET_ERROR_VAR(CreateDirectoryError, dwErr)
  92. SET_ERROR(BadDirectoryPath, ERROR_BAD_PATHNAME)
  93. TRACE_ERROR(OutOfMemory)
  94. SET_ERROR_VAR(CreateDirectory2Error, dwErr)
  95. }
  96. BOOL
  97. I_RecursiveDeleteDirectory(
  98. IN LPCWSTR pwszDelete
  99. )
  100. {
  101. BOOL fResult = TRUE;
  102. HANDLE hFindHandle = INVALID_HANDLE_VALUE;
  103. LPWSTR pwszSearch = NULL;
  104. WIN32_FIND_DATAW FindData;
  105. LPWSTR pwszDirOrFileDelete = NULL;
  106. DWORD dwErr = 0;
  107. //
  108. // Create search string
  109. //
  110. pwszSearch = (LPWSTR) malloc((wcslen(pwszDelete) + 3) * sizeof(WCHAR));// length + '\' + '*' + '/0'
  111. if (pwszSearch == NULL)
  112. {
  113. goto ErrorMemory;
  114. }
  115. wcscpy(pwszSearch, pwszDelete);
  116. if ((pwszSearch[wcslen(pwszSearch) - 1] != L'\\'))
  117. {
  118. wcscat(pwszSearch, L"\\");
  119. }
  120. wcscat(pwszSearch, L"*");
  121. //
  122. // Loop for each item (file or dir) in pwszDelete, and delete/remove it
  123. //
  124. hFindHandle = FindFirstFileU(pwszSearch, &FindData);
  125. if (hFindHandle == INVALID_HANDLE_VALUE)
  126. {
  127. // nothing found, get out
  128. if (GetLastError() == ERROR_NO_MORE_FILES)
  129. {
  130. SetFileAttributesU(pwszDelete, FILE_ATTRIBUTE_NORMAL);
  131. RemoveDirectoryW(pwszDelete);
  132. goto CommonReturn;
  133. }
  134. else
  135. {
  136. goto ErrorFindFirstFile;
  137. }
  138. }
  139. while (1)
  140. {
  141. if ((wcscmp(FindData.cFileName, L".") != 0) &&
  142. (wcscmp(FindData.cFileName, L"..") != 0))
  143. {
  144. //
  145. // name of dir or file to delete
  146. //
  147. pwszDirOrFileDelete = (LPWSTR) malloc((wcslen(pwszDelete) +
  148. wcslen(FindData.cFileName) +
  149. 2) * sizeof(WCHAR));
  150. if (pwszDirOrFileDelete == NULL)
  151. {
  152. goto ErrorMemory;
  153. }
  154. wcscpy(pwszDirOrFileDelete, pwszDelete);
  155. if ((pwszDirOrFileDelete[wcslen(pwszDirOrFileDelete) - 1] != L'\\'))
  156. {
  157. wcscat(pwszDirOrFileDelete, L"\\");
  158. }
  159. wcscat(pwszDirOrFileDelete, FindData.cFileName);
  160. //
  161. // check to see if this is a dir or a file
  162. //
  163. if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  164. {
  165. //
  166. // Recursive delete
  167. //
  168. if (!I_RecursiveDeleteDirectory(pwszDirOrFileDelete))
  169. {
  170. goto ErrorReturn;
  171. }
  172. }
  173. else
  174. {
  175. SetFileAttributesU(pwszDirOrFileDelete, FILE_ATTRIBUTE_NORMAL);
  176. if (!DeleteFileU(pwszDirOrFileDelete))
  177. {
  178. //goto ErrorReturn;
  179. }
  180. }
  181. free(pwszDirOrFileDelete);
  182. pwszDirOrFileDelete = NULL;
  183. }
  184. if (!FindNextFileU(hFindHandle, &FindData))
  185. {
  186. if (GetLastError() == ERROR_NO_MORE_FILES)
  187. {
  188. break;
  189. }
  190. else
  191. {
  192. goto ErrorFindNextFile;
  193. }
  194. }
  195. }
  196. SetFileAttributesU(pwszDelete, FILE_ATTRIBUTE_NORMAL);
  197. RemoveDirectoryW(pwszDelete);
  198. CommonReturn:
  199. dwErr = GetLastError();
  200. if (pwszSearch != NULL)
  201. {
  202. free(pwszSearch);
  203. }
  204. if (pwszDirOrFileDelete != NULL)
  205. {
  206. free(pwszDirOrFileDelete);
  207. }
  208. if (hFindHandle != INVALID_HANDLE_VALUE)
  209. {
  210. FindClose(hFindHandle);
  211. }
  212. SetLastError(dwErr);
  213. return (fResult);
  214. ErrorReturn:
  215. fResult = FALSE;
  216. goto CommonReturn;
  217. SET_ERROR_EX(DBG_SS_TRUST, ErrorMemory, ERROR_NOT_ENOUGH_MEMORY)
  218. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindFirstFile)
  219. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindNextFile)
  220. }
  221. BOOL
  222. I_RecursiveCopyDirectory(
  223. IN LPCWSTR pwszDirFrom,
  224. IN LPCWSTR pwszDirTo
  225. )
  226. {
  227. BOOL fResult = TRUE;
  228. HANDLE hFindHandle = INVALID_HANDLE_VALUE;
  229. LPWSTR pwszSearch = NULL;
  230. WIN32_FIND_DATAW FindData;
  231. LPWSTR pwszDirOrFileFrom = NULL;
  232. LPWSTR pwszDirOrFileTo = NULL;
  233. DWORD dwErr = 0;
  234. //
  235. // Create search string
  236. //
  237. pwszSearch = (LPWSTR) malloc((wcslen(pwszDirFrom) + 3) * sizeof(WCHAR)); // length + '\' + '*' + '/0'
  238. if (pwszSearch == NULL)
  239. {
  240. goto ErrorMemory;
  241. }
  242. wcscpy(pwszSearch, pwszDirFrom);
  243. if ((pwszSearch[wcslen(pwszSearch) - 1] != L'\\'))
  244. {
  245. wcscat(pwszSearch, L"\\");
  246. }
  247. wcscat(pwszSearch, L"*");
  248. //
  249. // Loop for each item (file or dir) in pwszDirFrom, and
  250. // copy it to pwszDirTo
  251. //
  252. hFindHandle = FindFirstFileU(pwszSearch, &FindData);
  253. if (hFindHandle == INVALID_HANDLE_VALUE)
  254. {
  255. // nothing found, get out
  256. if (GetLastError() == ERROR_NO_MORE_FILES)
  257. {
  258. goto CommonReturn;
  259. }
  260. else
  261. {
  262. goto ErrorFindFirstFile;
  263. }
  264. }
  265. while (1)
  266. {
  267. if ((wcscmp(FindData.cFileName, L".") != 0) &&
  268. (wcscmp(FindData.cFileName, L"..") != 0))
  269. {
  270. //
  271. // name of dir or file to copy from
  272. //
  273. pwszDirOrFileFrom = (LPWSTR) malloc((wcslen(pwszDirFrom) + wcslen(FindData.cFileName) + 2) * sizeof(WCHAR));
  274. if (pwszDirOrFileFrom == NULL)
  275. {
  276. goto ErrorMemory;
  277. }
  278. wcscpy(pwszDirOrFileFrom, pwszDirFrom);
  279. if ((pwszDirOrFileFrom[wcslen(pwszDirOrFileFrom) - 1] != L'\\'))
  280. {
  281. wcscat(pwszDirOrFileFrom, L"\\");
  282. }
  283. wcscat(pwszDirOrFileFrom, FindData.cFileName);
  284. //
  285. // name of dir or file to copy to
  286. //
  287. pwszDirOrFileTo = (LPWSTR) malloc((wcslen(pwszDirTo) + wcslen(FindData.cFileName) + 2) * sizeof(WCHAR));
  288. if (pwszDirOrFileTo == NULL)
  289. {
  290. goto ErrorMemory;
  291. }
  292. wcscpy(pwszDirOrFileTo, pwszDirTo);
  293. if ((pwszDirOrFileTo[wcslen(pwszDirOrFileTo) - 1] != L'\\'))
  294. {
  295. wcscat(pwszDirOrFileTo, L"\\");
  296. }
  297. wcscat(pwszDirOrFileTo, FindData.cFileName);
  298. //
  299. // check to see if this is a dir or a file
  300. //
  301. if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  302. {
  303. //
  304. // Create new dir then recursive copy
  305. //
  306. if (!I_RecursiveCreateDirectory(pwszDirOrFileTo, NULL))
  307. {
  308. goto ErrorReturn;
  309. }
  310. if (!I_RecursiveCopyDirectory(pwszDirOrFileFrom, pwszDirOrFileTo))
  311. {
  312. goto ErrorReturn;
  313. }
  314. }
  315. else
  316. {
  317. if (!CopyFileU(pwszDirOrFileFrom, pwszDirOrFileTo, TRUE))
  318. {
  319. goto ErrorCopyFile;
  320. }
  321. }
  322. free(pwszDirOrFileFrom);
  323. pwszDirOrFileFrom = NULL;
  324. free(pwszDirOrFileTo);
  325. pwszDirOrFileTo = NULL;
  326. }
  327. if (!FindNextFileU(hFindHandle, &FindData))
  328. {
  329. if (GetLastError() == ERROR_NO_MORE_FILES)
  330. {
  331. goto CommonReturn;
  332. }
  333. else
  334. {
  335. goto ErrorFindNextFile;
  336. }
  337. }
  338. }
  339. CommonReturn:
  340. dwErr = GetLastError();
  341. if (pwszSearch != NULL)
  342. {
  343. free(pwszSearch);
  344. }
  345. if (pwszDirOrFileFrom != NULL)
  346. {
  347. free(pwszDirOrFileFrom);
  348. }
  349. if (pwszDirOrFileTo != NULL)
  350. {
  351. free(pwszDirOrFileTo);
  352. }
  353. if (hFindHandle != INVALID_HANDLE_VALUE)
  354. {
  355. FindClose(hFindHandle);
  356. }
  357. SetLastError(dwErr);
  358. return (fResult);
  359. ErrorReturn:
  360. fResult = FALSE;
  361. goto CommonReturn;
  362. SET_ERROR(ErrorMemory, ERROR_NOT_ENOUGH_MEMORY)
  363. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindFirstFile)
  364. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorCopyFile)
  365. TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindNextFile)
  366. }