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