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 ******************************************************************/
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
= NULL
;
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 DPRINT("NtCreateFile failed with Status %lx\n", Status
);
138 SetLastErrorByStatus(Status
);
142 NtClose (DirectoryHandle
);
154 LPCWSTR lpTemplateDirectory
,
155 LPCWSTR lpNewDirectory
,
156 LPSECURITY_ATTRIBUTES lpSecurityAttributes
159 OBJECT_ATTRIBUTES ObjectAttributes
;
160 IO_STATUS_BLOCK IoStatusBlock
;
161 UNICODE_STRING NtPathU
, NtTemplatePathU
;
162 HANDLE DirectoryHandle
= NULL
;
163 HANDLE TemplateHandle
= NULL
;
164 FILE_EA_INFORMATION EaInformation
;
165 FILE_BASIC_INFORMATION FileBasicInfo
;
167 ULONG OpenOptions
, CreateOptions
;
168 ACCESS_MASK DesiredAccess
;
169 BOOLEAN ReparsePoint
= FALSE
;
170 PVOID EaBuffer
= NULL
;
173 OpenOptions
= FILE_DIRECTORY_FILE
| FILE_OPEN_REPARSE_POINT
|
174 FILE_OPEN_FOR_BACKUP_INTENT
;
175 CreateOptions
= FILE_DIRECTORY_FILE
| FILE_OPEN_FOR_BACKUP_INTENT
;
176 DesiredAccess
= FILE_LIST_DIRECTORY
| SYNCHRONIZE
| FILE_WRITE_ATTRIBUTES
|
177 FILE_READ_ATTRIBUTES
;
179 DPRINT ("lpTemplateDirectory %ws lpNewDirectory %ws lpSecurityAttributes %p\n",
180 lpTemplateDirectory
, lpNewDirectory
, lpSecurityAttributes
);
183 * Translate the template directory path
186 if (!RtlDosPathNameToNtPathName_U (lpTemplateDirectory
,
191 SetLastError(ERROR_PATH_NOT_FOUND
);
195 InitializeObjectAttributes(&ObjectAttributes
,
197 OBJ_CASE_INSENSITIVE
,
202 * Open the template directory
206 Status
= NtOpenFile (&TemplateHandle
,
207 FILE_LIST_DIRECTORY
| FILE_READ_ATTRIBUTES
| FILE_READ_EA
,
210 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
212 if (!NT_SUCCESS(Status
))
214 if (Status
== STATUS_INVALID_PARAMETER
&&
215 (OpenOptions
& FILE_OPEN_REPARSE_POINT
))
217 /* Some FSs (FAT) don't support reparse points, try opening
218 the directory without FILE_OPEN_REPARSE_POINT */
219 OpenOptions
&= ~FILE_OPEN_REPARSE_POINT
;
221 DPRINT("Reparse points not supported, try with less options\n");
224 goto OpenTemplateDir
;
228 DPRINT1("Failed to open the template directory: 0x%x\n", Status
);
229 goto CleanupNoNtPath
;
234 * Translate the new directory path and check if they're the same
237 if (!RtlDosPathNameToNtPathName_U (lpNewDirectory
,
242 Status
= STATUS_OBJECT_PATH_NOT_FOUND
;
243 goto CleanupNoNtPath
;
246 if (RtlEqualUnicodeString(&NtPathU
,
250 DPRINT1("Both directory paths are the same!\n");
251 Status
= STATUS_OBJECT_NAME_INVALID
;
255 InitializeObjectAttributes(&ObjectAttributes
,
257 OBJ_CASE_INSENSITIVE
,
259 (lpSecurityAttributes
? lpSecurityAttributes
->lpSecurityDescriptor
: NULL
));
262 * Query the basic file attributes from the template directory
265 /* Make sure FILE_ATTRIBUTE_NORMAL is used in case the information
266 isn't set by the FS */
267 FileBasicInfo
.FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
268 Status
= NtQueryInformationFile(TemplateHandle
,
271 sizeof(FILE_BASIC_INFORMATION
),
272 FileBasicInformation
);
273 if (!NT_SUCCESS(Status
))
275 DPRINT1("Failed to query the basic directory attributes\n");
279 /* clear the reparse point attribute if present. We're going to set the
280 reparse point later which will cause the attribute to be set */
281 if (FileBasicInfo
.FileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
)
283 FileBasicInfo
.FileAttributes
&= ~FILE_ATTRIBUTE_REPARSE_POINT
;
285 /* writing the extended attributes requires the FILE_WRITE_DATA
287 DesiredAccess
|= FILE_WRITE_DATA
;
289 CreateOptions
|= FILE_OPEN_REPARSE_POINT
;
294 * Read the Extended Attributes if present
299 Status
= NtQueryInformationFile(TemplateHandle
,
302 sizeof(FILE_EA_INFORMATION
),
304 if (NT_SUCCESS(Status
) && (EaInformation
.EaSize
!= 0))
306 EaBuffer
= RtlAllocateHeap(RtlGetProcessHeap(),
308 EaInformation
.EaSize
);
309 if (EaBuffer
== NULL
)
311 Status
= STATUS_INSUFFICIENT_RESOURCES
;
315 Status
= NtQueryEaFile(TemplateHandle
,
318 EaInformation
.EaSize
,
325 if (NT_SUCCESS(Status
))
327 /* we successfully read the extended attributes */
328 EaLength
= EaInformation
.EaSize
;
333 RtlFreeHeap(RtlGetProcessHeap(),
338 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
340 /* unless we just allocated not enough memory, break the loop
341 and just continue without copying extended attributes */
348 /* failure or no extended attributes present, break the loop */
353 if (!NT_SUCCESS(Status
))
355 DPRINT1("Querying the EA data failed: 0x%x\n", Status
);
360 * Create the new directory
363 Status
= NtCreateFile (&DirectoryHandle
,
368 FileBasicInfo
.FileAttributes
,
369 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
374 if (!NT_SUCCESS(Status
))
377 (Status
== STATUS_INVALID_PARAMETER
|| Status
== STATUS_ACCESS_DENIED
))
379 /* The FS doesn't seem to support reparse points... */
380 DPRINT1("Cannot copy the hardlink, destination doesn\'t support reparse points!\n");
389 * Copy the reparse point
392 PREPARSE_GUID_DATA_BUFFER ReparseDataBuffer
=
393 (PREPARSE_GUID_DATA_BUFFER
)RtlAllocateHeap(RtlGetProcessHeap(),
395 MAXIMUM_REPARSE_DATA_BUFFER_SIZE
);
397 if (ReparseDataBuffer
== NULL
)
399 Status
= STATUS_INSUFFICIENT_RESOURCES
;
403 /* query the size of the reparse data buffer structure */
404 Status
= NtFsControlFile(TemplateHandle
,
409 FSCTL_GET_REPARSE_POINT
,
413 MAXIMUM_REPARSE_DATA_BUFFER_SIZE
);
414 if (NT_SUCCESS(Status
))
416 /* write the reparse point */
417 Status
= NtFsControlFile(DirectoryHandle
,
422 FSCTL_SET_REPARSE_POINT
,
424 MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
429 RtlFreeHeap(RtlGetProcessHeap(),
433 if (!NT_SUCCESS(Status
))
435 /* fail, we were unable to read the reparse point data! */
436 DPRINT1("Querying or setting the reparse point failed: 0x%x\n", Status
);
443 * Copy alternate file streams, if existing
446 /* FIXME - enumerate and copy the file streams */
450 * We successfully created the directory and copied all information
451 * from the template directory
453 Status
= STATUS_SUCCESS
;
456 RtlFreeHeap (RtlGetProcessHeap (),
461 if (TemplateHandle
!= NULL
)
463 NtClose(TemplateHandle
);
466 RtlFreeHeap (RtlGetProcessHeap (),
468 NtTemplatePathU
.Buffer
);
470 /* free the he extended attributes buffer */
471 if (EaBuffer
!= NULL
)
473 RtlFreeHeap (RtlGetProcessHeap (),
478 if (DirectoryHandle
!= NULL
)
480 NtClose(DirectoryHandle
);
483 if (!NT_SUCCESS(Status
))
485 SetLastErrorByStatus(Status
);
504 DPRINT("RemoveDirectoryA(%s)\n",lpPathName
);
506 if (!(PathNameW
= FilenameA2W(lpPathName
, FALSE
)))
509 return RemoveDirectoryW (PathNameW
);
522 FILE_DISPOSITION_INFORMATION FileDispInfo
;
523 OBJECT_ATTRIBUTES ObjectAttributes
;
524 IO_STATUS_BLOCK IoStatusBlock
;
525 UNICODE_STRING NtPathU
;
526 HANDLE DirectoryHandle
= NULL
;
529 DPRINT("lpPathName %S\n", lpPathName
);
531 if (!RtlDosPathNameToNtPathName_U (lpPathName
,
537 InitializeObjectAttributes(&ObjectAttributes
,
539 OBJ_CASE_INSENSITIVE
,
543 DPRINT("NtPathU '%S'\n", NtPathU
.Buffer
);
545 Status
= NtCreateFile (&DirectoryHandle
,
550 FILE_ATTRIBUTE_DIRECTORY
, /* 0x7 */
553 FILE_DIRECTORY_FILE
, /* 0x204021 */
557 RtlFreeHeap (RtlGetProcessHeap (),
561 if (!NT_SUCCESS(Status
))
564 SetLastErrorByStatus (Status
);
568 FileDispInfo
.DeleteFile
= TRUE
;
570 Status
= NtSetInformationFile (DirectoryHandle
,
573 sizeof(FILE_DISPOSITION_INFORMATION
),
574 FileDispositionInformation
);
575 NtClose(DirectoryHandle
);
577 if (!NT_SUCCESS(Status
))
579 SetLastErrorByStatus (Status
);
599 WCHAR BufferW
[MAX_PATH
];
602 LPWSTR FilePartW
= NULL
;
604 DPRINT("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, "
605 "lpFilePart %p)\n",lpFileName
,nBufferLength
,lpBuffer
,lpFilePart
);
609 SetLastError(ERROR_INVALID_PARAMETER
);
613 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
616 ret
= GetFullPathNameW(FileNameW
, MAX_PATH
, BufferW
, &FilePartW
);
623 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
627 ret
= FilenameW2A_FitOrFail(lpBuffer
, nBufferLength
, BufferW
, ret
+1);
629 if (ret
< nBufferLength
&& lpFilePart
)
631 /* if the path closed with '\', FilePart is NULL */
635 *lpFilePart
= (FilePartW
- BufferW
) + lpBuffer
;
638 DPRINT("GetFullPathNameA ret: lpBuffer %s lpFilePart %s\n",
639 lpBuffer
, (lpFilePart
== NULL
) ? "NULL" : *lpFilePart
);
659 DPRINT("GetFullPathNameW(lpFileName %S, nBufferLength %d, lpBuffer %p, "
660 "lpFilePart %p)\n",lpFileName
,nBufferLength
,lpBuffer
,lpFilePart
);
662 Length
= RtlGetFullPathName_U ((LPWSTR
)lpFileName
,
663 nBufferLength
* sizeof(WCHAR
),
667 DPRINT("GetFullPathNameW ret: lpBuffer %S lpFilePart %S Length %ld\n",
668 lpBuffer
, (lpFilePart
== NULL
) ? L
"NULL" : *lpFilePart
, Length
/ sizeof(WCHAR
));
670 return Length
/sizeof(WCHAR
);
675 * NOTE: Copied from Wine.
687 WCHAR ShortPathW
[MAX_PATH
];
692 SetLastError(ERROR_INVALID_PARAMETER
);
696 if (!(LongPathW
= FilenameA2W(longpath
, FALSE
)))
699 ret
= GetShortPathNameW(LongPathW
, ShortPathW
, MAX_PATH
);
706 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
710 return FilenameW2A_FitOrFail(shortpath
, shortlen
, ShortPathW
, ret
+1);
715 * NOTE: Copied from Wine.
726 WCHAR tmpshortpath
[MAX_PATH
];
728 DWORD sp
= 0, lp
= 0;
730 WIN32_FIND_DATAW wfd
;
733 WCHAR ustr_buf
[8+1+3+1];
735 DPRINT("GetShortPathNameW: %S\n",longpath
);
739 SetLastError(ERROR_INVALID_PARAMETER
);
744 SetLastError(ERROR_BAD_PATHNAME
);
748 /* check for drive letter */
749 if (longpath
[1] == ':' )
751 tmpshortpath
[0] = longpath
[0];
752 tmpshortpath
[1] = ':';
756 ustr
.Buffer
= ustr_buf
;
758 ustr
.MaximumLength
= sizeof(ustr_buf
);
762 /* check for path delimiters and reproduce them */
763 if (longpath
[lp
] == '\\' || longpath
[lp
] == '/')
765 if (!sp
|| tmpshortpath
[sp
-1] != '\\')
767 /* strip double "\\" */
768 tmpshortpath
[sp
] = '\\';
771 tmpshortpath
[sp
] = 0; /* terminate string */
776 for (p
= longpath
+ lp
; *p
&& *p
!= '/' && *p
!= '\\'; p
++);
777 tmplen
= p
- (longpath
+ lp
);
778 lstrcpynW(tmpshortpath
+ sp
, longpath
+ lp
, tmplen
+ 1);
779 /* Check, if the current element is a valid dos name */
780 if (tmplen
<= 8+1+3+1)
783 memcpy(ustr_buf
, longpath
+ lp
, tmplen
* sizeof(WCHAR
));
784 ustr_buf
[tmplen
] = '\0';
785 ustr
.Length
= (USHORT
)tmplen
* sizeof(WCHAR
);
786 if (RtlIsNameLegalDOS8Dot3(&ustr
, NULL
, &spaces
) && !spaces
)
794 /* Check if the file exists and use the existing short file name */
795 goit
= FindFirstFileW(tmpshortpath
, &wfd
);
796 if (goit
== INVALID_HANDLE_VALUE
) goto notfound
;
798 lstrcpyW(tmpshortpath
+ sp
, wfd
.cAlternateFileName
);
799 sp
+= lstrlenW(tmpshortpath
+ sp
);
802 tmpshortpath
[sp
] = 0;
804 tmplen
= lstrlenW(tmpshortpath
) + 1;
805 if (tmplen
<= shortlen
)
807 lstrcpyW(shortpath
, tmpshortpath
);
808 tmplen
--; /* length without 0 */
814 SetLastError ( ERROR_FILE_NOT_FOUND
);
833 UNICODE_STRING PathU
= {0};
834 UNICODE_STRING FileNameU
= {0};
835 UNICODE_STRING ExtensionU
= {0};
836 UNICODE_STRING BufferU
= {0};
838 ANSI_STRING FileName
;
839 ANSI_STRING Extension
;
843 NTSTATUS Status
= STATUS_SUCCESS
;
845 RtlInitAnsiString (&Path
,
847 RtlInitAnsiString (&FileName
,
849 RtlInitAnsiString (&Extension
,
852 /* convert ansi (or oem) strings to unicode */
855 Status
= RtlAnsiStringToUnicodeString (&PathU
,
858 if (!NT_SUCCESS(Status
))
861 Status
= RtlAnsiStringToUnicodeString (&FileNameU
,
864 if (!NT_SUCCESS(Status
))
867 Status
= RtlAnsiStringToUnicodeString (&ExtensionU
,
870 if (!NT_SUCCESS(Status
))
875 Status
= RtlOemStringToUnicodeString (&PathU
,
878 if (!NT_SUCCESS(Status
))
880 Status
= RtlOemStringToUnicodeString (&FileNameU
,
883 if (!NT_SUCCESS(Status
))
886 Status
= RtlOemStringToUnicodeString (&ExtensionU
,
889 if (!NT_SUCCESS(Status
))
893 BufferU
.MaximumLength
= (USHORT
)nBufferLength
* sizeof(WCHAR
);
894 BufferU
.Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
896 BufferU
.MaximumLength
);
897 if (BufferU
.Buffer
== NULL
)
899 Status
= STATUS_NO_MEMORY
;
903 Buffer
.MaximumLength
= (USHORT
)nBufferLength
;
904 Buffer
.Buffer
= lpBuffer
;
906 RetValue
= SearchPathW (NULL
== lpPath
? NULL
: PathU
.Buffer
,
907 NULL
== lpFileName
? NULL
: FileNameU
.Buffer
,
908 NULL
== lpExtension
? NULL
: ExtensionU
.Buffer
,
915 BufferU
.Length
= wcslen(BufferU
.Buffer
) * sizeof(WCHAR
);
916 /* convert ansi (or oem) string to unicode */
918 RtlUnicodeStringToAnsiString (&Buffer
,
922 RtlUnicodeStringToOemString (&Buffer
,
925 /* nul-terminate ascii string */
926 Buffer
.Buffer
[BufferU
.Length
/ sizeof(WCHAR
)] = '\0';
928 if (NULL
!= lpFilePart
&& BufferU
.Length
!= 0)
930 *lpFilePart
= strrchr (lpBuffer
, '\\') + 1;
935 RtlFreeHeap (RtlGetProcessHeap (),
938 RtlFreeHeap (RtlGetProcessHeap (),
941 RtlFreeHeap (RtlGetProcessHeap (),
944 RtlFreeHeap (RtlGetProcessHeap (),
948 if (!NT_SUCCESS(Status
))
950 SetLastErrorByStatus(Status
);
972 * FUNCTION: Searches for the specified file
974 * lpPath = Points to a null-terminated string that specified the
975 * path to be searched. If this parameters is NULL then
976 * the following directories are searched
977 * The directory from which the application loaded
978 * The current directory
979 * The system directory
980 * The 16-bit system directory
981 * The windows directory
982 * The directories listed in the PATH environment
984 * lpFileName = Specifies the filename to search for
985 * lpExtension = Points to the null-terminated string that specifies
986 * an extension to be added to the filename when
987 * searching for the file. The first character of the
988 * filename extension must be a period (.). The
989 * extension is only added if the specified filename
990 * doesn't end with an extension
992 * If the filename extension is not required or if the
993 * filename contains an extension, this parameters can be
995 * nBufferLength = The length in characters of the buffer for output
996 * lpBuffer = Points to the buffer for the valid path and filename of
998 * lpFilePart = Points to the last component of the valid path and
1000 * RETURNS: On success, the length, in characters, of the string copied to the
1007 PWCHAR EnvironmentBufferW
= NULL
;
1008 PWCHAR AppPathW
= NULL
;
1014 DPRINT("SearchPath\n");
1016 HasExtension
= FALSE
;
1017 p
= lpFileName
+ wcslen(lpFileName
);
1018 while (lpFileName
< p
&&
1019 L
'\\' != *(p
- 1) &&
1023 HasExtension
= HasExtension
|| L
'.' == *(p
- 1);
1028 if (HasExtension
|| NULL
== lpExtension
)
1030 Name
= (PWCHAR
) lpFileName
;
1034 Name
= RtlAllocateHeap(GetProcessHeap(),
1035 HEAP_GENERATE_EXCEPTIONS
,
1036 (wcslen(lpFileName
) + wcslen(lpExtension
) + 1)
1040 SetLastError(ERROR_OUTOFMEMORY
);
1043 wcscat(wcscpy(Name
, lpFileName
), lpExtension
);
1045 if (RtlDoesFileExists_U(Name
))
1047 retCode
= RtlGetFullPathName_U (Name
,
1048 nBufferLength
* sizeof(WCHAR
),
1052 if (Name
!= lpFileName
)
1054 RtlFreeHeap(GetProcessHeap(), 0, Name
);
1062 AppPathW
= (PWCHAR
) RtlAllocateHeap(RtlGetProcessHeap(),
1063 HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,
1064 MAX_PATH
* sizeof(WCHAR
));
1065 if (AppPathW
== NULL
)
1067 SetLastError(ERROR_OUTOFMEMORY
);
1072 wcscat (AppPathW
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
);
1074 len
= wcslen (AppPathW
);
1076 while (len
&& AppPathW
[len
- 1] != L
'\\')
1079 if (len
) AppPathW
[len
-1] = L
'\0';
1081 len
= GetEnvironmentVariableW(L
"PATH", &Buffer
, 0);
1082 len
+= 1 + GetCurrentDirectoryW(0, &Buffer
);
1083 len
+= 1 + GetSystemDirectoryW(&Buffer
, 0);
1084 len
+= 1 + GetWindowsDirectoryW(&Buffer
, 0);
1085 len
+= 1 + wcslen(AppPathW
) * sizeof(WCHAR
);
1087 EnvironmentBufferW
= (PWCHAR
) RtlAllocateHeap(RtlGetProcessHeap(),
1088 HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,
1089 len
* sizeof(WCHAR
));
1090 if (EnvironmentBufferW
== NULL
)
1092 RtlFreeHeap(RtlGetProcessHeap(), 0, AppPathW
);
1093 SetLastError(ERROR_OUTOFMEMORY
);
1097 pos
= GetCurrentDirectoryW(len
, EnvironmentBufferW
);
1098 EnvironmentBufferW
[pos
++] = L
';';
1099 EnvironmentBufferW
[pos
] = 0;
1100 pos
+= GetSystemDirectoryW(&EnvironmentBufferW
[pos
], len
- pos
);
1101 EnvironmentBufferW
[pos
++] = L
';';
1102 EnvironmentBufferW
[pos
] = 0;
1103 pos
+= GetWindowsDirectoryW(&EnvironmentBufferW
[pos
], len
- pos
);
1104 EnvironmentBufferW
[pos
++] = L
';';
1105 EnvironmentBufferW
[pos
] = 0;
1106 pos
+= GetEnvironmentVariableW(L
"PATH", &EnvironmentBufferW
[pos
], len
- pos
);
1107 EnvironmentBufferW
[pos
++] = L
';';
1108 EnvironmentBufferW
[pos
] = 0;
1109 wcscat (EnvironmentBufferW
, AppPathW
);
1111 RtlFreeHeap (RtlGetProcessHeap (),
1115 lpPath
= EnvironmentBufferW
;
1119 retCode
= RtlDosSearchPath_U ((PWCHAR
)lpPath
, (PWCHAR
)lpFileName
, (PWCHAR
)lpExtension
,
1120 nBufferLength
* sizeof(WCHAR
), lpBuffer
, lpFilePart
);
1122 if (EnvironmentBufferW
!= NULL
)
1124 RtlFreeHeap(GetProcessHeap(), 0, EnvironmentBufferW
);
1128 SetLastError(ERROR_FILE_NOT_FOUND
);
1131 return retCode
/ sizeof(WCHAR
);
1143 UNICODE_STRING PathName
;
1145 RtlInitUnicodeString(&PathName
, lpPathName
);
1147 RtlEnterCriticalSection(&DllLock
);
1148 if(PathName
.Length
> 0)
1150 if(PathName
.Length
+ sizeof(WCHAR
) <= DllDirectory
.MaximumLength
)
1152 RtlCopyUnicodeString(&DllDirectory
, &PathName
);
1156 RtlFreeUnicodeString(&DllDirectory
);
1157 if(!(DllDirectory
.Buffer
= (PWSTR
)RtlAllocateHeap(RtlGetProcessHeap(),
1159 PathName
.Length
+ sizeof(WCHAR
))))
1161 RtlLeaveCriticalSection(&DllLock
);
1162 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1165 DllDirectory
.Length
= 0;
1166 DllDirectory
.MaximumLength
= PathName
.Length
+ sizeof(WCHAR
);
1168 RtlCopyUnicodeString(&DllDirectory
, &PathName
);
1173 RtlFreeUnicodeString(&DllDirectory
);
1175 RtlLeaveCriticalSection(&DllLock
);
1186 LPCSTR lpPathName
/* can be NULL */
1189 PWCHAR PathNameW
=NULL
;
1193 if (!(PathNameW
= FilenameA2W(lpPathName
, FALSE
)))
1197 return SetDllDirectoryW(PathNameW
);
1206 DWORD nBufferLength
,
1212 RtlEnterCriticalSection(&DllLock
);
1213 if(nBufferLength
> 0)
1215 Ret
= DllDirectory
.Length
/ sizeof(WCHAR
);
1216 if(Ret
> nBufferLength
- 1)
1218 Ret
= nBufferLength
- 1;
1223 RtlCopyMemory(lpBuffer
, DllDirectory
.Buffer
, Ret
* sizeof(WCHAR
));
1225 lpBuffer
[Ret
] = L
'\0';
1229 /* include termination character, even if the string is empty! */
1230 Ret
= (DllDirectory
.Length
/ sizeof(WCHAR
)) + 1;
1232 RtlLeaveCriticalSection(&DllLock
);
1243 DWORD nBufferLength
,
1247 WCHAR BufferW
[MAX_PATH
];
1250 ret
= GetDllDirectoryW(MAX_PATH
, BufferW
);
1257 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
1261 return FilenameW2A_FitOrFail(lpBuffer
, nBufferLength
, BufferW
, ret
+1);
1269 NeedCurrentDirectoryForExePathW(LPCWSTR ExeName
)
1271 return (wcschr(ExeName
,
1280 NeedCurrentDirectoryForExePathA(LPCSTR ExeName
)
1282 return (strchr(ExeName
,
1290 /***********************************************************************
1293 * GetLongPathNameW (KERNEL32.@)
1296 * observed (Win2000):
1297 * shortpath=NULL: LastError=ERROR_INVALID_PARAMETER, ret=0
1298 * shortpath="": LastError=ERROR_PATH_NOT_FOUND, ret=0
1300 DWORD STDCALL
GetLongPathNameW( LPCWSTR shortpath
, LPWSTR longpath
, DWORD longlen
)
1302 #define MAX_PATHNAME_LEN 1024
1304 WCHAR tmplongpath
[MAX_PATHNAME_LEN
];
1306 DWORD sp
= 0, lp
= 0;
1308 BOOL unixabsolute
= (shortpath
[0] == '/');
1309 WIN32_FIND_DATAW wfd
;
1314 SetLastError(ERROR_INVALID_PARAMETER
);
1319 SetLastError(ERROR_PATH_NOT_FOUND
);
1323 DPRINT("GetLongPathNameW(%s,%p,%ld)\n", shortpath
, longpath
, longlen
);
1325 if (shortpath
[0] == '\\' && shortpath
[1] == '\\')
1327 DPRINT1("ERR: UNC pathname %s\n", shortpath
);
1328 lstrcpynW( longpath
, shortpath
, longlen
);
1329 return wcslen(longpath
);
1332 /* check for drive letter */
1333 if (!unixabsolute
&& shortpath
[1] == ':' )
1335 tmplongpath
[0] = shortpath
[0];
1336 tmplongpath
[1] = ':';
1340 while (shortpath
[sp
])
1342 /* check for path delimiters and reproduce them */
1343 if (shortpath
[sp
] == '\\' || shortpath
[sp
] == '/')
1345 if (!lp
|| tmplongpath
[lp
-1] != '\\')
1347 /* strip double "\\" */
1348 tmplongpath
[lp
++] = '\\';
1350 tmplongpath
[lp
] = 0; /* terminate string */
1356 if (sp
== 0 && p
[0] == '.' && (p
[1] == '/' || p
[1] == '\\'))
1358 tmplongpath
[lp
++] = *p
++;
1359 tmplongpath
[lp
++] = *p
++;
1361 for (; *p
&& *p
!= '/' && *p
!= '\\'; p
++);
1362 tmplen
= p
- (shortpath
+ sp
);
1363 lstrcpynW(tmplongpath
+ lp
, shortpath
+ sp
, tmplen
+ 1);
1364 /* Check if the file exists and use the existing file name */
1365 goit
= FindFirstFileW(tmplongpath
, &wfd
);
1366 if (goit
== INVALID_HANDLE_VALUE
)
1368 DPRINT("not found %s!\n", tmplongpath
);
1369 SetLastError ( ERROR_FILE_NOT_FOUND
);
1373 wcscpy(tmplongpath
+ lp
, wfd
.cFileName
);
1374 lp
+= wcslen(tmplongpath
+ lp
);
1377 tmplen
= wcslen(shortpath
) - 1;
1378 if ((shortpath
[tmplen
] == '/' || shortpath
[tmplen
] == '\\') &&
1379 (tmplongpath
[lp
- 1] != '/' && tmplongpath
[lp
- 1] != '\\'))
1380 tmplongpath
[lp
++] = shortpath
[tmplen
];
1381 tmplongpath
[lp
] = 0;
1383 tmplen
= wcslen(tmplongpath
) + 1;
1384 if (tmplen
<= longlen
)
1386 wcscpy(longpath
, tmplongpath
);
1387 DPRINT("returning %s\n", longpath
);
1388 tmplen
--; /* length without 0 */
1396 /***********************************************************************
1397 * GetLongPathNameA (KERNEL32.@)
1399 DWORD STDCALL
GetLongPathNameA( LPCSTR shortpath
, LPSTR longpath
, DWORD longlen
)
1402 WCHAR longpathW
[MAX_PATH
];
1405 DPRINT("GetLongPathNameA %s, %i\n",shortpath
,longlen
);
1407 if (!(shortpathW
= FilenameA2W( shortpath
, FALSE
)))
1410 ret
= GetLongPathNameW(shortpathW
, longpathW
, MAX_PATH
);
1415 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
1419 return FilenameW2A_FitOrFail(longpath
, longlen
, longpathW
, ret
+1 );