3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/file/dir.c
6 * PURPOSE: Directory functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
13 * NOTES: Changed to using ZwCreateFile
16 /* INCLUDES ******************************************************************/
21 #include "../include/debug.h"
23 UNICODE_STRING DllDirectory
= {0, 0, NULL
};
25 /* FUNCTIONS *****************************************************************/
34 LPSECURITY_ATTRIBUTES lpSecurityAttributes
39 if (!(PathNameW
= FilenameA2W(lpPathName
, FALSE
)))
42 return CreateDirectoryW (PathNameW
,
43 lpSecurityAttributes
);
53 LPCSTR lpTemplateDirectory
,
54 LPCSTR lpNewDirectory
,
55 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
57 PWCHAR TemplateDirectoryW
;
61 if (!(TemplateDirectoryW
= FilenameA2W(lpTemplateDirectory
, TRUE
)))
64 if (!(NewDirectoryW
= FilenameA2W(lpNewDirectory
, FALSE
)))
66 RtlFreeHeap (RtlGetProcessHeap (),
72 ret
= CreateDirectoryExW (TemplateDirectoryW
,
74 lpSecurityAttributes
);
76 RtlFreeHeap (RtlGetProcessHeap (),
91 LPSECURITY_ATTRIBUTES lpSecurityAttributes
94 OBJECT_ATTRIBUTES ObjectAttributes
;
95 IO_STATUS_BLOCK IoStatusBlock
;
96 UNICODE_STRING NtPathU
;
97 HANDLE DirectoryHandle
;
100 DPRINT ("lpPathName %S lpSecurityAttributes %p\n",
101 lpPathName
, lpSecurityAttributes
);
103 if (!RtlDosPathNameToNtPathName_U (lpPathName
,
108 SetLastError(ERROR_PATH_NOT_FOUND
);
112 InitializeObjectAttributes(&ObjectAttributes
,
114 OBJ_CASE_INSENSITIVE
,
116 (lpSecurityAttributes
? lpSecurityAttributes
->lpSecurityDescriptor
: NULL
));
118 Status
= NtCreateFile (&DirectoryHandle
,
119 FILE_LIST_DIRECTORY
| SYNCHRONIZE
|
120 FILE_OPEN_FOR_BACKUP_INTENT
,
124 FILE_ATTRIBUTE_NORMAL
,
125 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
127 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
131 RtlFreeHeap (RtlGetProcessHeap (),
135 if (!NT_SUCCESS(Status
))
137 SetLastErrorByStatus(Status
);
141 NtClose (DirectoryHandle
);
153 LPCWSTR lpTemplateDirectory
,
154 LPCWSTR lpNewDirectory
,
155 LPSECURITY_ATTRIBUTES lpSecurityAttributes
158 OBJECT_ATTRIBUTES ObjectAttributes
;
159 IO_STATUS_BLOCK IoStatusBlock
;
160 UNICODE_STRING NtPathU
, NtTemplatePathU
;
161 HANDLE DirectoryHandle
= NULL
;
162 HANDLE TemplateHandle
= NULL
;
163 FILE_EA_INFORMATION EaInformation
;
164 FILE_BASIC_INFORMATION FileBasicInfo
;
166 ULONG OpenOptions
, CreateOptions
;
167 ACCESS_MASK DesiredAccess
;
168 BOOLEAN ReparsePoint
= FALSE
;
169 PVOID EaBuffer
= NULL
;
172 OpenOptions
= FILE_DIRECTORY_FILE
| FILE_OPEN_REPARSE_POINT
|
173 FILE_OPEN_FOR_BACKUP_INTENT
;
174 CreateOptions
= FILE_DIRECTORY_FILE
| FILE_OPEN_FOR_BACKUP_INTENT
;
175 DesiredAccess
= FILE_LIST_DIRECTORY
| SYNCHRONIZE
| FILE_WRITE_ATTRIBUTES
|
176 FILE_READ_ATTRIBUTES
;
178 DPRINT ("lpTemplateDirectory %ws lpNewDirectory %ws lpSecurityAttributes %p\n",
179 lpTemplateDirectory
, lpNewDirectory
, lpSecurityAttributes
);
182 * Translate the template directory path
185 if (!RtlDosPathNameToNtPathName_U (lpTemplateDirectory
,
190 SetLastError(ERROR_PATH_NOT_FOUND
);
194 InitializeObjectAttributes(&ObjectAttributes
,
196 OBJ_CASE_INSENSITIVE
,
198 (lpSecurityAttributes
? lpSecurityAttributes
->lpSecurityDescriptor
: NULL
));
200 InitializeObjectAttributes(&ObjectAttributes
,
202 OBJ_CASE_INSENSITIVE
,
207 * Open the template directory
211 Status
= NtOpenFile (&TemplateHandle
,
212 FILE_LIST_DIRECTORY
| FILE_READ_ATTRIBUTES
| FILE_READ_EA
,
215 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
217 if (!NT_SUCCESS(Status
))
219 if (Status
== STATUS_INVALID_PARAMETER
&&
220 (OpenOptions
& FILE_OPEN_REPARSE_POINT
))
222 /* Some FSs (FAT) don't support reparse points, try opening
223 the directory without FILE_OPEN_REPARSE_POINT */
224 OpenOptions
&= ~FILE_OPEN_REPARSE_POINT
;
226 DPRINT("Reparse points not supported, try with less options\n");
229 goto OpenTemplateDir
;
233 DPRINT1("Failed to open the template directory: 0x%x\n", Status
);
234 goto CleanupNoNtPath
;
239 * Translate the new directory path and check if they're the same
242 if (!RtlDosPathNameToNtPathName_U (lpNewDirectory
,
247 Status
= STATUS_OBJECT_PATH_NOT_FOUND
;
248 goto CleanupNoNtPath
;
251 if (RtlEqualUnicodeString(&NtPathU
,
255 DPRINT1("Both directory paths are the same!\n");
256 Status
= STATUS_OBJECT_NAME_INVALID
;
261 * Query the basic file attributes from the template directory
264 /* Make sure FILE_ATTRIBUTE_NORMAL is used in case the information
265 isn't set by the FS */
266 FileBasicInfo
.FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
267 Status
= NtQueryInformationFile(TemplateHandle
,
270 sizeof(FILE_BASIC_INFORMATION
),
271 FileBasicInformation
);
272 if (!NT_SUCCESS(Status
))
274 DPRINT1("Failed to query the basic directory attributes\n");
278 /* clear the reparse point attribute if present. We're going to set the
279 reparse point later which will cause the attribute to be set */
280 if (FileBasicInfo
.FileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
)
282 FileBasicInfo
.FileAttributes
&= ~FILE_ATTRIBUTE_REPARSE_POINT
;
284 /* writing the extended attributes requires the FILE_WRITE_DATA
286 DesiredAccess
|= FILE_WRITE_DATA
;
288 CreateOptions
|= FILE_OPEN_REPARSE_POINT
;
293 * Read the Extended Attributes if present
298 Status
= NtQueryInformationFile(TemplateHandle
,
301 sizeof(FILE_EA_INFORMATION
),
303 if (NT_SUCCESS(Status
) && (EaInformation
.EaSize
!= 0))
305 EaBuffer
= RtlAllocateHeap(RtlGetProcessHeap(),
307 EaInformation
.EaSize
);
308 if (EaBuffer
== NULL
)
310 Status
= STATUS_INSUFFICIENT_RESOURCES
;
314 Status
= NtQueryEaFile(TemplateHandle
,
317 EaInformation
.EaSize
,
324 if (NT_SUCCESS(Status
))
326 /* we successfully read the extended attributes */
327 EaLength
= EaInformation
.EaSize
;
332 RtlFreeHeap(RtlGetProcessHeap(),
337 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
339 /* unless we just allocated not enough memory, break the loop
340 and just continue without copying extended attributes */
347 /* failure or no extended attributes present, break the loop */
352 if (!NT_SUCCESS(Status
))
354 DPRINT1("Querying the EA data failed: 0x%x\n", Status
);
359 * Create the new directory
361 Status
= NtCreateFile (&DirectoryHandle
,
366 FileBasicInfo
.FileAttributes
,
367 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
372 if (!NT_SUCCESS(Status
))
375 (Status
== STATUS_INVALID_PARAMETER
|| Status
== STATUS_ACCESS_DENIED
))
377 /* The FS doesn't seem to support reparse points... */
378 DPRINT1("Cannot copy the hardlink, destination doesn\'t support reparse points!\n");
387 * Copy the reparse point
390 PREPARSE_GUID_DATA_BUFFER ReparseDataBuffer
=
391 (PREPARSE_GUID_DATA_BUFFER
)RtlAllocateHeap(RtlGetProcessHeap(),
393 MAXIMUM_REPARSE_DATA_BUFFER_SIZE
);
395 if (ReparseDataBuffer
== NULL
)
397 Status
= STATUS_INSUFFICIENT_RESOURCES
;
401 /* query the size of the reparse data buffer structure */
402 Status
= NtFsControlFile(TemplateHandle
,
407 FSCTL_GET_REPARSE_POINT
,
411 MAXIMUM_REPARSE_DATA_BUFFER_SIZE
);
412 if (NT_SUCCESS(Status
))
414 /* write the reparse point */
415 Status
= NtFsControlFile(DirectoryHandle
,
420 FSCTL_SET_REPARSE_POINT
,
422 MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
427 RtlFreeHeap(RtlGetProcessHeap(),
431 if (!NT_SUCCESS(Status
))
433 /* fail, we were unable to read the reparse point data! */
434 DPRINT1("Querying or setting the reparse point failed: 0x%x\n", Status
);
441 * Copy alternate file streams, if existing
444 /* FIXME - enumerate and copy the file streams */
448 * We successfully created the directory and copied all information
449 * from the template directory
451 Status
= STATUS_SUCCESS
;
454 RtlFreeHeap (RtlGetProcessHeap (),
459 if (TemplateHandle
!= NULL
)
461 NtClose(TemplateHandle
);
464 RtlFreeHeap (RtlGetProcessHeap (),
466 NtTemplatePathU
.Buffer
);
468 /* free the he extended attributes buffer */
469 if (EaBuffer
!= NULL
)
471 RtlFreeHeap (RtlGetProcessHeap (),
476 if (DirectoryHandle
!= NULL
)
478 NtClose(DirectoryHandle
);
481 if (!NT_SUCCESS(Status
))
483 SetLastErrorByStatus(Status
);
502 DPRINT("RemoveDirectoryA(%s)\n",lpPathName
);
504 if (!(PathNameW
= FilenameA2W(lpPathName
, FALSE
)))
507 return RemoveDirectoryW (PathNameW
);
520 FILE_DISPOSITION_INFORMATION FileDispInfo
;
521 OBJECT_ATTRIBUTES ObjectAttributes
;
522 IO_STATUS_BLOCK IoStatusBlock
;
523 UNICODE_STRING NtPathU
;
524 HANDLE DirectoryHandle
;
527 DPRINT("lpPathName %S\n", lpPathName
);
529 if (!RtlDosPathNameToNtPathName_U (lpPathName
,
535 InitializeObjectAttributes(&ObjectAttributes
,
537 OBJ_CASE_INSENSITIVE
,
541 DPRINT("NtPathU '%S'\n", NtPathU
.Buffer
);
543 Status
= NtCreateFile (&DirectoryHandle
,
548 FILE_ATTRIBUTE_DIRECTORY
, /* 0x7 */
551 FILE_DIRECTORY_FILE
, /* 0x204021 */
555 RtlFreeHeap (RtlGetProcessHeap (),
559 if (!NT_SUCCESS(Status
))
562 SetLastErrorByStatus (Status
);
566 FileDispInfo
.DeleteFile
= TRUE
;
568 Status
= NtSetInformationFile (DirectoryHandle
,
571 sizeof(FILE_DISPOSITION_INFORMATION
),
572 FileDispositionInformation
);
573 NtClose(DirectoryHandle
);
575 if (!NT_SUCCESS(Status
))
577 SetLastErrorByStatus (Status
);
597 WCHAR BufferW
[MAX_PATH
];
600 LPWSTR FilePartW
= NULL
;
602 DPRINT("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, "
603 "lpFilePart %p)\n",lpFileName
,nBufferLength
,lpBuffer
,lpFilePart
);
607 SetLastError(ERROR_INVALID_PARAMETER
);
611 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
614 ret
= GetFullPathNameW(FileNameW
, MAX_PATH
, BufferW
, &FilePartW
);
621 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
625 ret
= FilenameW2A_FitOrFail(lpBuffer
, nBufferLength
, BufferW
, ret
+1);
627 if (ret
< nBufferLength
&& lpFilePart
)
629 /* if the path closed with '\', FilePart is NULL */
633 *lpFilePart
= (FilePartW
- BufferW
) + lpBuffer
;
636 DPRINT("GetFullPathNameA ret: lpBuffer %s lpFilePart %s\n",
637 lpBuffer
, (lpFilePart
== NULL
) ? "NULL" : *lpFilePart
);
657 DPRINT("GetFullPathNameW(lpFileName %S, nBufferLength %d, lpBuffer %p, "
658 "lpFilePart %p)\n",lpFileName
,nBufferLength
,lpBuffer
,lpFilePart
);
660 Length
= RtlGetFullPathName_U ((LPWSTR
)lpFileName
,
661 nBufferLength
* sizeof(WCHAR
),
665 DPRINT("GetFullPathNameW ret: lpBuffer %S lpFilePart %S Length %ld\n",
666 lpBuffer
, (lpFilePart
== NULL
) ? L
"NULL" : *lpFilePart
, Length
/ sizeof(WCHAR
));
668 return Length
/sizeof(WCHAR
);
673 * NOTE: Copied from Wine.
685 WCHAR ShortPathW
[MAX_PATH
];
690 SetLastError(ERROR_INVALID_PARAMETER
);
694 if (!(LongPathW
= FilenameA2W(longpath
, FALSE
)))
697 ret
= GetShortPathNameW(LongPathW
, ShortPathW
, MAX_PATH
);
704 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
708 return FilenameW2A_FitOrFail(shortpath
, shortlen
, ShortPathW
, ret
+1);
713 * NOTE: Copied from Wine.
724 WCHAR tmpshortpath
[MAX_PATH
];
726 DWORD sp
= 0, lp
= 0;
728 WIN32_FIND_DATAW wfd
;
731 WCHAR ustr_buf
[8+1+3+1];
733 DPRINT("GetShortPathNameW: %S\n",longpath
);
737 SetLastError(ERROR_INVALID_PARAMETER
);
742 SetLastError(ERROR_BAD_PATHNAME
);
746 /* check for drive letter */
747 if (longpath
[1] == ':' )
749 tmpshortpath
[0] = longpath
[0];
750 tmpshortpath
[1] = ':';
754 ustr
.Buffer
= ustr_buf
;
756 ustr
.MaximumLength
= sizeof(ustr_buf
);
760 /* check for path delimiters and reproduce them */
761 if (longpath
[lp
] == '\\' || longpath
[lp
] == '/')
763 if (!sp
|| tmpshortpath
[sp
-1] != '\\')
765 /* strip double "\\" */
766 tmpshortpath
[sp
] = '\\';
769 tmpshortpath
[sp
] = 0; /* terminate string */
774 for (p
= longpath
+ lp
; *p
&& *p
!= '/' && *p
!= '\\'; p
++);
775 tmplen
= p
- (longpath
+ lp
);
776 lstrcpynW(tmpshortpath
+ sp
, longpath
+ lp
, tmplen
+ 1);
777 /* Check, if the current element is a valid dos name */
778 if (tmplen
<= 8+1+3+1)
781 memcpy(ustr_buf
, longpath
+ lp
, tmplen
* sizeof(WCHAR
));
782 ustr_buf
[tmplen
] = '\0';
783 ustr
.Length
= tmplen
* sizeof(WCHAR
);
784 if (RtlIsNameLegalDOS8Dot3(&ustr
, NULL
, &spaces
) && !spaces
)
792 /* Check if the file exists and use the existing short file name */
793 goit
= FindFirstFileW(tmpshortpath
, &wfd
);
794 if (goit
== INVALID_HANDLE_VALUE
) goto notfound
;
796 lstrcpyW(tmpshortpath
+ sp
, wfd
.cAlternateFileName
);
797 sp
+= lstrlenW(tmpshortpath
+ sp
);
800 tmpshortpath
[sp
] = 0;
802 tmplen
= lstrlenW(tmpshortpath
) + 1;
803 if (tmplen
<= shortlen
)
805 lstrcpyW(shortpath
, tmpshortpath
);
806 tmplen
--; /* length without 0 */
812 SetLastError ( ERROR_FILE_NOT_FOUND
);
831 UNICODE_STRING PathU
= {0};
832 UNICODE_STRING FileNameU
= {0};
833 UNICODE_STRING ExtensionU
= {0};
834 UNICODE_STRING BufferU
= {0};
836 ANSI_STRING FileName
;
837 ANSI_STRING Extension
;
841 NTSTATUS Status
= STATUS_SUCCESS
;
843 RtlInitAnsiString (&Path
,
845 RtlInitAnsiString (&FileName
,
847 RtlInitAnsiString (&Extension
,
850 /* convert ansi (or oem) strings to unicode */
853 Status
= RtlAnsiStringToUnicodeString (&PathU
,
856 if (!NT_SUCCESS(Status
))
859 Status
= RtlAnsiStringToUnicodeString (&FileNameU
,
862 if (!NT_SUCCESS(Status
))
865 Status
= RtlAnsiStringToUnicodeString (&ExtensionU
,
868 if (!NT_SUCCESS(Status
))
873 Status
= RtlOemStringToUnicodeString (&PathU
,
876 if (!NT_SUCCESS(Status
))
878 Status
= RtlOemStringToUnicodeString (&FileNameU
,
881 if (!NT_SUCCESS(Status
))
884 Status
= RtlOemStringToUnicodeString (&ExtensionU
,
887 if (!NT_SUCCESS(Status
))
891 BufferU
.MaximumLength
= nBufferLength
* sizeof(WCHAR
);
892 BufferU
.Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
894 BufferU
.MaximumLength
);
895 if (BufferU
.Buffer
== NULL
)
897 Status
= STATUS_NO_MEMORY
;
901 Buffer
.MaximumLength
= nBufferLength
;
902 Buffer
.Buffer
= lpBuffer
;
904 RetValue
= SearchPathW (NULL
== lpPath
? NULL
: PathU
.Buffer
,
905 NULL
== lpFileName
? NULL
: FileNameU
.Buffer
,
906 NULL
== lpExtension
? NULL
: ExtensionU
.Buffer
,
913 BufferU
.Length
= wcslen(BufferU
.Buffer
) * sizeof(WCHAR
);
914 /* convert ansi (or oem) string to unicode */
916 RtlUnicodeStringToAnsiString (&Buffer
,
920 RtlUnicodeStringToOemString (&Buffer
,
923 /* nul-terminate ascii string */
924 Buffer
.Buffer
[BufferU
.Length
/ sizeof(WCHAR
)] = '\0';
926 if (NULL
!= lpFilePart
&& BufferU
.Length
!= 0)
928 *lpFilePart
= strrchr (lpBuffer
, '\\') + 1;
933 RtlFreeHeap (RtlGetProcessHeap (),
936 RtlFreeHeap (RtlGetProcessHeap (),
939 RtlFreeHeap (RtlGetProcessHeap (),
942 RtlFreeHeap (RtlGetProcessHeap (),
946 if (!NT_SUCCESS(Status
))
948 SetLastErrorByStatus(Status
);
970 * FUNCTION: Searches for the specified file
972 * lpPath = Points to a null-terminated string that specified the
973 * path to be searched. If this parameters is NULL then
974 * the following directories are searched
975 * The directory from which the application loaded
976 * The current directory
977 * The system directory
978 * The 16-bit system directory
979 * The windows directory
980 * The directories listed in the PATH environment
982 * lpFileName = Specifies the filename to search for
983 * lpExtension = Points to the null-terminated string that specifies
984 * an extension to be added to the filename when
985 * searching for the file. The first character of the
986 * filename extension must be a period (.). The
987 * extension is only added if the specified filename
988 * doesn't end with an extension
990 * If the filename extension is not required or if the
991 * filename contains an extension, this parameters can be
993 * nBufferLength = The length in characters of the buffer for output
994 * lpBuffer = Points to the buffer for the valid path and filename of
996 * lpFilePart = Points to the last component of the valid path and
998 * RETURNS: On success, the length, in characters, of the string copied to the
1005 PWCHAR EnvironmentBufferW
= NULL
;
1006 PWCHAR AppPathW
= NULL
;
1012 DPRINT("SearchPath\n");
1014 HasExtension
= FALSE
;
1015 p
= lpFileName
+ wcslen(lpFileName
);
1016 while (lpFileName
< p
&&
1017 L
'\\' != *(p
- 1) &&
1021 HasExtension
= HasExtension
|| L
'.' == *(p
- 1);
1026 if (HasExtension
|| NULL
== lpExtension
)
1028 Name
= (PWCHAR
) lpFileName
;
1032 Name
= RtlAllocateHeap(GetProcessHeap(),
1033 HEAP_GENERATE_EXCEPTIONS
,
1034 (wcslen(lpFileName
) + wcslen(lpExtension
) + 1)
1038 SetLastError(ERROR_OUTOFMEMORY
);
1041 wcscat(wcscpy(Name
, lpFileName
), lpExtension
);
1043 if (RtlDoesFileExists_U(Name
))
1045 retCode
= RtlGetFullPathName_U (Name
,
1046 nBufferLength
* sizeof(WCHAR
),
1050 if (Name
!= lpFileName
)
1052 RtlFreeHeap(GetProcessHeap(), 0, Name
);
1060 AppPathW
= (PWCHAR
) RtlAllocateHeap(RtlGetProcessHeap(),
1061 HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,
1062 MAX_PATH
* sizeof(WCHAR
));
1063 if (AppPathW
== NULL
)
1065 SetLastError(ERROR_OUTOFMEMORY
);
1070 wcscat (AppPathW
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
);
1072 len
= wcslen (AppPathW
);
1074 while (len
&& AppPathW
[len
- 1] != L
'\\')
1077 if (len
) AppPathW
[len
-1] = L
'\0';
1079 len
= GetEnvironmentVariableW(L
"PATH", &Buffer
, 0);
1080 len
+= 1 + GetCurrentDirectoryW(0, &Buffer
);
1081 len
+= 1 + GetSystemDirectoryW(&Buffer
, 0);
1082 len
+= 1 + GetWindowsDirectoryW(&Buffer
, 0);
1083 len
+= 1 + wcslen(AppPathW
) * sizeof(WCHAR
);
1085 EnvironmentBufferW
= (PWCHAR
) RtlAllocateHeap(RtlGetProcessHeap(),
1086 HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,
1087 len
* sizeof(WCHAR
));
1088 if (EnvironmentBufferW
== NULL
)
1090 RtlFreeHeap(RtlGetProcessHeap(), 0, AppPathW
);
1091 SetLastError(ERROR_OUTOFMEMORY
);
1095 pos
= GetCurrentDirectoryW(len
, EnvironmentBufferW
);
1096 EnvironmentBufferW
[pos
++] = L
';';
1097 EnvironmentBufferW
[pos
] = 0;
1098 pos
+= GetSystemDirectoryW(&EnvironmentBufferW
[pos
], len
- pos
);
1099 EnvironmentBufferW
[pos
++] = L
';';
1100 EnvironmentBufferW
[pos
] = 0;
1101 pos
+= GetWindowsDirectoryW(&EnvironmentBufferW
[pos
], len
- pos
);
1102 EnvironmentBufferW
[pos
++] = L
';';
1103 EnvironmentBufferW
[pos
] = 0;
1104 pos
+= GetEnvironmentVariableW(L
"PATH", &EnvironmentBufferW
[pos
], len
- pos
);
1105 EnvironmentBufferW
[pos
++] = L
';';
1106 EnvironmentBufferW
[pos
] = 0;
1107 wcscat (EnvironmentBufferW
, AppPathW
);
1109 RtlFreeHeap (RtlGetProcessHeap (),
1113 lpPath
= EnvironmentBufferW
;
1117 retCode
= RtlDosSearchPath_U ((PWCHAR
)lpPath
, (PWCHAR
)lpFileName
, (PWCHAR
)lpExtension
,
1118 nBufferLength
* sizeof(WCHAR
), lpBuffer
, lpFilePart
);
1120 if (EnvironmentBufferW
!= NULL
)
1122 RtlFreeHeap(GetProcessHeap(), 0, EnvironmentBufferW
);
1126 SetLastError(ERROR_FILE_NOT_FOUND
);
1129 return retCode
/ sizeof(WCHAR
);
1141 UNICODE_STRING PathName
;
1143 RtlInitUnicodeString(&PathName
, lpPathName
);
1145 RtlEnterCriticalSection(&DllLock
);
1146 if(PathName
.Length
> 0)
1148 if(PathName
.Length
+ sizeof(WCHAR
) <= DllDirectory
.MaximumLength
)
1150 RtlCopyUnicodeString(&DllDirectory
, &PathName
);
1154 RtlFreeUnicodeString(&DllDirectory
);
1155 if(!(DllDirectory
.Buffer
= (PWSTR
)RtlAllocateHeap(RtlGetProcessHeap(),
1157 PathName
.Length
+ sizeof(WCHAR
))))
1159 RtlLeaveCriticalSection(&DllLock
);
1160 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1163 DllDirectory
.Length
= 0;
1164 DllDirectory
.MaximumLength
= PathName
.Length
+ sizeof(WCHAR
);
1166 RtlCopyUnicodeString(&DllDirectory
, &PathName
);
1171 RtlFreeUnicodeString(&DllDirectory
);
1173 RtlLeaveCriticalSection(&DllLock
);
1184 LPCSTR lpPathName
/* can be NULL */
1187 PWCHAR PathNameW
=NULL
;
1191 if (!(PathNameW
= FilenameA2W(lpPathName
, FALSE
)))
1195 return SetDllDirectoryW(PathNameW
);
1204 DWORD nBufferLength
,
1210 RtlEnterCriticalSection(&DllLock
);
1211 if(nBufferLength
> 0)
1213 Ret
= DllDirectory
.Length
/ sizeof(WCHAR
);
1214 if(Ret
> nBufferLength
- 1)
1216 Ret
= nBufferLength
- 1;
1221 RtlCopyMemory(lpBuffer
, DllDirectory
.Buffer
, Ret
* sizeof(WCHAR
));
1223 lpBuffer
[Ret
] = L
'\0';
1227 /* include termination character, even if the string is empty! */
1228 Ret
= (DllDirectory
.Length
/ sizeof(WCHAR
)) + 1;
1230 RtlLeaveCriticalSection(&DllLock
);
1241 DWORD nBufferLength
,
1245 WCHAR BufferW
[MAX_PATH
];
1248 ret
= GetDllDirectoryW(MAX_PATH
, BufferW
);
1255 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
1259 return FilenameW2A_FitOrFail(lpBuffer
, nBufferLength
, BufferW
, ret
+1);
1267 NeedCurrentDirectoryForExePathW(LPCWSTR ExeName
)
1269 return (wcschr(ExeName
,
1278 NeedCurrentDirectoryForExePathA(LPCSTR ExeName
)
1280 return (strchr(ExeName
,
1288 /***********************************************************************
1291 * GetLongPathNameW (KERNEL32.@)
1294 * observed (Win2000):
1295 * shortpath=NULL: LastError=ERROR_INVALID_PARAMETER, ret=0
1296 * shortpath="": LastError=ERROR_PATH_NOT_FOUND, ret=0
1298 DWORD STDCALL
GetLongPathNameW( LPCWSTR shortpath
, LPWSTR longpath
, DWORD longlen
)
1300 #define MAX_PATHNAME_LEN 1024
1302 WCHAR tmplongpath
[MAX_PATHNAME_LEN
];
1304 DWORD sp
= 0, lp
= 0;
1306 BOOL unixabsolute
= (shortpath
[0] == '/');
1307 WIN32_FIND_DATAW wfd
;
1312 SetLastError(ERROR_INVALID_PARAMETER
);
1317 SetLastError(ERROR_PATH_NOT_FOUND
);
1321 DPRINT("GetLongPathNameW(%s,%p,%ld)\n", shortpath
, longpath
, longlen
);
1323 if (shortpath
[0] == '\\' && shortpath
[1] == '\\')
1325 DPRINT1("ERR: UNC pathname %s\n", shortpath
);
1326 lstrcpynW( longpath
, shortpath
, longlen
);
1327 return wcslen(longpath
);
1330 /* check for drive letter */
1331 if (!unixabsolute
&& shortpath
[1] == ':' )
1333 tmplongpath
[0] = shortpath
[0];
1334 tmplongpath
[1] = ':';
1338 while (shortpath
[sp
])
1340 /* check for path delimiters and reproduce them */
1341 if (shortpath
[sp
] == '\\' || shortpath
[sp
] == '/')
1343 if (!lp
|| tmplongpath
[lp
-1] != '\\')
1345 /* strip double "\\" */
1346 tmplongpath
[lp
++] = '\\';
1348 tmplongpath
[lp
] = 0; /* terminate string */
1354 if (sp
== 0 && p
[0] == '.' && (p
[1] == '/' || p
[1] == '\\'))
1356 tmplongpath
[lp
++] = *p
++;
1357 tmplongpath
[lp
++] = *p
++;
1359 for (; *p
&& *p
!= '/' && *p
!= '\\'; p
++);
1360 tmplen
= p
- (shortpath
+ sp
);
1361 lstrcpynW(tmplongpath
+ lp
, shortpath
+ sp
, tmplen
+ 1);
1362 /* Check if the file exists and use the existing file name */
1363 goit
= FindFirstFileW(tmplongpath
, &wfd
);
1364 if (goit
== INVALID_HANDLE_VALUE
)
1366 DPRINT("not found %s!\n", tmplongpath
);
1367 SetLastError ( ERROR_FILE_NOT_FOUND
);
1371 wcscpy(tmplongpath
+ lp
, wfd
.cFileName
);
1372 lp
+= wcslen(tmplongpath
+ lp
);
1375 tmplen
= wcslen(shortpath
) - 1;
1376 if ((shortpath
[tmplen
] == '/' || shortpath
[tmplen
] == '\\') &&
1377 (tmplongpath
[lp
- 1] != '/' && tmplongpath
[lp
- 1] != '\\'))
1378 tmplongpath
[lp
++] = shortpath
[tmplen
];
1379 tmplongpath
[lp
] = 0;
1381 tmplen
= wcslen(tmplongpath
) + 1;
1382 if (tmplen
<= longlen
)
1384 wcscpy(longpath
, tmplongpath
);
1385 DPRINT("returning %s\n", longpath
);
1386 tmplen
--; /* length without 0 */
1394 /***********************************************************************
1395 * GetLongPathNameA (KERNEL32.@)
1397 DWORD STDCALL
GetLongPathNameA( LPCSTR shortpath
, LPSTR longpath
, DWORD longlen
)
1400 WCHAR longpathW
[MAX_PATH
];
1403 DPRINT("GetLongPathNameA %s, %i\n",shortpath
,longlen
);
1405 if (!(shortpathW
= FilenameA2W( shortpath
, FALSE
)))
1408 ret
= GetLongPathNameW(shortpathW
, longpathW
, MAX_PATH
);
1413 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
1417 return FilenameW2A_FitOrFail(longpath
, longlen
, longpathW
, ret
+1 );