1 /* $Id: dir.c,v 1.48 2004/08/18 02:13:27 navaraf Exp $
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"
24 /* FUNCTIONS *****************************************************************/
33 LPSECURITY_ATTRIBUTES lpSecurityAttributes
36 return CreateDirectoryExA (NULL
,
38 lpSecurityAttributes
);
48 LPCSTR lpTemplateDirectory
,
49 LPCSTR lpNewDirectory
,
50 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
52 UNICODE_STRING TmplDirU
;
53 UNICODE_STRING NewDirU
;
58 RtlInitUnicodeString (&TmplDirU
,
61 RtlInitUnicodeString (&NewDirU
,
64 if (lpTemplateDirectory
!= NULL
)
66 RtlInitAnsiString (&TmplDir
,
67 (LPSTR
)lpTemplateDirectory
);
69 /* convert ansi (or oem) string to unicode */
71 RtlAnsiStringToUnicodeString (&TmplDirU
,
75 RtlOemStringToUnicodeString (&TmplDirU
,
80 if (lpNewDirectory
!= NULL
)
82 RtlInitAnsiString (&NewDir
,
83 (LPSTR
)lpNewDirectory
);
85 /* convert ansi (or oem) string to unicode */
87 RtlAnsiStringToUnicodeString (&NewDirU
,
91 RtlOemStringToUnicodeString (&NewDirU
,
96 Result
= CreateDirectoryExW (TmplDirU
.Buffer
,
98 lpSecurityAttributes
);
100 if (lpTemplateDirectory
!= NULL
)
101 RtlFreeHeap (RtlGetProcessHeap (),
105 if (lpNewDirectory
!= NULL
)
106 RtlFreeHeap (RtlGetProcessHeap (),
121 LPSECURITY_ATTRIBUTES lpSecurityAttributes
124 return CreateDirectoryExW (NULL
,
126 lpSecurityAttributes
);
136 LPCWSTR lpTemplateDirectory
,
137 LPCWSTR lpNewDirectory
,
138 LPSECURITY_ATTRIBUTES lpSecurityAttributes
141 OBJECT_ATTRIBUTES ObjectAttributes
;
142 IO_STATUS_BLOCK IoStatusBlock
;
143 UNICODE_STRING NtPathU
;
144 HANDLE DirectoryHandle
;
147 DPRINT ("lpTemplateDirectory %S lpNewDirectory %S lpSecurityAttributes %p\n",
148 lpTemplateDirectory
, lpNewDirectory
, lpSecurityAttributes
);
150 // Can't create empty directory
151 if(lpNewDirectory
== NULL
|| *lpNewDirectory
== 0)
153 SetLastError(ERROR_PATH_NOT_FOUND
);
157 if (lpTemplateDirectory
!= NULL
&& *lpTemplateDirectory
!= 0)
159 // get object attributes from template directory
160 DPRINT("KERNEL32:FIXME:%s:%d\n",__FILE__
,__LINE__
);
164 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpNewDirectory
,
170 DPRINT ("NtPathU \'%wZ\'\n", &NtPathU
);
172 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
173 ObjectAttributes
.RootDirectory
= NULL
;
174 ObjectAttributes
.ObjectName
= &NtPathU
;
175 ObjectAttributes
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
;
176 ObjectAttributes
.SecurityDescriptor
= NULL
;
177 ObjectAttributes
.SecurityQualityOfService
= NULL
;
179 Status
= NtCreateFile (&DirectoryHandle
,
180 DIRECTORY_ALL_ACCESS
,
184 FILE_ATTRIBUTE_DIRECTORY
,
190 DPRINT("Status: %lx\n", Status
);
192 RtlFreeHeap (RtlGetProcessHeap (),
196 if (!NT_SUCCESS(Status
))
198 SetLastErrorByStatus(Status
);
202 NtClose (DirectoryHandle
);
217 UNICODE_STRING PathNameU
;
218 ANSI_STRING PathName
;
221 RtlInitAnsiString (&PathName
,
224 /* convert ansi (or oem) string to unicode */
226 RtlAnsiStringToUnicodeString (&PathNameU
,
230 RtlOemStringToUnicodeString (&PathNameU
,
234 Result
= RemoveDirectoryW (PathNameU
.Buffer
);
236 RtlFreeHeap (RtlGetProcessHeap (),
253 FILE_DISPOSITION_INFORMATION FileDispInfo
;
254 OBJECT_ATTRIBUTES ObjectAttributes
;
255 IO_STATUS_BLOCK IoStatusBlock
;
256 UNICODE_STRING NtPathU
;
257 HANDLE DirectoryHandle
;
260 DPRINT("lpPathName %S\n", lpPathName
);
262 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpPathName
,
268 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
269 ObjectAttributes
.RootDirectory
= NULL
;
270 ObjectAttributes
.ObjectName
= &NtPathU
;
271 ObjectAttributes
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
;
272 ObjectAttributes
.SecurityDescriptor
= NULL
;
273 ObjectAttributes
.SecurityQualityOfService
= NULL
;
275 DPRINT("NtPathU '%S'\n", NtPathU
.Buffer
);
277 Status
= NtCreateFile (&DirectoryHandle
,
278 FILE_WRITE_ATTRIBUTES
, /* 0x110080 */
282 FILE_ATTRIBUTE_DIRECTORY
, /* 0x7 */
285 FILE_DIRECTORY_FILE
, /* 0x204021 */
289 RtlFreeHeap (RtlGetProcessHeap (),
293 if (!NT_SUCCESS(Status
))
296 SetLastErrorByStatus (Status
);
300 FileDispInfo
.DeleteFile
= TRUE
;
302 Status
= NtSetInformationFile (DirectoryHandle
,
305 sizeof(FILE_DISPOSITION_INFORMATION
),
306 FileDispositionInformation
);
307 if (!NT_SUCCESS(Status
))
310 NtClose(DirectoryHandle
);
311 SetLastErrorByStatus (Status
);
315 Status
= NtClose (DirectoryHandle
);
316 if (!NT_SUCCESS(Status
))
319 SetLastErrorByStatus (Status
);
339 UNICODE_STRING nameW
;
340 WCHAR bufferW
[MAX_PATH
];
342 LPWSTR FilePart
= NULL
;
344 DPRINT("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, "
345 "lpFilePart %p)\n",lpFileName
,nBufferLength
,lpBuffer
,lpFilePart
);
349 SetLastError(ERROR_INVALID_PARAMETER
);
353 if (!RtlCreateUnicodeStringFromAsciiz(&nameW
, (LPSTR
)lpFileName
))
355 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
364 retW
= GetFullPathNameW(nameW
.Buffer
, MAX_PATH
, bufferW
, &FilePart
);
370 else if (retW
> MAX_PATH
)
372 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
377 ANSI_STRING AnsiBuffer
;
378 UNICODE_STRING UnicodeBuffer
;
380 UnicodeBuffer
.Length
= wcslen(bufferW
) * sizeof(WCHAR
);
382 if (nameW
.Length
<= nBufferLength
)
384 UnicodeBuffer
.Buffer
= bufferW
;
385 AnsiBuffer
.MaximumLength
= nBufferLength
;
386 AnsiBuffer
.Length
= 0;
387 AnsiBuffer
.Buffer
= lpBuffer
;
388 RtlUnicodeStringToAnsiString(&AnsiBuffer
, &UnicodeBuffer
, FALSE
);
390 if (lpFilePart
&& FilePart
!= NULL
)
392 *lpFilePart
= (FilePart
- bufferW
) + lpBuffer
;
397 RtlFreeUnicodeString(&nameW
);
399 DPRINT("lpBuffer %s lpFilePart %s Length %ld\n",
400 lpBuffer
, (lpFilePart
== NULL
) ? "NULL" : *lpFilePart
, nameW
.Length
);
420 DPRINT("GetFullPathNameW(lpFileName %S, nBufferLength %d, lpBuffer %p, "
421 "lpFilePart %p)\n",lpFileName
,nBufferLength
,lpBuffer
,lpFilePart
);
423 Length
= RtlGetFullPathName_U ((LPWSTR
)lpFileName
,
424 nBufferLength
* sizeof(WCHAR
),
428 DPRINT("lpBuffer %S lpFilePart %S Length %ld\n",
429 lpBuffer
, (lpFilePart
== NULL
) ? L
"NULL" : *lpFilePart
, Length
/ sizeof(WCHAR
));
431 return (Length
/ sizeof(WCHAR
));
436 * NOTE: Copied from Wine.
447 UNICODE_STRING longpathW
;
448 WCHAR shortpathW
[MAX_PATH
];
453 SetLastError(ERROR_INVALID_PARAMETER
);
457 if (!RtlCreateUnicodeStringFromAsciiz(&longpathW
, longpath
))
459 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
463 retW
= GetShortPathNameW(longpathW
.Buffer
, shortpathW
, MAX_PATH
);
467 else if (retW
> PATH_MAX
)
469 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
474 ret
= WideCharToMultiByte(CP_ACP
, 0, shortpathW
, -1, NULL
, 0, NULL
, NULL
);
477 WideCharToMultiByte(CP_ACP
, 0, shortpathW
, -1, shortpath
, shortlen
, NULL
, NULL
);
478 ret
--; /* length without 0 */
482 RtlFreeUnicodeString(&longpathW
);
488 * NOTE: Copied from Wine.
499 WCHAR tmpshortpath
[PATH_MAX
];
501 DWORD sp
= 0, lp
= 0;
503 WIN32_FIND_DATAW wfd
;
506 WCHAR ustr_buf
[8+1+3+1];
510 SetLastError(ERROR_INVALID_PARAMETER
);
515 SetLastError(ERROR_BAD_PATHNAME
);
519 /* check for drive letter */
520 if (longpath
[1] == ':' )
522 tmpshortpath
[0] = longpath
[0];
523 tmpshortpath
[1] = ':';
527 ustr
.Buffer
= ustr_buf
;
529 ustr
.MaximumLength
= sizeof(ustr_buf
);
533 /* check for path delimiters and reproduce them */
534 if (longpath
[lp
] == '\\' || longpath
[lp
] == '/')
536 if (!sp
|| tmpshortpath
[sp
-1] != '\\')
538 /* strip double "\\" */
539 tmpshortpath
[sp
] = '\\';
542 tmpshortpath
[sp
] = 0; /* terminate string */
547 for (p
= longpath
+ lp
; *p
&& *p
!= '/' && *p
!= '\\'; p
++);
548 tmplen
= p
- (longpath
+ lp
);
549 lstrcpynW(tmpshortpath
+ sp
, longpath
+ lp
, tmplen
+ 1);
550 /* Check, if the current element is a valid dos name */
551 if (tmplen
<= 8+1+3+1)
554 memcpy(ustr_buf
, longpath
+ lp
, tmplen
* sizeof(WCHAR
));
555 ustr_buf
[tmplen
] = '\0';
556 ustr
.Length
= tmplen
* sizeof(WCHAR
);
557 if (RtlIsNameLegalDOS8Dot3(&ustr
, NULL
, &spaces
) && !spaces
)
565 /* Check if the file exists and use the existing short file name */
566 goit
= FindFirstFileW(tmpshortpath
, &wfd
);
567 if (goit
== INVALID_HANDLE_VALUE
) goto notfound
;
569 lstrcpyW(tmpshortpath
+ sp
, wfd
.cAlternateFileName
);
570 sp
+= lstrlenW(tmpshortpath
+ sp
);
573 tmpshortpath
[sp
] = 0;
575 tmplen
= lstrlenW(tmpshortpath
) + 1;
576 if (tmplen
<= shortlen
)
578 lstrcpyW(shortpath
, tmpshortpath
);
579 tmplen
--; /* length without 0 */
585 SetLastError ( ERROR_FILE_NOT_FOUND
);
604 UNICODE_STRING PathU
;
605 UNICODE_STRING FileNameU
;
606 UNICODE_STRING ExtensionU
;
607 UNICODE_STRING BufferU
;
609 ANSI_STRING FileName
;
610 ANSI_STRING Extension
;
615 RtlInitAnsiString (&Path
,
617 RtlInitAnsiString (&FileName
,
619 RtlInitAnsiString (&Extension
,
622 /* convert ansi (or oem) strings to unicode */
625 RtlAnsiStringToUnicodeString (&PathU
,
628 RtlAnsiStringToUnicodeString (&FileNameU
,
631 RtlAnsiStringToUnicodeString (&ExtensionU
,
637 RtlOemStringToUnicodeString (&PathU
,
640 RtlOemStringToUnicodeString (&FileNameU
,
643 RtlOemStringToUnicodeString (&ExtensionU
,
649 BufferU
.MaximumLength
= nBufferLength
* sizeof(WCHAR
);
650 BufferU
.Buffer
= RtlAllocateHeap (RtlGetProcessHeap (),
652 BufferU
.MaximumLength
);
655 Buffer
.MaximumLength
= nBufferLength
;
656 Buffer
.Buffer
= lpBuffer
;
658 RetValue
= SearchPathW (NULL
== lpPath
? NULL
: PathU
.Buffer
,
659 NULL
== lpFileName
? NULL
: FileNameU
.Buffer
,
660 NULL
== lpExtension
? NULL
: ExtensionU
.Buffer
,
665 RtlFreeHeap (RtlGetProcessHeap (),
668 RtlFreeHeap (RtlGetProcessHeap (),
671 RtlFreeHeap (RtlGetProcessHeap (),
677 BufferU
.Length
= wcslen(BufferU
.Buffer
) * sizeof(WCHAR
);
678 /* convert ansi (or oem) string to unicode */
680 RtlUnicodeStringToAnsiString (&Buffer
,
684 RtlUnicodeStringToOemString (&Buffer
,
687 /* nul-terminate ascii string */
688 Buffer
.Buffer
[BufferU
.Length
/ sizeof(WCHAR
)] = '\0';
691 RtlFreeHeap (RtlGetProcessHeap (),
695 if (NULL
!= lpFilePart
)
697 *lpFilePart
= strrchr (lpBuffer
, '\\') + 1;
718 * FUNCTION: Searches for the specified file
720 * lpPath = Points to a null-terminated string that specified the
721 * path to be searched. If this parameters is NULL then
722 * the following directories are searched
723 * The directory from which the application loaded
724 * The current directory
725 * The system directory
726 * The 16-bit system directory
727 * The windows directory
728 * The directories listed in the PATH environment
730 * lpFileName = Specifies the filename to search for
731 * lpExtension = Points to the null-terminated string that specifies
732 * an extension to be added to the filename when
733 * searching for the file. The first character of the
734 * filename extension must be a period (.). The
735 * extension is only added if the specified filename
736 * doesn't end with an extension
738 * If the filename extension is not required or if the
739 * filename contains an extension, this parameters can be
741 * nBufferLength = The length in characters of the buffer for output
742 * lpBuffer = Points to the buffer for the valid path and filename of
744 * lpFilePart = Points to the last component of the valid path and
746 * RETURNS: On success, the length, in characters, of the string copied to the
753 PWCHAR EnvironmentBufferW
= NULL
;
754 PWCHAR AppPathW
= NULL
;
760 DPRINT("SearchPath\n");
762 HasExtension
= FALSE
;
763 p
= lpFileName
+ wcslen(lpFileName
);
764 while (lpFileName
< p
&&
769 HasExtension
= HasExtension
|| L
'.' == *(p
- 1);
774 if (HasExtension
|| NULL
== lpExtension
)
776 Name
= (PWCHAR
) lpFileName
;
780 Name
= RtlAllocateHeap(GetProcessHeap(),
781 HEAP_GENERATE_EXCEPTIONS
,
782 (wcslen(lpFileName
) + wcslen(lpExtension
) + 1)
786 SetLastError(ERROR_OUTOFMEMORY
);
789 wcscat(wcscpy(Name
, lpFileName
), lpExtension
);
791 if (RtlDoesFileExists_U(Name
))
793 retCode
= RtlGetFullPathName_U (Name
,
794 nBufferLength
* sizeof(WCHAR
),
798 if (Name
!= lpFileName
)
800 RtlFreeHeap(GetProcessHeap(), 0, Name
);
808 AppPathW
= (PWCHAR
) RtlAllocateHeap(GetProcessHeap(),
809 HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,
810 MAX_PATH
* sizeof(WCHAR
));
813 wcscat (AppPathW
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
);
815 len
= wcslen (AppPathW
);
817 while (len
&& AppPathW
[len
- 1] != L
'\\')
820 if (len
) AppPathW
[len
-1] = L
'\0';
822 len
= GetEnvironmentVariableW(L
"PATH", &Buffer
, 0);
823 len
+= 1 + GetCurrentDirectoryW(0, &Buffer
);
824 len
+= 1 + GetSystemDirectoryW(&Buffer
, 0);
825 len
+= 1 + GetWindowsDirectoryW(&Buffer
, 0);
826 len
+= 1 + wcslen(AppPathW
) * sizeof(WCHAR
);
828 EnvironmentBufferW
= (PWCHAR
) RtlAllocateHeap(GetProcessHeap(),
829 HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,
830 len
* sizeof(WCHAR
));
831 if (EnvironmentBufferW
== NULL
)
833 SetLastError(ERROR_OUTOFMEMORY
);
837 pos
= GetCurrentDirectoryW(len
, EnvironmentBufferW
);
838 EnvironmentBufferW
[pos
++] = L
';';
839 EnvironmentBufferW
[pos
] = 0;
840 pos
+= GetSystemDirectoryW(&EnvironmentBufferW
[pos
], len
- pos
);
841 EnvironmentBufferW
[pos
++] = L
';';
842 EnvironmentBufferW
[pos
] = 0;
843 pos
+= GetWindowsDirectoryW(&EnvironmentBufferW
[pos
], len
- pos
);
844 EnvironmentBufferW
[pos
++] = L
';';
845 EnvironmentBufferW
[pos
] = 0;
846 pos
+= GetEnvironmentVariableW(L
"PATH", &EnvironmentBufferW
[pos
], len
- pos
);
847 EnvironmentBufferW
[pos
++] = L
';';
848 EnvironmentBufferW
[pos
] = 0;
849 wcscat (EnvironmentBufferW
, AppPathW
);
851 RtlFreeHeap (RtlGetProcessHeap (),
855 lpPath
= EnvironmentBufferW
;
859 retCode
= RtlDosSearchPath_U ((PWCHAR
)lpPath
, (PWCHAR
)lpFileName
, (PWCHAR
)lpExtension
,
860 nBufferLength
* sizeof(WCHAR
), lpBuffer
, lpFilePart
);
862 if (EnvironmentBufferW
!= NULL
)
864 RtlFreeHeap(GetProcessHeap(), 0, EnvironmentBufferW
);
868 SetLastError(ERROR_FILE_NOT_FOUND
);
871 return retCode
/ sizeof(WCHAR
);