FileDir.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. // Windows/FileDir.cpp
  2. #include "StdAfx.h"
  3. #include "FileDir.h"
  4. #include "FileName.h"
  5. #include "FileFind.h"
  6. #include "Defs.h"
  7. #ifndef _UNICODE
  8. #include "../Common/StringConvert.h"
  9. #endif
  10. #ifndef _UNICODE
  11. extern bool g_IsNT;
  12. #endif
  13. namespace NWindows {
  14. namespace NFile {
  15. #if defined(WIN_LONG_PATH) && defined(_UNICODE)
  16. #define WIN_LONG_PATH2
  17. #endif
  18. // SetCurrentDirectory doesn't support \\?\ prefix
  19. #ifdef WIN_LONG_PATH
  20. bool GetLongPathBase(LPCWSTR fileName, UString &res);
  21. bool GetLongPath(LPCWSTR fileName, UString &res);
  22. #endif
  23. namespace NDirectory {
  24. #ifndef _UNICODE
  25. static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }
  26. static UString GetUnicodePath(const CSysString &sysPath)
  27. { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); }
  28. static CSysString GetSysPath(LPCWSTR sysPath)
  29. { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); }
  30. #endif
  31. bool MyGetWindowsDirectory(CSysString &path)
  32. {
  33. UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
  34. path.ReleaseBuffer();
  35. return (needLength > 0 && needLength <= MAX_PATH);
  36. }
  37. bool MyGetSystemDirectory(CSysString &path)
  38. {
  39. UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
  40. path.ReleaseBuffer();
  41. return (needLength > 0 && needLength <= MAX_PATH);
  42. }
  43. #ifndef _UNICODE
  44. bool MyGetWindowsDirectory(UString &path)
  45. {
  46. if (g_IsNT)
  47. {
  48. UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
  49. path.ReleaseBuffer();
  50. return (needLength > 0 && needLength <= MAX_PATH);
  51. }
  52. CSysString sysPath;
  53. if (!MyGetWindowsDirectory(sysPath))
  54. return false;
  55. path = GetUnicodePath(sysPath);
  56. return true;
  57. }
  58. bool MyGetSystemDirectory(UString &path)
  59. {
  60. if (g_IsNT)
  61. {
  62. UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
  63. path.ReleaseBuffer();
  64. return (needLength > 0 && needLength <= MAX_PATH);
  65. }
  66. CSysString sysPath;
  67. if (!MyGetSystemDirectory(sysPath))
  68. return false;
  69. path = GetUnicodePath(sysPath);
  70. return true;
  71. }
  72. #endif
  73. bool SetDirTime(LPCWSTR fileName, const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime)
  74. {
  75. #ifndef _UNICODE
  76. if (!g_IsNT)
  77. {
  78. ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  79. return false;
  80. }
  81. #endif
  82. HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE,
  83. FILE_SHARE_READ | FILE_SHARE_WRITE,
  84. NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
  85. #ifdef WIN_LONG_PATH
  86. if (hDir == INVALID_HANDLE_VALUE)
  87. {
  88. UString longPath;
  89. if (GetLongPath(fileName, longPath))
  90. hDir = ::CreateFileW(longPath, GENERIC_WRITE,
  91. FILE_SHARE_READ | FILE_SHARE_WRITE,
  92. NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
  93. }
  94. #endif
  95. bool res = false;
  96. if (hDir != INVALID_HANDLE_VALUE)
  97. {
  98. res = BOOLToBool(::SetFileTime(hDir, creationTime, lastAccessTime, lastWriteTime));
  99. ::CloseHandle(hDir);
  100. }
  101. return res;
  102. }
  103. bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes)
  104. {
  105. if (::SetFileAttributes(fileName, fileAttributes))
  106. return true;
  107. #ifdef WIN_LONG_PATH2
  108. UString longPath;
  109. if (GetLongPath(fileName, longPath))
  110. return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes));
  111. #endif
  112. return false;
  113. }
  114. bool MyRemoveDirectory(LPCTSTR pathName)
  115. {
  116. if (::RemoveDirectory(pathName))
  117. return true;
  118. #ifdef WIN_LONG_PATH2
  119. UString longPath;
  120. if (GetLongPath(pathName, longPath))
  121. return BOOLToBool(::RemoveDirectoryW(longPath));
  122. #endif
  123. return false;
  124. }
  125. #ifdef WIN_LONG_PATH
  126. bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2)
  127. {
  128. if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2))
  129. return false;
  130. if (d1.IsEmpty() && d2.IsEmpty()) return false;
  131. if (d1.IsEmpty()) d1 = s1;
  132. if (d2.IsEmpty()) d2 = s2;
  133. return true;
  134. }
  135. #endif
  136. bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName)
  137. {
  138. if (::MoveFile(existFileName, newFileName))
  139. return true;
  140. #ifdef WIN_LONG_PATH2
  141. UString d1, d2;
  142. if (GetLongPaths(existFileName, newFileName, d1, d2))
  143. return BOOLToBool(::MoveFileW(d1, d2));
  144. #endif
  145. return false;
  146. }
  147. #ifndef _UNICODE
  148. bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes)
  149. {
  150. if (!g_IsNT)
  151. return MySetFileAttributes(GetSysPath(fileName), fileAttributes);
  152. if (::SetFileAttributesW(fileName, fileAttributes))
  153. return true;
  154. #ifdef WIN_LONG_PATH
  155. UString longPath;
  156. if (GetLongPath(fileName, longPath))
  157. return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes));
  158. #endif
  159. return false;
  160. }
  161. bool MyRemoveDirectory(LPCWSTR pathName)
  162. {
  163. if (!g_IsNT)
  164. return MyRemoveDirectory(GetSysPath(pathName));
  165. if (::RemoveDirectoryW(pathName))
  166. return true;
  167. #ifdef WIN_LONG_PATH
  168. UString longPath;
  169. if (GetLongPath(pathName, longPath))
  170. return BOOLToBool(::RemoveDirectoryW(longPath));
  171. #endif
  172. return false;
  173. }
  174. bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName)
  175. {
  176. if (!g_IsNT)
  177. return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName));
  178. if (::MoveFileW(existFileName, newFileName))
  179. return true;
  180. #ifdef WIN_LONG_PATH
  181. UString d1, d2;
  182. if (GetLongPaths(existFileName, newFileName, d1, d2))
  183. return BOOLToBool(::MoveFileW(d1, d2));
  184. #endif
  185. return false;
  186. }
  187. #endif
  188. bool MyCreateDirectory(LPCTSTR pathName)
  189. {
  190. if (::CreateDirectory(pathName, NULL))
  191. return true;
  192. #ifdef WIN_LONG_PATH2
  193. if (::GetLastError() != ERROR_ALREADY_EXISTS)
  194. {
  195. UString longPath;
  196. if (GetLongPath(pathName, longPath))
  197. return BOOLToBool(::CreateDirectoryW(longPath, NULL));
  198. }
  199. #endif
  200. return false;
  201. }
  202. #ifndef _UNICODE
  203. bool MyCreateDirectory(LPCWSTR pathName)
  204. {
  205. if (!g_IsNT)
  206. return MyCreateDirectory(GetSysPath(pathName));
  207. if (::CreateDirectoryW(pathName, NULL))
  208. return true;
  209. #ifdef WIN_LONG_PATH
  210. if (::GetLastError() != ERROR_ALREADY_EXISTS)
  211. {
  212. UString longPath;
  213. if (GetLongPath(pathName, longPath))
  214. return BOOLToBool(::CreateDirectoryW(longPath, NULL));
  215. }
  216. #endif
  217. return false;
  218. }
  219. #endif
  220. /*
  221. bool CreateComplexDirectory(LPCTSTR pathName)
  222. {
  223. NName::CParsedPath path;
  224. path.ParsePath(pathName);
  225. CSysString fullPath = path.Prefix;
  226. DWORD errorCode = ERROR_SUCCESS;
  227. for(int i = 0; i < path.PathParts.Size(); i++)
  228. {
  229. const CSysString &string = path.PathParts[i];
  230. if(string.IsEmpty())
  231. {
  232. if(i != path.PathParts.Size() - 1)
  233. return false;
  234. return true;
  235. }
  236. fullPath += path.PathParts[i];
  237. if (!MyCreateDirectory(fullPath))
  238. {
  239. DWORD errorCode = GetLastError();
  240. if(errorCode != ERROR_ALREADY_EXISTS)
  241. return false;
  242. }
  243. fullPath += NName::kDirDelimiter;
  244. }
  245. return true;
  246. }
  247. */
  248. bool CreateComplexDirectory(LPCTSTR _aPathName)
  249. {
  250. CSysString pathName = _aPathName;
  251. int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
  252. if (pos > 0 && pos == pathName.Length() - 1)
  253. {
  254. if (pathName.Length() == 3 && pathName[1] == ':')
  255. return true; // Disk folder;
  256. pathName.Delete(pos);
  257. }
  258. CSysString pathName2 = pathName;
  259. pos = pathName.Length();
  260. for (;;)
  261. {
  262. if(MyCreateDirectory(pathName))
  263. break;
  264. if (::GetLastError() == ERROR_ALREADY_EXISTS)
  265. {
  266. NFind::CFileInfo fileInfo;
  267. if (!NFind::FindFile(pathName, fileInfo)) // For network folders
  268. return true;
  269. if (!fileInfo.IsDirectory())
  270. return false;
  271. break;
  272. }
  273. pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
  274. if (pos < 0 || pos == 0)
  275. return false;
  276. if (pathName[pos - 1] == ':')
  277. return false;
  278. pathName = pathName.Left(pos);
  279. }
  280. pathName = pathName2;
  281. while(pos < pathName.Length())
  282. {
  283. pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1);
  284. if (pos < 0)
  285. pos = pathName.Length();
  286. if (!MyCreateDirectory(pathName.Left(pos)))
  287. return false;
  288. }
  289. return true;
  290. }
  291. #ifndef _UNICODE
  292. bool CreateComplexDirectory(LPCWSTR _aPathName)
  293. {
  294. UString pathName = _aPathName;
  295. int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR);
  296. if (pos > 0 && pos == pathName.Length() - 1)
  297. {
  298. if (pathName.Length() == 3 && pathName[1] == L':')
  299. return true; // Disk folder;
  300. pathName.Delete(pos);
  301. }
  302. UString pathName2 = pathName;
  303. pos = pathName.Length();
  304. for (;;)
  305. {
  306. if(MyCreateDirectory(pathName))
  307. break;
  308. if (::GetLastError() == ERROR_ALREADY_EXISTS)
  309. {
  310. NFind::CFileInfoW fileInfo;
  311. if (!NFind::FindFile(pathName, fileInfo)) // For network folders
  312. return true;
  313. if (!fileInfo.IsDirectory())
  314. return false;
  315. break;
  316. }
  317. pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR);
  318. if (pos < 0 || pos == 0)
  319. return false;
  320. if (pathName[pos - 1] == L':')
  321. return false;
  322. pathName = pathName.Left(pos);
  323. }
  324. pathName = pathName2;
  325. while(pos < pathName.Length())
  326. {
  327. pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1);
  328. if (pos < 0)
  329. pos = pathName.Length();
  330. if (!MyCreateDirectory(pathName.Left(pos)))
  331. return false;
  332. }
  333. return true;
  334. }
  335. #endif
  336. bool DeleteFileAlways(LPCTSTR name)
  337. {
  338. if (!MySetFileAttributes(name, 0))
  339. return false;
  340. if (::DeleteFile(name))
  341. return true;
  342. #ifdef WIN_LONG_PATH2
  343. UString longPath;
  344. if (GetLongPath(name, longPath))
  345. return BOOLToBool(::DeleteFileW(longPath));
  346. #endif
  347. return false;
  348. }
  349. #ifndef _UNICODE
  350. bool DeleteFileAlways(LPCWSTR name)
  351. {
  352. if (!g_IsNT)
  353. return DeleteFileAlways(GetSysPath(name));
  354. if (!MySetFileAttributes(name, 0))
  355. return false;
  356. if (::DeleteFileW(name))
  357. return true;
  358. #ifdef WIN_LONG_PATH
  359. UString longPath;
  360. if (GetLongPath(name, longPath))
  361. return BOOLToBool(::DeleteFileW(longPath));
  362. #endif
  363. return false;
  364. }
  365. #endif
  366. static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo)
  367. {
  368. if(fileInfo.IsDirectory())
  369. return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);
  370. return DeleteFileAlways(pathPrefix + fileInfo.Name);
  371. }
  372. bool RemoveDirectoryWithSubItems(const CSysString &path)
  373. {
  374. NFind::CFileInfo fileInfo;
  375. CSysString pathPrefix = path + NName::kDirDelimiter;
  376. {
  377. NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard));
  378. while(enumerator.Next(fileInfo))
  379. if (!RemoveDirectorySubItems2(pathPrefix, fileInfo))
  380. return false;
  381. }
  382. if (!MySetFileAttributes(path, 0))
  383. return false;
  384. return MyRemoveDirectory(path);
  385. }
  386. #ifndef _UNICODE
  387. static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo)
  388. {
  389. if(fileInfo.IsDirectory())
  390. return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);
  391. return DeleteFileAlways(pathPrefix + fileInfo.Name);
  392. }
  393. bool RemoveDirectoryWithSubItems(const UString &path)
  394. {
  395. NFind::CFileInfoW fileInfo;
  396. UString pathPrefix = path + UString(NName::kDirDelimiter);
  397. {
  398. NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard));
  399. while(enumerator.Next(fileInfo))
  400. if (!RemoveDirectorySubItems2(pathPrefix, fileInfo))
  401. return false;
  402. }
  403. if (!MySetFileAttributes(path, 0))
  404. return false;
  405. return MyRemoveDirectory(path);
  406. }
  407. #endif
  408. #ifndef _WIN32_WCE
  409. bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath)
  410. {
  411. DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1);
  412. shortPath.ReleaseBuffer();
  413. return (needLength > 0 && needLength < MAX_PATH);
  414. }
  415. bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex)
  416. {
  417. resultPath.Empty();
  418. LPTSTR fileNamePointer = 0;
  419. LPTSTR buffer = resultPath.GetBuffer(MAX_PATH);
  420. DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer);
  421. resultPath.ReleaseBuffer();
  422. if (needLength == 0)
  423. return false;
  424. if (needLength >= MAX_PATH)
  425. {
  426. #ifdef WIN_LONG_PATH2
  427. needLength++;
  428. buffer = resultPath.GetBuffer(needLength + 1);
  429. DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer);
  430. resultPath.ReleaseBuffer();
  431. if (needLength2 == 0 || needLength2 > needLength)
  432. #endif
  433. return false;
  434. }
  435. if (fileNamePointer == 0)
  436. fileNamePartStartIndex = lstrlen(fileName);
  437. else
  438. fileNamePartStartIndex = (int)(fileNamePointer - buffer);
  439. return true;
  440. }
  441. #ifndef _UNICODE
  442. bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex)
  443. {
  444. resultPath.Empty();
  445. if (g_IsNT)
  446. {
  447. LPWSTR fileNamePointer = 0;
  448. LPWSTR buffer = resultPath.GetBuffer(MAX_PATH);
  449. DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer);
  450. resultPath.ReleaseBuffer();
  451. if (needLength == 0)
  452. return false;
  453. if (needLength >= MAX_PATH)
  454. {
  455. #ifdef WIN_LONG_PATH
  456. needLength++;
  457. buffer = resultPath.GetBuffer(needLength + 1);
  458. DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer);
  459. resultPath.ReleaseBuffer();
  460. if (needLength2 == 0 || needLength2 > needLength)
  461. #endif
  462. return false;
  463. }
  464. if (fileNamePointer == 0)
  465. fileNamePartStartIndex = MyStringLen(fileName);
  466. else
  467. fileNamePartStartIndex = (int)(fileNamePointer - buffer);
  468. }
  469. else
  470. {
  471. CSysString sysPath;
  472. if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex))
  473. return false;
  474. UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex));
  475. UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex));
  476. fileNamePartStartIndex = resultPath1.Length();
  477. resultPath = resultPath1 + resultPath2;
  478. }
  479. return true;
  480. }
  481. #endif
  482. bool MyGetFullPathName(LPCTSTR fileName, CSysString &path)
  483. {
  484. int index;
  485. return MyGetFullPathName(fileName, path, index);
  486. }
  487. #ifndef _UNICODE
  488. bool MyGetFullPathName(LPCWSTR fileName, UString &path)
  489. {
  490. int index;
  491. return MyGetFullPathName(fileName, path, index);
  492. }
  493. #endif
  494. bool GetOnlyName(LPCTSTR fileName, CSysString &resultName)
  495. {
  496. int index;
  497. if (!MyGetFullPathName(fileName, resultName, index))
  498. return false;
  499. resultName = resultName.Mid(index);
  500. return true;
  501. }
  502. #ifndef _UNICODE
  503. bool GetOnlyName(LPCWSTR fileName, UString &resultName)
  504. {
  505. int index;
  506. if (!MyGetFullPathName(fileName, resultName, index))
  507. return false;
  508. resultName = resultName.Mid(index);
  509. return true;
  510. }
  511. #endif
  512. bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName)
  513. {
  514. int index;
  515. if (!MyGetFullPathName(fileName, resultName, index))
  516. return false;
  517. resultName = resultName.Left(index);
  518. return true;
  519. }
  520. #ifndef _UNICODE
  521. bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName)
  522. {
  523. int index;
  524. if (!MyGetFullPathName(fileName, resultName, index))
  525. return false;
  526. resultName = resultName.Left(index);
  527. return true;
  528. }
  529. #endif
  530. bool MyGetCurrentDirectory(CSysString &path)
  531. {
  532. DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
  533. path.ReleaseBuffer();
  534. return (needLength > 0 && needLength <= MAX_PATH);
  535. }
  536. #ifndef _UNICODE
  537. bool MySetCurrentDirectory(LPCWSTR path)
  538. {
  539. if (g_IsNT)
  540. return BOOLToBool(::SetCurrentDirectoryW(path));
  541. return MySetCurrentDirectory(GetSysPath(path));
  542. }
  543. bool MyGetCurrentDirectory(UString &path)
  544. {
  545. if (g_IsNT)
  546. {
  547. DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
  548. path.ReleaseBuffer();
  549. return (needLength > 0 && needLength <= MAX_PATH);
  550. }
  551. CSysString sysPath;
  552. if (!MyGetCurrentDirectory(sysPath))
  553. return false;
  554. path = GetUnicodePath(sysPath);
  555. return true;
  556. }
  557. #endif
  558. #endif
  559. bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension,
  560. CSysString &resultPath, UINT32 &filePart)
  561. {
  562. LPTSTR filePartPointer;
  563. DWORD value = ::SearchPath(path, fileName, extension,
  564. MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer);
  565. filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath);
  566. resultPath.ReleaseBuffer();
  567. return (value > 0 && value <= MAX_PATH);
  568. }
  569. #ifndef _UNICODE
  570. bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension,
  571. UString &resultPath, UINT32 &filePart)
  572. {
  573. if (g_IsNT)
  574. {
  575. LPWSTR filePartPointer = 0;
  576. DWORD value = ::SearchPathW(path, fileName, extension,
  577. MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer);
  578. filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath);
  579. resultPath.ReleaseBuffer();
  580. return (value > 0 && value <= MAX_PATH);
  581. }
  582. CSysString sysPath;
  583. if (!MySearchPath(
  584. path != 0 ? (LPCTSTR)GetSysPath(path): 0,
  585. fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0,
  586. extension != 0 ? (LPCTSTR)GetSysPath(extension): 0,
  587. sysPath, filePart))
  588. return false;
  589. UString resultPath1 = GetUnicodePath(sysPath.Left(filePart));
  590. UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart));
  591. filePart = resultPath1.Length();
  592. resultPath = resultPath1 + resultPath2;
  593. return true;
  594. }
  595. #endif
  596. bool MyGetTempPath(CSysString &path)
  597. {
  598. DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
  599. path.ReleaseBuffer();
  600. return (needLength > 0 && needLength <= MAX_PATH);
  601. }
  602. #ifndef _UNICODE
  603. bool MyGetTempPath(UString &path)
  604. {
  605. path.Empty();
  606. if (g_IsNT)
  607. {
  608. DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1));
  609. path.ReleaseBuffer();
  610. return (needLength > 0 && needLength <= MAX_PATH);
  611. }
  612. CSysString sysPath;
  613. if (!MyGetTempPath(sysPath))
  614. return false;
  615. path = GetUnicodePath(sysPath);
  616. return true;
  617. }
  618. #endif
  619. UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path)
  620. {
  621. UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1));
  622. path.ReleaseBuffer();
  623. return number;
  624. }
  625. #ifndef _UNICODE
  626. UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path)
  627. {
  628. if (g_IsNT)
  629. {
  630. UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH));
  631. path.ReleaseBuffer();
  632. return number;
  633. }
  634. CSysString sysPath;
  635. UINT number = MyGetTempFileName(
  636. dirPath ? (LPCTSTR)GetSysPath(dirPath): 0,
  637. prefix ? (LPCTSTR)GetSysPath(prefix): 0,
  638. sysPath);
  639. path = GetUnicodePath(sysPath);
  640. return number;
  641. }
  642. #endif
  643. UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath)
  644. {
  645. Remove();
  646. UINT number = MyGetTempFileName(dirPath, prefix, resultPath);
  647. if(number != 0)
  648. {
  649. _fileName = resultPath;
  650. _mustBeDeleted = true;
  651. }
  652. return number;
  653. }
  654. bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath)
  655. {
  656. CSysString tempPath;
  657. if (!MyGetTempPath(tempPath))
  658. return false;
  659. if (Create(tempPath, prefix, resultPath) != 0)
  660. return true;
  661. if (!MyGetWindowsDirectory(tempPath))
  662. return false;
  663. return (Create(tempPath, prefix, resultPath) != 0);
  664. }
  665. bool CTempFile::Remove()
  666. {
  667. if (!_mustBeDeleted)
  668. return true;
  669. _mustBeDeleted = !DeleteFileAlways(_fileName);
  670. return !_mustBeDeleted;
  671. }
  672. #ifndef _UNICODE
  673. UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath)
  674. {
  675. Remove();
  676. UINT number = MyGetTempFileName(dirPath, prefix, resultPath);
  677. if(number != 0)
  678. {
  679. _fileName = resultPath;
  680. _mustBeDeleted = true;
  681. }
  682. return number;
  683. }
  684. bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath)
  685. {
  686. UString tempPath;
  687. if (!MyGetTempPath(tempPath))
  688. return false;
  689. if (Create(tempPath, prefix, resultPath) != 0)
  690. return true;
  691. if (!MyGetWindowsDirectory(tempPath))
  692. return false;
  693. return (Create(tempPath, prefix, resultPath) != 0);
  694. }
  695. bool CTempFileW::Remove()
  696. {
  697. if (!_mustBeDeleted)
  698. return true;
  699. _mustBeDeleted = !DeleteFileAlways(_fileName);
  700. return !_mustBeDeleted;
  701. }
  702. #endif
  703. bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName)
  704. {
  705. /*
  706. CSysString prefix = tempPath + prefixChars;
  707. CRandom random;
  708. random.Init();
  709. */
  710. for (;;)
  711. {
  712. CTempFile tempFile;
  713. if (!tempFile.Create(prefix, dirName))
  714. return false;
  715. if (!::DeleteFile(dirName))
  716. return false;
  717. /*
  718. UINT32 randomNumber = random.Generate();
  719. TCHAR randomNumberString[32];
  720. _stprintf(randomNumberString, _T("%04X"), randomNumber);
  721. dirName = prefix + randomNumberString;
  722. */
  723. if(NFind::DoesFileExist(dirName))
  724. continue;
  725. if (MyCreateDirectory(dirName))
  726. return true;
  727. if (::GetLastError() != ERROR_ALREADY_EXISTS)
  728. return false;
  729. }
  730. }
  731. bool CTempDirectory::Create(LPCTSTR prefix)
  732. {
  733. Remove();
  734. return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir));
  735. }
  736. #ifndef _UNICODE
  737. bool CreateTempDirectory(LPCWSTR prefix, UString &dirName)
  738. {
  739. /*
  740. CSysString prefix = tempPath + prefixChars;
  741. CRandom random;
  742. random.Init();
  743. */
  744. for (;;)
  745. {
  746. CTempFileW tempFile;
  747. if (!tempFile.Create(prefix, dirName))
  748. return false;
  749. if (!DeleteFileAlways(dirName))
  750. return false;
  751. /*
  752. UINT32 randomNumber = random.Generate();
  753. TCHAR randomNumberString[32];
  754. _stprintf(randomNumberString, _T("%04X"), randomNumber);
  755. dirName = prefix + randomNumberString;
  756. */
  757. if(NFind::DoesFileExist(dirName))
  758. continue;
  759. if (MyCreateDirectory(dirName))
  760. return true;
  761. if (::GetLastError() != ERROR_ALREADY_EXISTS)
  762. return false;
  763. }
  764. }
  765. bool CTempDirectoryW::Create(LPCWSTR prefix)
  766. {
  767. Remove();
  768. return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir));
  769. }
  770. #endif
  771. }}}