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