• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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