From cb05e516a2f83fb87cbf0984c83b07ce115dec18 Mon Sep 17 00:00:00 2001 From: Gunnar Dalsnes Date: Tue, 15 Mar 2005 19:40:22 +0000 Subject: [PATCH] fixed GetTempFileNameA/W by ripping from wine impl. GetLongPathNameA/W by ripping from wine impl. EnumResourceNamesA/W by ripping from wine Use common routines for filename A2W/W2A conversion (wine inspired) impl. ReadDirectoryChangesW (kmode part is not workin yet) fixed RtlSetCurrentDirectory_U (dont convert to long path) svn path=/trunk/; revision=14101 --- reactos/include/ddk/ldrfuncs.h | 6 +- reactos/lib/kernel32/file/cnotify.c | 133 +++++-- reactos/lib/kernel32/file/curdir.c | 328 ++++------------ reactos/lib/kernel32/file/dir.c | 494 ++++++++++++------------ reactos/lib/kernel32/file/file.c | 463 +++++++++++++--------- reactos/lib/kernel32/file/hardlink.c | 35 +- reactos/lib/kernel32/file/volume.c | 194 +++------- reactos/lib/kernel32/include/kernel32.h | 11 + reactos/lib/kernel32/misc/dllmain.c | 18 +- reactos/lib/kernel32/misc/res.c | 186 +++++++-- reactos/lib/kernel32/misc/stubs.c | 51 +-- reactos/lib/ntdll/ldr/res.c | 7 +- reactos/lib/ntdll/rtl/path.c | 230 +++++------ 13 files changed, 1039 insertions(+), 1117 deletions(-) diff --git a/reactos/include/ddk/ldrfuncs.h b/reactos/include/ddk/ldrfuncs.h index 64b896f62be..14e3fc2caed 100644 --- a/reactos/include/ddk/ldrfuncs.h +++ b/reactos/include/ddk/ldrfuncs.h @@ -14,12 +14,12 @@ LdrFindResource_U(IN PVOID BaseAddress, IN ULONG Level, OUT PIMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry); -/*NTSTATUS STDCALL +NTSTATUS STDCALL LdrFindResourceDirectory_U( IN PVOID BaseAddress, - IN PLDR_RESOURCE_INFO ResourceInfo, + IN PLDR_RESOURCE_INFO ResourceInfo, IN ULONG Level, OUT PIMAGE_RESOURCE_DIRECTORY *ResourceDirectory); -*/ + NTSTATUS STDCALL LdrEnumResources(IN PVOID BaseAddress, IN PLDR_RESOURCE_INFO ResourceInfo, diff --git a/reactos/lib/kernel32/file/cnotify.c b/reactos/lib/kernel32/file/cnotify.c index 9512418dc1a..2d9b45047e5 100644 --- a/reactos/lib/kernel32/file/cnotify.c +++ b/reactos/lib/kernel32/file/cnotify.c @@ -42,34 +42,14 @@ FindFirstChangeNotificationA ( DWORD dwNotifyFilter ) { - UNICODE_STRING PathNameU; - ANSI_STRING PathName; - HANDLE hNotify; + PWCHAR PathNameW; - RtlInitAnsiString (&PathName, - (LPSTR)lpPathName); + if (!(PathNameW = FilenameA2W(lpPathName, FALSE))) + return INVALID_HANDLE_VALUE; - /* convert ansi (or oem) string to unicode */ - if (bIsFileApiAnsi) - { - RtlAnsiStringToUnicodeString (&PathNameU, - &PathName, - TRUE); - } - else - { - RtlOemStringToUnicodeString (&PathNameU, - &PathName, - TRUE); - } - - hNotify = FindFirstChangeNotificationW (PathNameU.Buffer, + return FindFirstChangeNotificationW (PathNameW , bWatchSubtree, dwNotifyFilter); - - RtlFreeUnicodeString(&PathNameU); - - return hNotify; } @@ -90,13 +70,6 @@ FindFirstChangeNotificationW ( OBJECT_ATTRIBUTES ObjectAttributes; HANDLE hDir; - /* - RtlDosPathNameToNtPathName takes a fully qualified file name "C:\Projects\LoadLibrary\Debug\TestDll.dll" - and returns something like "\??\C:\Projects\LoadLibrary\Debug\TestDll.dll." - If the file name cannot be interpreted, then the routine returns STATUS_OBJECT_PATH_SYNTAX_BAD and - ends execution. - */ - if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpPathName, &NtPathU, NULL, @@ -106,9 +79,11 @@ FindFirstChangeNotificationW ( return INVALID_HANDLE_VALUE; } + + InitializeObjectAttributes (&ObjectAttributes, &NtPathU, - 0, + OBJ_CASE_INSENSITIVE, NULL, NULL); @@ -119,6 +94,23 @@ FindFirstChangeNotificationW ( FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_DIRECTORY_FILE); + /* + FIXME: I think we should use FILE_OPEN_FOR_BACKUP_INTENT. See M$ Q188321 + -Gunnar + */ + + + + /* FIXME: We free the string alloced by RtlDosPathNameToNtPathName_U, but what + * about the special case where the user can pass a \\?\ path? We must not free + * the users buffer!. But should we even call RtlDosPathNameToNtPathName_U in that + * case??? -Gunnar + */ + + RtlFreeUnicodeString( &NtPathU); + + + if (!NT_SUCCESS(Status)) { SetLastErrorByStatus(Status); @@ -157,15 +149,16 @@ FindNextChangeNotification ( NTSTATUS Status; Status = NtNotifyChangeDirectoryFile(hChangeHandle, - NULL, - NULL, - NULL, - &IoStatus, - NULL,//Buffer, - 0,//BufferLength, - FILE_NOTIFY_CHANGE_SECURITY,//meaningless for subsequent calls, but must contain a valid flag(s) - 0//meaningless for subsequent calls - ); + NULL, + NULL, + NULL, + &IoStatus, + NULL,//Buffer, + 0,//BufferLength, + FILE_NOTIFY_CHANGE_SECURITY,//meaningless/ignored for subsequent calls, but must contain a valid flag + 0 //meaningless/ignored for subsequent calls + ); + if (!NT_SUCCESS(Status)) { SetLastErrorByStatus(Status); @@ -175,4 +168,62 @@ FindNextChangeNotification ( return TRUE; } + +extern VOID STDCALL +(ApcRoutine)(PVOID ApcContext, + struct _IO_STATUS_BLOCK* IoStatusBlock, + ULONG Reserved); + + +/* + * @implemented + */ +BOOL +STDCALL +ReadDirectoryChangesW( + HANDLE hDirectory, + LPVOID lpBuffer OPTIONAL, + DWORD nBufferLength, + BOOL bWatchSubtree, + DWORD dwNotifyFilter, + LPDWORD lpBytesReturned, /* undefined for asych. operations */ + LPOVERLAPPED lpOverlapped OPTIONAL, + LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine /* OPTIONAL???????? */ + ) +{ + NTSTATUS Status; + IO_STATUS_BLOCK IoStatus; + + if (lpOverlapped ) + lpOverlapped->Internal = STATUS_PENDING; + + Status = NtNotifyChangeDirectoryFile( + hDirectory, + lpOverlapped ? lpOverlapped->hEvent : NULL, + lpCompletionRoutine ? ApcRoutine : NULL, /* ApcRoutine OPTIONAL???? */ + lpCompletionRoutine, /* ApcContext */ + lpOverlapped ? (PIO_STATUS_BLOCK)lpOverlapped : &IoStatus, + lpBuffer, + nBufferLength, + dwNotifyFilter, + bWatchSubtree + ); + + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + + /* NOTE: lpBytesReturned is undefined for asynch. operations */ + *lpBytesReturned = IoStatus.Information; + + return TRUE; +} + + + + + /* EOF */ diff --git a/reactos/lib/kernel32/file/curdir.c b/reactos/lib/kernel32/file/curdir.c index 1084bd4359c..f2eddf00f46 100644 --- a/reactos/lib/kernel32/file/curdir.c +++ b/reactos/lib/kernel32/file/curdir.c @@ -25,6 +25,9 @@ UNICODE_STRING WindowsDirectory; /* FUNCTIONS *****************************************************************/ + + + /* * @implemented */ @@ -35,71 +38,19 @@ GetCurrentDirectoryA ( LPSTR lpBuffer ) { - ANSI_STRING AnsiString; - UNICODE_STRING UnicodeString; - ULONG Length; + WCHAR BufferW[MAX_PATH]; + DWORD ret; - /* allocate buffer for unicode string */ - UnicodeString.Length = 0; - UnicodeString.MaximumLength = nBufferLength * sizeof(WCHAR); - if (nBufferLength > 0) - { - UnicodeString.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), - 0, - UnicodeString.MaximumLength); + ret = GetCurrentDirectoryW(MAX_PATH, BufferW); - /* initialize ansi string */ - AnsiString.Length = 0; - AnsiString.MaximumLength = nBufferLength; - AnsiString.Buffer = lpBuffer; - } - else - { - UnicodeString.Buffer = NULL; - } - - /* get current directory */ - UnicodeString.Length = RtlGetCurrentDirectory_U (UnicodeString.MaximumLength, - UnicodeString.Buffer); - DPRINT("UnicodeString.Buffer %wZ\n", &UnicodeString); - - /* convert unicode string to ansi (or oem) */ - if (bIsFileApiAnsi) - { - Length = RtlUnicodeStringToAnsiSize (&UnicodeString); - if (Length > nBufferLength) - { - RtlFreeHeap (RtlGetProcessHeap (), - 0, - UnicodeString.Buffer); - return Length-1; - } - RtlUnicodeStringToAnsiString (&AnsiString, - &UnicodeString, - FALSE); - } - else - { - Length = RtlUnicodeStringToOemSize (&UnicodeString); - if (Length > nBufferLength) - { - RtlFreeHeap (RtlGetProcessHeap (), - 0, - UnicodeString.Buffer); - return Length-1; - } - RtlUnicodeStringToOemString (&AnsiString, - &UnicodeString, - FALSE); - } - DPRINT("AnsiString.Buffer %s\n", AnsiString.Buffer); - - /* free unicode string */ - RtlFreeHeap (RtlGetProcessHeap (), - 0, - UnicodeString.Buffer); - - return AnsiString.Length; + if (!ret) return 0; + if (ret > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } + + return FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1); } @@ -122,6 +73,7 @@ GetCurrentDirectoryW ( } + /* * @implemented */ @@ -131,26 +83,15 @@ SetCurrentDirectoryA ( LPCSTR lpPathName ) { - ANSI_STRING AnsiString; - UNICODE_STRING UnicodeString; + PUNICODE_STRING PathNameU; NTSTATUS Status; - RtlInitAnsiString (&AnsiString, - (LPSTR)lpPathName); + DPRINT("setcurrdir: %s\n",lpPathName); - /* convert ansi (or oem) to unicode */ - if (bIsFileApiAnsi) - RtlAnsiStringToUnicodeString (&UnicodeString, - &AnsiString, - TRUE); - else - RtlOemStringToUnicodeString (&UnicodeString, - &AnsiString, - TRUE); + if (!(PathNameU = FilenameA2U(lpPathName, FALSE))) + return FALSE; - Status = RtlSetCurrentDirectory_U (&UnicodeString); - - RtlFreeUnicodeString (&UnicodeString); + Status = RtlSetCurrentDirectory_U(PathNameU); if (!NT_SUCCESS(Status)) { @@ -190,6 +131,8 @@ SetCurrentDirectoryW ( /* * @implemented + * + * NOTE: Windows returns a dos/short (8.3) path */ DWORD STDCALL @@ -198,138 +141,82 @@ GetTempPathA ( LPSTR lpBuffer ) { - UNICODE_STRING UnicodeString; - ANSI_STRING AnsiString; - DWORD Length; + WCHAR BufferW[MAX_PATH]; + DWORD ret; - AnsiString.Length = 0; - AnsiString.MaximumLength = nBufferLength; - AnsiString.Buffer = lpBuffer; + ret = GetTempPathW(MAX_PATH, BufferW); - /* initialize allocate unicode string */ - UnicodeString.Length = 0; - if(nBufferLength > 0) - { - UnicodeString.MaximumLength = (nBufferLength + 1) * sizeof(WCHAR); - UnicodeString.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), - 0, - UnicodeString.MaximumLength); - if (UnicodeString.Buffer == NULL) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - } - else - { - UnicodeString.MaximumLength = 0; - UnicodeString.Buffer = NULL; - } + if (!ret) + return 0; - Length = GetTempPathW (nBufferLength, - UnicodeString.Buffer); + if (ret > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } - if (nBufferLength >= Length) - { - /* only touch the buffer if the supplied buffer length is at least - the length that GetTempPathW returned! */ - UnicodeString.Length = Length * sizeof(WCHAR); - - /* convert unicode string to ansi (or oem) */ - if (bIsFileApiAnsi) - RtlUnicodeStringToAnsiString (&AnsiString, - &UnicodeString, - FALSE); - else - RtlUnicodeStringToOemString (&AnsiString, - &UnicodeString, - FALSE); - } - - /* free unicode string buffer */ - RtlFreeHeap (RtlGetProcessHeap (), - 0, - UnicodeString.Buffer); - - return Length; + return FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1); } /* * @implemented + * + * ripped from wine */ DWORD STDCALL GetTempPathW ( - DWORD nBufferLength, - LPWSTR lpBuffer + DWORD count, + LPWSTR path ) { - UNICODE_STRING Name; - PUNICODE_STRING Value; - PTEB Teb; - DWORD Length; - NTSTATUS Status; + WCHAR tmp_path[MAX_PATH]; + WCHAR tmp_full_path[MAX_PATH]; + UINT ret; - Teb = NtCurrentTeb(); - Teb->StaticUnicodeString.Length = 0; - Teb->StaticUnicodeString.MaximumLength = MAX_PATH * sizeof(WCHAR); - Teb->StaticUnicodeString.Buffer = Teb->StaticUnicodeBuffer; - Value = &Teb->StaticUnicodeString; + DPRINT("GetTempPathW(%lu,%p)\n", nBufferLength, lpBuffer); - RtlRosInitUnicodeStringFromLiteral (&Name, - L"TMP"); + if (!(ret = GetEnvironmentVariableW( L"TMP", tmp_path, MAX_PATH ))) + if (!(ret = GetEnvironmentVariableW( L"TEMP", tmp_path, MAX_PATH ))) + if (!(ret = GetCurrentDirectoryW( MAX_PATH, tmp_path ))) + return 0; - Status = RtlQueryEnvironmentVariable_U (NULL, - &Name, - Value); - if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) - { - RtlRosInitUnicodeStringFromLiteral (&Name, - L"TEMP"); + if (ret > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } - Status = RtlQueryEnvironmentVariable_U (NULL, - &Name, - Value); - if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) - { - Value->Length = RtlGetCurrentDirectory_U(Value->MaximumLength, - Value->Buffer); - } - } + ret = GetFullPathNameW(tmp_path, MAX_PATH, tmp_full_path, NULL); + if (!ret) return 0; - if (!NT_SUCCESS(Status)) - { - SetLastError(RtlNtStatusToDosError(Status)); - return 0; - } + if (ret > MAX_PATH - 2) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } - Length = Value->Length / sizeof(WCHAR) + 1; - if (nBufferLength < Value->Length / sizeof(WCHAR) + 2) - Length++; + if (tmp_full_path[ret-1] != '\\') + { + tmp_full_path[ret++] = '\\'; + tmp_full_path[ret] = '\0'; + } - if (nBufferLength >= Value->Length /sizeof(WCHAR) + 1) - { - if (nBufferLength < Value->Length / sizeof(WCHAR) + 2) - { - memcpy (lpBuffer, - Value->Buffer, - nBufferLength * sizeof(WCHAR)); - } - else - { - memcpy (lpBuffer, - Value->Buffer, - Value->Length); - lpBuffer[Value->Length / sizeof(WCHAR)] = L'\\'; - lpBuffer[Value->Length / sizeof(WCHAR) + 1] = 0; - } - } else if (nBufferLength > 0) - { - lpBuffer[0] = L'\0'; - } + ret++; /* add space for terminating 0 */ + + if (count) + { + lstrcpynW(path, tmp_full_path, count); + if (count >= ret) + ret--; /* return length without 0 */ + else if (count < 4) + path[0] = 0; /* avoid returning ambiguous "X:" */ + } + + DPRINT("GetTempPathW returning %u, %s\n", ret, path); + return ret; - return Length; } @@ -343,37 +230,7 @@ GetSystemDirectoryA ( UINT uSize ) { - ANSI_STRING String; - ULONG Length; - NTSTATUS Status; - - Length = RtlUnicodeStringToAnsiSize (&SystemDirectory); //len of ansi str incl. nullchar - - if (lpBuffer == NULL) - return Length; - - if (uSize >= Length){ - String.Length = 0; - String.MaximumLength = uSize; - String.Buffer = lpBuffer; - - /* convert unicode string to ansi (or oem) */ - if (bIsFileApiAnsi) - Status = RtlUnicodeStringToAnsiString (&String, - &SystemDirectory, - FALSE); - else - Status = RtlUnicodeStringToOemString (&String, - &SystemDirectory, - FALSE); - if (!NT_SUCCESS(Status) ) - return 0; - - return Length-1; //good: ret chars excl. nullchar - - } - - return Length; //bad: ret space needed incl. nullchar + return FilenameU2A_FitOrFail(lpBuffer, uSize, &SystemDirectory); } @@ -416,38 +273,7 @@ GetWindowsDirectoryA ( UINT uSize ) { - ANSI_STRING String; - ULONG Length; - NTSTATUS Status; - - Length = RtlUnicodeStringToAnsiSize (&WindowsDirectory); //len of ansi str incl. nullchar - - if (lpBuffer == NULL) - return Length; - - if (uSize >= Length){ - - String.Length = 0; - String.MaximumLength = uSize; - String.Buffer = lpBuffer; - - /* convert unicode string to ansi (or oem) */ - if (bIsFileApiAnsi) - Status = RtlUnicodeStringToAnsiString (&String, - &WindowsDirectory, - FALSE); - else - Status = RtlUnicodeStringToOemString (&String, - &WindowsDirectory, - FALSE); - - if (!NT_SUCCESS(Status)) - return 0; - - return Length-1; //good: ret chars excl. nullchar - } - - return Length; //bad: ret space needed incl. nullchar + return FilenameU2A_FitOrFail(lpBuffer, uSize, &WindowsDirectory); } diff --git a/reactos/lib/kernel32/file/dir.c b/reactos/lib/kernel32/file/dir.c index 5011b836986..0d2ea65d557 100644 --- a/reactos/lib/kernel32/file/dir.c +++ b/reactos/lib/kernel32/file/dir.c @@ -50,65 +50,26 @@ CreateDirectoryExA ( LPCSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes) { - UNICODE_STRING TmplDirU; - UNICODE_STRING NewDirU; - ANSI_STRING TmplDir; - ANSI_STRING NewDir; - BOOL Result; + PWCHAR TemplateDirectoryW; + PWCHAR NewDirectoryW; + BOOL ret; - RtlInitUnicodeString (&TmplDirU, - NULL); + if (!(TemplateDirectoryW = FilenameA2W(lpTemplateDirectory, FALSE))) + return FALSE; + + if (!(NewDirectoryW = FilenameA2W(lpNewDirectory, TRUE))) + return FALSE; + + ret = CreateDirectoryExW (TemplateDirectoryW, + NewDirectoryW, + lpSecurityAttributes); - RtlInitUnicodeString (&NewDirU, - NULL); + if (lpNewDirectory != NULL) + RtlFreeHeap (RtlGetProcessHeap (), + 0, + NewDirectoryW); - if (lpTemplateDirectory != NULL) - { - RtlInitAnsiString (&TmplDir, - (LPSTR)lpTemplateDirectory); - - /* convert ansi (or oem) string to unicode */ - if (bIsFileApiAnsi) - RtlAnsiStringToUnicodeString (&TmplDirU, - &TmplDir, - TRUE); - else - RtlOemStringToUnicodeString (&TmplDirU, - &TmplDir, - TRUE); - } - - if (lpNewDirectory != NULL) - { - RtlInitAnsiString (&NewDir, - (LPSTR)lpNewDirectory); - - /* convert ansi (or oem) string to unicode */ - if (bIsFileApiAnsi) - RtlAnsiStringToUnicodeString (&NewDirU, - &NewDir, - TRUE); - else - RtlOemStringToUnicodeString (&NewDirU, - &NewDir, - TRUE); - } - - Result = CreateDirectoryExW (TmplDirU.Buffer, - NewDirU.Buffer, - lpSecurityAttributes); - - if (lpTemplateDirectory != NULL) - RtlFreeHeap (RtlGetProcessHeap (), - 0, - TmplDirU.Buffer); - - if (lpNewDirectory != NULL) - RtlFreeHeap (RtlGetProcessHeap (), - 0, - NewDirU.Buffer); - - return Result; + return ret; } @@ -215,30 +176,14 @@ RemoveDirectoryA ( LPCSTR lpPathName ) { - UNICODE_STRING PathNameU; - ANSI_STRING PathName; - BOOL Result; + PWCHAR PathNameW; + + DPRINT("RemoveDirectoryA(%s)\n",lpPathName); - RtlInitAnsiString (&PathName, - (LPSTR)lpPathName); + if (!(PathNameW = FilenameA2W(lpPathName, FALSE))) + return FALSE; - /* convert ansi (or oem) string to unicode */ - if (bIsFileApiAnsi) - RtlAnsiStringToUnicodeString (&PathNameU, - &PathName, - TRUE); - else - RtlOemStringToUnicodeString (&PathNameU, - &PathName, - TRUE); - - Result = RemoveDirectoryW (PathNameU.Buffer); - - RtlFreeHeap (RtlGetProcessHeap (), - 0, - PathNameU.Buffer); - - return Result; + return RemoveDirectoryW (PathNameW); } @@ -337,70 +282,49 @@ GetFullPathNameA ( LPSTR *lpFilePart ) { - UNICODE_STRING nameW; - WCHAR bufferW[MAX_PATH]; - DWORD ret; - LPWSTR FilePart = NULL; + WCHAR BufferW[MAX_PATH]; + PWCHAR FileNameW; + DWORD ret; + LPWSTR FilePartW = NULL; - DPRINT("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, " - "lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart); + DPRINT("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, " + "lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart); - if (!lpFileName) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } + if (!lpFileName) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } - if (!RtlCreateUnicodeStringFromAsciiz(&nameW, (LPSTR)lpFileName)) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } + if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) + return 0; - if (lpFilePart) - { - *lpFilePart = NULL; - } + ret = GetFullPathNameW(FileNameW, MAX_PATH, BufferW, &FilePartW); + + if (!ret) + return 0; + + if (ret > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } + + ret = FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1); + + if (ret < nBufferLength && lpFilePart) + { + /* if the path closed with '\', FilePart is NULL */ + if (!FilePartW) + *lpFilePart=NULL; + else + *lpFilePart = (FilePartW - BufferW) + lpBuffer; + } + + DPRINT("GetFullPathNameA ret: lpBuffer %s lpFilePart %s\n", + lpBuffer, (lpFilePart == NULL) ? "NULL" : *lpFilePart); - ret = GetFullPathNameW(nameW.Buffer, MAX_PATH, bufferW, &FilePart); - - if (MAX_PATH < ret) - { - SetLastError(ERROR_FILENAME_EXCED_RANGE); - ret = 0; - } - else if (0 < ret) - { - if (ret < nBufferLength) - { - ANSI_STRING AnsiBuffer; - UNICODE_STRING UnicodeBuffer; - - UnicodeBuffer.Length = wcslen(bufferW) * sizeof(WCHAR); - UnicodeBuffer.MaximumLength = MAX_PATH * sizeof(WCHAR); - UnicodeBuffer.Buffer = bufferW; - AnsiBuffer.MaximumLength = nBufferLength; - AnsiBuffer.Length = 0; - AnsiBuffer.Buffer = lpBuffer; - RtlUnicodeStringToAnsiString(&AnsiBuffer, &UnicodeBuffer, FALSE); - - if (lpFilePart && FilePart != NULL) - { - *lpFilePart = (FilePart - bufferW) + lpBuffer; - } - } - else - { - ret++; - } - } - - RtlFreeUnicodeString(&nameW); - - DPRINT("lpBuffer %s lpFilePart %s Length %ld\n", - lpBuffer, (lpFilePart == NULL) ? "NULL" : *lpFilePart, nameW.Length); - - return ret; + return ret; } @@ -426,17 +350,10 @@ GetFullPathNameW ( lpBuffer, lpFilePart); - DPRINT("lpBuffer %S lpFilePart %S Length %ld\n", + DPRINT("GetFullPathNameW ret: lpBuffer %S lpFilePart %S Length %ld\n", lpBuffer, (lpFilePart == NULL) ? L"NULL" : *lpFilePart, Length / sizeof(WCHAR)); - Length = Length / sizeof(WCHAR); - if (nBufferLength < Length + 1) - { - DPRINT("Adjusting Length for terminator\n"); - Length++; - } - - return Length; + return Length/sizeof(WCHAR); } @@ -452,9 +369,9 @@ GetShortPathNameA ( DWORD shortlen ) { - UNICODE_STRING longpathW; - WCHAR shortpathW[MAX_PATH]; - DWORD ret, retW; + PWCHAR LongPathW; + WCHAR ShortPathW[MAX_PATH]; + DWORD ret; if (!longpath) { @@ -462,33 +379,21 @@ GetShortPathNameA ( return 0; } - if (!RtlCreateUnicodeStringFromAsciiz(&longpathW, longpath)) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); + if (!(LongPathW = FilenameA2W(longpath, FALSE))) + return 0; + + ret = GetShortPathNameW(LongPathW, ShortPathW, MAX_PATH); + + if (!ret) return 0; - } - - retW = GetShortPathNameW(longpathW.Buffer, shortpathW, MAX_PATH); - - if (!retW) - ret = 0; - else if (retW > PATH_MAX) + + if (ret > MAX_PATH) { SetLastError(ERROR_FILENAME_EXCED_RANGE); - ret = 0; + return 0; } - else - { - ret = WideCharToMultiByte(CP_ACP, 0, shortpathW, -1, NULL, 0, NULL, NULL); - if (ret <= shortlen) - { - WideCharToMultiByte(CP_ACP, 0, shortpathW, -1, shortpath, shortlen, NULL, NULL); - ret--; /* length without 0 */ - } - } - - RtlFreeUnicodeString(&longpathW); - return ret; + + return FilenameW2A_FitOrFail(shortpath, shortlen, ShortPathW, ret+1); } @@ -513,6 +418,8 @@ GetShortPathNameW ( UNICODE_STRING ustr; WCHAR ustr_buf[8+1+3+1]; + DPRINT("GetShortPathNameW: %S\n",longpath); + if (!longpath) { SetLastError(ERROR_INVALID_PARAMETER); @@ -931,38 +838,18 @@ SetDllDirectoryW( BOOL STDCALL SetDllDirectoryA( - LPCSTR lpPathName + LPCSTR lpPathName /* can be NULL */ ) { - UNICODE_STRING PathNameU; - ANSI_STRING PathNameA; - BOOL Ret; + PWCHAR PathNameW=NULL; - if(lpPathName != NULL) + if(lpPathName) { - RtlInitAnsiString(&PathNameA, lpPathName); - if(bIsFileApiAnsi) - { - RtlAnsiStringToUnicodeString(&PathNameU, &PathNameA, TRUE); - } - else - { - RtlOemStringToUnicodeString(&PathNameU, &PathNameA, TRUE); - } - } - else - { - PathNameU.Buffer = NULL; + if (!(PathNameW = FilenameA2W(lpPathName, FALSE))) + return FALSE; } - Ret = SetDllDirectoryW(PathNameU.Buffer); - - if(lpPathName != NULL) - { - RtlFreeUnicodeString(&PathNameU); - } - - return Ret; + return SetDllDirectoryW(PathNameW); } /* @@ -1012,51 +899,21 @@ GetDllDirectoryA( LPSTR lpBuffer ) { - UNICODE_STRING PathNameU; - ANSI_STRING PathNameA; - DWORD Ret; - - if(nBufferLength > 0) + WCHAR BufferW[MAX_PATH]; + DWORD ret; + + ret = GetDllDirectoryW(MAX_PATH, BufferW); + + if (!ret) + return 0; + + if (ret > MAX_PATH) { - if(!(PathNameU.Buffer = (PWSTR)RtlAllocateHeap(RtlGetProcessHeap(), - 0, - nBufferLength * sizeof(WCHAR)))) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - PathNameU.Length = 0; - PathNameU.MaximumLength = nBufferLength * sizeof(WCHAR); - } - - Ret = GetDllDirectoryW(nBufferLength, - ((nBufferLength > 0) ? PathNameU.Buffer : NULL)); - - if(nBufferLength > 0) - { - PathNameU.Length = Ret * sizeof(WCHAR); - - PathNameA.Length = 0; - PathNameA.MaximumLength = nBufferLength; - PathNameA.Buffer = lpBuffer; - - if(Ret > 0) - { - if(bIsFileApiAnsi) - { - RtlUnicodeStringToAnsiString(&PathNameA, &PathNameU, FALSE); - } - else - { - RtlUnicodeStringToOemString(&PathNameA, &PathNameU, FALSE); - } - } - lpBuffer[Ret] = '\0'; - - RtlFreeHeap(RtlGetProcessHeap(), 0, PathNameU.Buffer); + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; } - return Ret; + return FilenameW2A_FitOrFail(lpBuffer, nBufferLength, BufferW, ret+1); } @@ -1078,25 +935,148 @@ NeedCurrentDirectoryForExePathW(LPCWSTR ExeName) BOOL STDCALL NeedCurrentDirectoryForExePathA(LPCSTR ExeName) { - ANSI_STRING ExeNameA; - UNICODE_STRING ExeNameU; - BOOL Ret; + PWCHAR ExeNameW; - RtlInitAnsiString(&ExeNameA, ExeName); - if(bIsFileApiAnsi) - { - RtlAnsiStringToUnicodeString(&ExeNameU, &ExeNameA, TRUE); - } - else - { - RtlOemStringToUnicodeString(&ExeNameU, &ExeNameA, TRUE); - } + if (!(ExeNameW = FilenameA2W(ExeName, FALSE))) + return FALSE; - Ret = NeedCurrentDirectoryForExePathW(ExeNameU.Buffer); - - RtlFreeUnicodeString(&ExeNameU); - - return Ret; + return NeedCurrentDirectoryForExePathW(ExeNameW); +} + + + + + +/*********************************************************************** + * @implemented + * + * GetLongPathNameW (KERNEL32.@) + * + * NOTES + * observed (Win2000): + * shortpath=NULL: LastError=ERROR_INVALID_PARAMETER, ret=0 + * shortpath="": LastError=ERROR_PATH_NOT_FOUND, ret=0 + */ +DWORD STDCALL GetLongPathNameW( LPCWSTR shortpath, LPWSTR longpath, DWORD longlen ) +{ +#define MAX_PATHNAME_LEN 1024 + + WCHAR tmplongpath[MAX_PATHNAME_LEN]; + LPCWSTR p; + DWORD sp = 0, lp = 0; + DWORD tmplen; + BOOL unixabsolute = (shortpath[0] == '/'); + WIN32_FIND_DATAW wfd; + HANDLE goit; + + if (!shortpath) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + if (!shortpath[0]) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return 0; + } + + DPRINT("GetLongPathNameW(%s,%p,%ld)\n", shortpath, longpath, longlen); + + if (shortpath[0] == '\\' && shortpath[1] == '\\') + { + DPRINT1("ERR: UNC pathname %s\n", shortpath); + lstrcpynW( longpath, shortpath, longlen ); + return wcslen(longpath); + } + + /* check for drive letter */ + if (!unixabsolute && shortpath[1] == ':' ) + { + tmplongpath[0] = shortpath[0]; + tmplongpath[1] = ':'; + lp = sp = 2; + } + + while (shortpath[sp]) + { + /* check for path delimiters and reproduce them */ + if (shortpath[sp] == '\\' || shortpath[sp] == '/') + { + if (!lp || tmplongpath[lp-1] != '\\') + { + /* strip double "\\" */ + tmplongpath[lp++] = '\\'; + } + tmplongpath[lp] = 0; /* terminate string */ + sp++; + continue; + } + + p = shortpath + sp; + if (sp == 0 && p[0] == '.' && (p[1] == '/' || p[1] == '\\')) + { + tmplongpath[lp++] = *p++; + tmplongpath[lp++] = *p++; + } + for (; *p && *p != '/' && *p != '\\'; p++); + tmplen = p - (shortpath + sp); + lstrcpynW(tmplongpath + lp, shortpath + sp, tmplen + 1); + /* Check if the file exists and use the existing file name */ + goit = FindFirstFileW(tmplongpath, &wfd); + if (goit == INVALID_HANDLE_VALUE) + { + DPRINT("not found %s!\n", tmplongpath); + SetLastError ( ERROR_FILE_NOT_FOUND ); + return 0; + } + FindClose(goit); + wcscpy(tmplongpath + lp, wfd.cFileName); + lp += wcslen(tmplongpath + lp); + sp += tmplen; + } + tmplen = wcslen(shortpath) - 1; + if ((shortpath[tmplen] == '/' || shortpath[tmplen] == '\\') && + (tmplongpath[lp - 1] != '/' && tmplongpath[lp - 1] != '\\')) + tmplongpath[lp++] = shortpath[tmplen]; + tmplongpath[lp] = 0; + + tmplen = wcslen(tmplongpath) + 1; + if (tmplen <= longlen) + { + wcscpy(longpath, tmplongpath); + DPRINT("returning %s\n", longpath); + tmplen--; /* length without 0 */ + } + + return tmplen; +} + + + +/*********************************************************************** + * GetLongPathNameA (KERNEL32.@) + */ +DWORD STDCALL GetLongPathNameA( LPCSTR shortpath, LPSTR longpath, DWORD longlen ) +{ + WCHAR *shortpathW; + WCHAR longpathW[MAX_PATH]; + DWORD ret; + + DPRINT("GetLongPathNameA %s, %i\n",shortpath,longlen ); + + if (!(shortpathW = FilenameA2W( shortpath, FALSE ))) + return 0; + + ret = GetLongPathNameW(shortpathW, longpathW, MAX_PATH); + + if (!ret) return 0; + if (ret > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } + + return FilenameW2A_FitOrFail(longpath, longlen, longpathW, ret+1 ); } /* EOF */ diff --git a/reactos/lib/kernel32/file/file.c b/reactos/lib/kernel32/file/file.c index 0c3eb45a3c7..10ccfdfa3d2 100644 --- a/reactos/lib/kernel32/file/file.c +++ b/reactos/lib/kernel32/file/file.c @@ -25,6 +25,162 @@ BOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem /* FUNCTIONS ****************************************************************/ + +PWCHAR +FilenameA2W(LPCSTR NameA, BOOL alloc) +{ + PUNICODE_STRING pstrW; + + pstrW = FilenameA2U(NameA, alloc); + + return pstrW ? pstrW->Buffer : NULL; +} + + +PUNICODE_STRING +FilenameA2U(LPCSTR NameA, BOOL alloc) +{ + ANSI_STRING str; + UNICODE_STRING strW; + PUNICODE_STRING pstrW; + NTSTATUS Status; + + ASSERT(NtCurrentTeb()->StaticUnicodeString.Buffer == NtCurrentTeb()->StaticUnicodeBuffer); + ASSERT(NtCurrentTeb()->StaticUnicodeString.MaximumLength == sizeof(NtCurrentTeb()->StaticUnicodeBuffer)); + + RtlInitAnsiString(&str, NameA); + pstrW = alloc ? &strW : &NtCurrentTeb()->StaticUnicodeString; + + if (bIsFileApiAnsi) + Status= RtlAnsiStringToUnicodeString( pstrW, &str, alloc ); + else + Status= RtlOemStringToUnicodeString( pstrW, &str, alloc ); + + if (NT_SUCCESS(Status)) + return pstrW; + + if (Status== STATUS_BUFFER_OVERFLOW) + SetLastError( ERROR_FILENAME_EXCED_RANGE ); + else + SetLastErrorByStatus(Status); + + return NULL; +} + + +/* +No copy/conversion is done if the dest. buffer is too small. + +Returns: + Success: number of TCHARS copied into dest. buffer NOT including nullterm + Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm +*/ +DWORD +FilenameU2A_FitOrFail( + LPSTR DestA, + INT destLen, /* buffer size in TCHARS incl. nullchar */ + PUNICODE_STRING SourceU + ) +{ + DWORD ret; + + ret = bIsFileApiAnsi? RtlUnicodeStringToAnsiSize(SourceU) : RtlUnicodeStringToOemSize(SourceU); + /* ret incl. nullchar */ + + if (DestA && ret <= destLen) + { + ANSI_STRING str; + + str.Buffer = DestA; + str.MaximumLength = destLen; + + + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString(&str, SourceU, FALSE ); + else + RtlUnicodeStringToOemString(&str, SourceU, FALSE ); + + ret = str.Length; /* SUCCESS: length without terminating 0 */ + } + + return ret; +} + + +/* +No copy/conversion is done if the dest. buffer is too small. + +Returns: + Success: number of TCHARS copied into dest. buffer NOT including nullterm + Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm +*/ +DWORD +FilenameW2A_FitOrFail( + LPSTR DestA, + INT destLen, /* buffer size in TCHARS incl. nullchar */ + LPCWSTR SourceW, + INT sourceLen /* buffer size in TCHARS incl. nullchar */ + ) +{ + UNICODE_STRING strW; + + if (sourceLen < 0) sourceLen = wcslen(SourceW) + 1; + + strW.Buffer = (PWCHAR)SourceW; + strW.MaximumLength = sourceLen * sizeof(WCHAR); + strW.Length = strW.MaximumLength - sizeof(WCHAR); + + return FilenameU2A_FitOrFail(DestA, destLen, &strW); +} + + + +DWORD +FilenameA2W_N( + LPWSTR dest, + INT destlen, /* buffer size in TCHARS incl. nullchar */ + LPCSTR src, + INT srclen /* buffer size in TCHARS incl. nullchar */ + ) +{ + DWORD ret; + + if (srclen < 0) srclen = strlen( src ) + 1; + + if (bIsFileApiAnsi) + RtlMultiByteToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen ); + else + RtlOemToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen ); + + if (ret) dest[(ret/sizeof(WCHAR))-1]=0; + + return ret; +} + + +DWORD +FilenameW2A_N( + LPSTR dest, + INT destlen, /* buffer size in TCHARS incl. nullchar */ + LPCWSTR src, + INT srclen /* buffer size in TCHARS incl. nullchar */ + ) +{ + DWORD ret; + + if (srclen < 0) srclen = wcslen( src ) + 1; + + if (bIsFileApiAnsi) + RtlUnicodeToMultiByteN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR)); + else + RtlUnicodeToOemN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR) ); + + if (ret) dest[ret-1]=0; + + return ret; +} + + /* * @implemented */ @@ -518,29 +674,12 @@ DWORD STDCALL GetCompressedFileSizeA(LPCSTR lpFileName, LPDWORD lpFileSizeHigh) { - UNICODE_STRING FileNameU; - ANSI_STRING FileName; - DWORD Size; + PWCHAR FileNameW; - RtlInitAnsiString(&FileName, - (LPSTR)lpFileName); + if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) + return INVALID_FILE_SIZE; - /* convert ansi (or oem) string to unicode */ - if (bIsFileApiAnsi) - RtlAnsiStringToUnicodeString(&FileNameU, - &FileName, - TRUE); - else - RtlOemStringToUnicodeString(&FileNameU, - &FileName, - TRUE); - - Size = GetCompressedFileSizeW(FileNameU.Buffer, - lpFileSizeHigh); - - RtlFreeUnicodeString (&FileNameU); - - return Size; + return GetCompressedFileSizeW(FileNameW, lpFileSizeHigh); } @@ -563,23 +702,28 @@ GetCompressedFileSizeW(LPCWSTR lpFileName, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hFile == INVALID_HANDLE_VALUE) + return INVALID_FILE_SIZE; errCode = NtQueryInformationFile(hFile, &IoStatusBlock, &FileCompression, sizeof(FILE_COMPRESSION_INFORMATION), FileCompressionInformation); + + CloseHandle(hFile); + if (!NT_SUCCESS(errCode)) { - CloseHandle(hFile); SetLastErrorByStatus(errCode); return INVALID_FILE_SIZE; } - CloseHandle(hFile); if(lpFileSizeHigh) *lpFileSizeHigh = FileCompression.CompressedFileSize.u.HighPart; + SetLastError(NO_ERROR); return FileCompression.CompressedFileSize.u.LowPart; } @@ -773,27 +917,12 @@ GetFileAttributesExA(LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation) { - UNICODE_STRING FileNameU; - ANSI_STRING FileName; - BOOL Result; - RtlInitAnsiString (&FileName, - (LPSTR)lpFileName); + PWCHAR FileNameW; + + if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) + return FALSE; - /* convert ansi (or oem) string to unicode */ - if (bIsFileApiAnsi) - RtlAnsiStringToUnicodeString (&FileNameU, - &FileName, - TRUE); - else - RtlOemStringToUnicodeString (&FileNameU, - &FileName, - TRUE); - - Result = GetFileAttributesExW(FileNameU.Buffer, fInfoLevelId, lpFileInformation); - - RtlFreeUnicodeString (&FileNameU); - - return Result; + return GetFileAttributesExW(FileNameW, fInfoLevelId, lpFileInformation); } @@ -803,29 +932,16 @@ GetFileAttributesExA(LPCSTR lpFileName, DWORD STDCALL GetFileAttributesA(LPCSTR lpFileName) { - WIN32_FILE_ATTRIBUTE_DATA FileAttributeData; - UNICODE_STRING FileNameU; - ANSI_STRING FileName; - BOOL Result; + WIN32_FILE_ATTRIBUTE_DATA FileAttributeData; + PWSTR FileNameW; + BOOL ret; - RtlInitAnsiString (&FileName, - (LPSTR)lpFileName); + if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) + return INVALID_FILE_ATTRIBUTES; + + ret = GetFileAttributesExW(FileNameW, GetFileExInfoStandard, &FileAttributeData); - /* convert ansi (or oem) string to unicode */ - if (bIsFileApiAnsi) - RtlAnsiStringToUnicodeString (&FileNameU, - &FileName, - TRUE); - else - RtlOemStringToUnicodeString (&FileNameU, - &FileName, - TRUE); - - Result = GetFileAttributesExW(FileNameU.Buffer, GetFileExInfoStandard, &FileAttributeData); - - RtlFreeUnicodeString (&FileNameU); - - return Result ? FileAttributeData.dwFileAttributes : 0xffffffff; + return ret ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES; } @@ -842,36 +958,20 @@ GetFileAttributesW(LPCWSTR lpFileName) Result = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &FileAttributeData); - return Result ? FileAttributeData.dwFileAttributes : 0xffffffff; + return Result ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES; } BOOL STDCALL -SetFileAttributesA(LPCSTR lpFileName, - DWORD dwFileAttributes) +SetFileAttributesA( + LPCSTR lpFileName, + DWORD dwFileAttributes) { - UNICODE_STRING FileNameU; - ANSI_STRING FileName; - BOOL Result; + PWCHAR FileNameW; - RtlInitAnsiString (&FileName, - (LPSTR)lpFileName); + if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) + return FALSE; - /* convert ansi (or oem) string to unicode */ - if (bIsFileApiAnsi) - RtlAnsiStringToUnicodeString (&FileNameU, - &FileName, - TRUE); - else - RtlOemStringToUnicodeString (&FileNameU, - &FileName, - TRUE); - - Result = SetFileAttributesW (FileNameU.Buffer, - dwFileAttributes); - - RtlFreeUnicodeString (&FileNameU); - - return Result; + return SetFileAttributesW(FileNameW, dwFileAttributes); } @@ -956,100 +1056,91 @@ SetFileAttributesW(LPCWSTR lpFileName, } -/* - * @implemented + + +/*********************************************************************** + * GetTempFileNameA (KERNEL32.@) */ -UINT STDCALL -GetTempFileNameA(LPCSTR lpPathName, - LPCSTR lpPrefixString, - UINT uUnique, - LPSTR lpTempFileName) +UINT WINAPI GetTempFileNameA( LPCSTR path, LPCSTR prefix, UINT unique, LPSTR buffer) { - HANDLE hFile; - UINT unique = uUnique; - UINT len; - const char *format = "%.*s\\~%.3s%4.4x.TMP"; - - DPRINT("GetTempFileNameA(lpPathName %s, lpPrefixString %.*s, " - "uUnique %x, lpTempFileName %x)\n", lpPathName, 4, - lpPrefixString, uUnique, lpTempFileName); - - if (lpPathName == NULL) - return 0; - - len = strlen(lpPathName); - if (len > 0 && (lpPathName[len-1] == '\\' || lpPathName[len-1] == '/')) - len--; - - if (uUnique == 0) - uUnique = GetCurrentTime(); + WCHAR BufferW[MAX_PATH]; + PWCHAR PathW; + WCHAR PrefixW[3+1]; + UINT ret; - sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique); + if (!(PathW = FilenameA2W(path, FALSE))) + return 0; + + if (prefix) + FilenameA2W_N(PrefixW, 3+1, prefix, -1); - if (unique) - return uUnique; + ret = GetTempFileNameW(PathW, prefix ? PrefixW : NULL, unique, BufferW); + + if (ret) + FilenameW2A_N(buffer, MAX_PATH, BufferW, -1); - while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL, - CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY, - 0)) == INVALID_HANDLE_VALUE) - { - if (GetLastError() != ERROR_FILE_EXISTS) - { - return 0; - } - sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique); - } - CloseHandle(hFile); - return uUnique; + return ret; +} + +/*********************************************************************** + * GetTempFileNameW (KERNEL32.@) + */ +UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR buffer ) +{ + static const WCHAR formatW[] = L"%x.tmp"; + + int i; + LPWSTR p; + + if ( !path || !prefix || !buffer ) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + wcscpy( buffer, path ); + p = buffer + wcslen(buffer); + + /* add a \, if there isn't one */ + if ((p == buffer) || (p[-1] != '\\')) *p++ = '\\'; + + for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++; + + unique &= 0xffff; + + if (unique) swprintf( p, formatW, unique ); + else + { + /* get a "random" unique number and try to create the file */ + HANDLE handle; + UINT num = GetTickCount() & 0xffff; + + if (!num) num = 1; + unique = num; + do + { + swprintf( p, formatW, unique ); + handle = CreateFileW( buffer, GENERIC_WRITE, 0, NULL, + CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); + if (handle != INVALID_HANDLE_VALUE) + { /* We created it */ + DPRINT("created %S\n", buffer); + CloseHandle( handle ); + break; + } + if (GetLastError() != ERROR_FILE_EXISTS && + GetLastError() != ERROR_SHARING_VIOLATION) + break; /* No need to go on */ + if (!(++unique & 0xffff)) unique = 1; + } while (unique != num); + } + + DPRINT("returning %S\n", buffer); + return unique; } -/* - * @implemented - */ -UINT STDCALL -GetTempFileNameW(LPCWSTR lpPathName, - LPCWSTR lpPrefixString, - UINT uUnique, - LPWSTR lpTempFileName) -{ - HANDLE hFile; - UINT unique = uUnique; - UINT len; - const WCHAR *format = L"%.*s\\~%.3s%4.4x.TMP"; - - DPRINT("GetTempFileNameW(lpPathName %S, lpPrefixString %.*S, " - "uUnique %x, lpTempFileName %x)\n", lpPathName, 4, - lpPrefixString, uUnique, lpTempFileName); - if (lpPathName == NULL) - return 0; - - len = wcslen(lpPathName); - if (len > 0 && (lpPathName[len-1] == L'\\' || lpPathName[len-1] == L'/')) - len--; - - if (uUnique == 0) - uUnique = GetCurrentTime(); - - swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique); - - if (unique) - return uUnique; - - while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL, - CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY, - 0)) == INVALID_HANDLE_VALUE) - { - if (GetLastError() != ERROR_FILE_EXISTS) - { - return 0; - } - swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique); - } - CloseHandle(hFile); - return uUnique; -} /* @@ -1258,6 +1349,7 @@ SetFileValidData( } + /* * @implemented */ @@ -1324,10 +1416,7 @@ SetFileShortNameA( LPCSTR lpShortName ) { - NTSTATUS Status; - BOOL Ret; - ANSI_STRING ShortNameA; - UNICODE_STRING ShortName; + PWCHAR ShortNameW; if(IsConsoleHandle(hFile)) { @@ -1341,22 +1430,10 @@ SetFileShortNameA( return FALSE; } - RtlInitAnsiString(&ShortNameA, (LPSTR)lpShortName); - - if(bIsFileApiAnsi) - Status = RtlAnsiStringToUnicodeString(&ShortName, &ShortNameA, TRUE); - else - Status = RtlOemStringToUnicodeString(&ShortName, &ShortNameA, TRUE); - if(!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - Ret = SetFileShortNameW(hFile, ShortName.Buffer); - - RtlFreeUnicodeString(&ShortName); - return Ret; + if (!(ShortNameW = FilenameA2W(lpShortName, FALSE))) + return FALSE; + + return SetFileShortNameW(hFile, ShortNameW); } diff --git a/reactos/lib/kernel32/file/hardlink.c b/reactos/lib/kernel32/file/hardlink.c index 522544adbcf..984a2dd6454 100644 --- a/reactos/lib/kernel32/file/hardlink.c +++ b/reactos/lib/kernel32/file/hardlink.c @@ -200,9 +200,7 @@ CreateHardLinkA(LPCSTR lpFileName, LPCSTR lpExistingFileName, LPSECURITY_ATTRIBUTES lpSecurityAttributes) { - ANSI_STRING FileNameA, ExistingFileNameA; - UNICODE_STRING FileName, ExistingFileName; - NTSTATUS Status; + PWCHAR FileNameW, ExistingFileNameW; BOOL Ret; if(!lpFileName || !lpExistingFileName) @@ -211,34 +209,15 @@ CreateHardLinkA(LPCSTR lpFileName, return FALSE; } - RtlInitAnsiString(&FileNameA, (LPSTR)lpFileName); - RtlInitAnsiString(&ExistingFileNameA, (LPSTR)lpExistingFileName); - - if(bIsFileApiAnsi) - Status = RtlAnsiStringToUnicodeString(&FileName, &FileNameA, TRUE); - else - Status = RtlOemStringToUnicodeString(&FileName, &FileNameA, TRUE); - if(!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); + if (!(FileNameW = FilenameA2W(lpFileName, FALSE))) return FALSE; - } - - if(bIsFileApiAnsi) - Status = RtlAnsiStringToUnicodeString(&ExistingFileName, &ExistingFileNameA, TRUE); - else - Status = RtlOemStringToUnicodeString(&ExistingFileName, &ExistingFileNameA, TRUE); - if(!NT_SUCCESS(Status)) - { - RtlFreeUnicodeString(&FileName); - SetLastErrorByStatus(Status); + + if (!(ExistingFileNameW = FilenameA2W(lpExistingFileName, TRUE))) return FALSE; - } + + Ret = CreateHardLinkW(FileNameW , ExistingFileNameW , lpSecurityAttributes); - Ret = CreateHardLinkW(FileName.Buffer, ExistingFileName.Buffer, lpSecurityAttributes); - - RtlFreeUnicodeString(&FileName); - RtlFreeUnicodeString(&ExistingFileName); + RtlFreeHeap(RtlGetProcessHeap(), 0, ExistingFileNameW); return Ret; } diff --git a/reactos/lib/kernel32/file/volume.c b/reactos/lib/kernel32/file/volume.c index 2f903427e19..27a8ea35ce4 100644 --- a/reactos/lib/kernel32/file/volume.c +++ b/reactos/lib/kernel32/file/volume.c @@ -188,43 +188,19 @@ GetDiskFreeSpaceA ( LPDWORD lpTotalNumberOfClusters ) { - UNICODE_STRING RootPathNameU; - ANSI_STRING RootPathName; - BOOL Result; + PWCHAR RootPathNameW=NULL; - RtlInitAnsiString (&RootPathName, - (LPSTR)lpRootPathName); - - RtlInitUnicodeString (&RootPathNameU, - NULL); - - if (lpRootPathName) - { - /* convert ansi (or oem) string to unicode */ - if (bIsFileApiAnsi) - RtlAnsiStringToUnicodeString (&RootPathNameU, - &RootPathName, - TRUE); - else - RtlOemStringToUnicodeString (&RootPathNameU, - &RootPathName, - TRUE); - } - - Result = GetDiskFreeSpaceW (RootPathNameU.Buffer, + if (lpRootPathName) + { + if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE))) + return FALSE; + } + + return GetDiskFreeSpaceW (RootPathNameW, lpSectorsPerCluster, lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters); - - if (lpRootPathName) - { - RtlFreeHeap (RtlGetProcessHeap (), - 0, - RootPathNameU.Buffer); - } - - return Result; } @@ -290,48 +266,24 @@ GetDiskFreeSpaceW( */ BOOL STDCALL GetDiskFreeSpaceExA ( - LPCSTR lpDirectoryName, + LPCSTR lpDirectoryName OPTIONAL, PULARGE_INTEGER lpFreeBytesAvailableToCaller, PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes ) { - UNICODE_STRING DirectoryNameU; - ANSI_STRING DirectoryName; - BOOL Result; - - RtlInitAnsiString (&DirectoryName, - (LPSTR)lpDirectoryName); - - RtlInitUnicodeString (&DirectoryNameU, - NULL); + PWCHAR DirectoryNameW=NULL; if (lpDirectoryName) { - /* convert ansi (or oem) string to unicode */ - if (bIsFileApiAnsi) - RtlAnsiStringToUnicodeString (&DirectoryNameU, - &DirectoryName, - TRUE); - else - RtlOemStringToUnicodeString (&DirectoryNameU, - &DirectoryName, - TRUE); + if (!(DirectoryNameW = FilenameA2W(lpDirectoryName, FALSE))) + return FALSE; } - Result = GetDiskFreeSpaceExW (DirectoryNameU.Buffer, + return GetDiskFreeSpaceExW (DirectoryNameW , lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes); - - if (lpDirectoryName) - { - RtlFreeHeap (RtlGetProcessHeap (), - 0, - DirectoryNameU.Buffer); - } - - return Result; } @@ -340,7 +292,7 @@ GetDiskFreeSpaceExA ( */ BOOL STDCALL GetDiskFreeSpaceExW( - LPCWSTR lpDirectoryName, + LPCWSTR lpDirectoryName OPTIONAL, PULARGE_INTEGER lpFreeBytesAvailableToCaller, PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes @@ -353,6 +305,10 @@ GetDiskFreeSpaceExW( HANDLE hFile; NTSTATUS errCode; + /* + FIXME: this is obviously wrong for UNC paths, symbolic directories etc. + -Gunnar + */ if (lpDirectoryName) { wcsncpy (RootPathName, lpDirectoryName, 3); @@ -408,30 +364,12 @@ GetDiskFreeSpaceExW( UINT STDCALL GetDriveTypeA(LPCSTR lpRootPathName) { - UNICODE_STRING RootPathNameU; - ANSI_STRING RootPathName; - UINT Result; + PWCHAR RootPathNameW; + + if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE))) + return DRIVE_UNKNOWN; - RtlInitAnsiString (&RootPathName, - (LPSTR)lpRootPathName); - - /* convert ansi (or oem) string to unicode */ - if (bIsFileApiAnsi) - RtlAnsiStringToUnicodeString (&RootPathNameU, - &RootPathName, - TRUE); - else - RtlOemStringToUnicodeString (&RootPathNameU, - &RootPathName, - TRUE); - - Result = GetDriveTypeW (RootPathNameU.Buffer); - - RtlFreeHeap (RtlGetProcessHeap (), - 0, - RootPathNameU.Buffer); - - return Result; + return GetDriveTypeW(RootPathNameW); } @@ -505,27 +443,16 @@ GetVolumeInformationA( DWORD nFileSystemNameSize ) { - UNICODE_STRING RootPathNameU; UNICODE_STRING FileSystemNameU; UNICODE_STRING VolumeNameU; - ANSI_STRING RootPathName; ANSI_STRING VolumeName; ANSI_STRING FileSystemName; + PWCHAR RootPathNameW; BOOL Result; - RtlInitAnsiString (&RootPathName, - (LPSTR)lpRootPathName); - - /* convert ansi (or oem) string to unicode */ - if (bIsFileApiAnsi) - RtlAnsiStringToUnicodeString (&RootPathNameU, - &RootPathName, - TRUE); - else - RtlOemStringToUnicodeString (&RootPathNameU, - &RootPathName, - TRUE); - + if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE))) + return FALSE; + if (lpVolumeNameBuffer) { VolumeNameU.Length = 0; @@ -544,7 +471,7 @@ GetVolumeInformationA( FileSystemNameU.MaximumLength); } - Result = GetVolumeInformationW (RootPathNameU.Buffer, + Result = GetVolumeInformationW (RootPathNameW, lpVolumeNameBuffer ? VolumeNameU.Buffer : NULL, nVolumeNameSize, lpVolumeSerialNumber, @@ -604,9 +531,6 @@ GetVolumeInformationA( } } - RtlFreeHeap (RtlGetProcessHeap (), - 0, - RootPathNameU.Buffer); if (lpVolumeNameBuffer) { RtlFreeHeap (RtlGetProcessHeap (), @@ -750,49 +674,31 @@ BOOL STDCALL SetVolumeLabelA ( LPCSTR lpRootPathName, - LPCSTR lpVolumeName + LPCSTR lpVolumeName /* NULL if deleting label */ ) { - UNICODE_STRING RootPathNameU; - ANSI_STRING RootPathName; - UNICODE_STRING VolumeNameU; - ANSI_STRING VolumeName; + PWCHAR RootPathNameW; + PWCHAR VolumeNameW = NULL; BOOL Result; - RtlInitAnsiString (&RootPathName, - (LPSTR)lpRootPathName); - RtlInitAnsiString (&VolumeName, - (LPSTR)lpVolumeName); + if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE))) + return FALSE; - /* convert ansi (or oem) strings to unicode */ - if (bIsFileApiAnsi) - { - RtlAnsiStringToUnicodeString (&RootPathNameU, - &RootPathName, - TRUE); - RtlAnsiStringToUnicodeString (&VolumeNameU, - &VolumeName, - TRUE); - } - else - { - RtlOemStringToUnicodeString (&RootPathNameU, - &RootPathName, - TRUE); - RtlOemStringToUnicodeString (&VolumeNameU, - &VolumeName, - TRUE); - } + if (lpVolumeName) + { + if (!(VolumeNameW = FilenameA2W(lpVolumeName, TRUE))) + return FALSE; + } + + Result = SetVolumeLabelW (RootPathNameW, + VolumeNameW); - Result = SetVolumeLabelW (RootPathNameU.Buffer, - VolumeNameU.Buffer); - - RtlFreeHeap (RtlGetProcessHeap (), - 0, - RootPathNameU.Buffer); - RtlFreeHeap (RtlGetProcessHeap (), - 0, - VolumeNameU.Buffer); + if (VolumeNameW) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + VolumeNameW ); + } return Result; } @@ -802,8 +708,10 @@ SetVolumeLabelA ( * @implemented */ BOOL STDCALL -SetVolumeLabelW(LPCWSTR lpRootPathName, - LPCWSTR lpVolumeName) +SetVolumeLabelW( + LPCWSTR lpRootPathName, + LPCWSTR lpVolumeName /* NULL if deleting label */ + ) { PFILE_FS_LABEL_INFORMATION LabelInfo; IO_STATUS_BLOCK IoStatusBlock; diff --git a/reactos/lib/kernel32/include/kernel32.h b/reactos/lib/kernel32/include/kernel32.h index b4515c0ebc3..85689c81f90 100755 --- a/reactos/lib/kernel32/include/kernel32.h +++ b/reactos/lib/kernel32/include/kernel32.h @@ -60,5 +60,16 @@ HANDLE STDCALL OpenConsoleW (LPWSTR wsName, PTEB GetTeb(VOID); + +PWCHAR FilenameA2W(LPCSTR NameA, BOOL alloc); +PUNICODE_STRING FilenameA2U(LPCSTR NameA, BOOL alloc); + +DWORD FilenameW2A_FitOrFail(LPSTR DestA, INT destLen, LPCWSTR SourceW, INT sourceLen); +DWORD FilenameU2A_FitOrFail(LPSTR DestA, INT destLen, PUNICODE_STRING SourceU); + + + + + #endif /* ndef _KERNEL32_INCLUDE_KERNEL32_H */ diff --git a/reactos/lib/kernel32/misc/dllmain.c b/reactos/lib/kernel32/misc/dllmain.c index 6431ff04873..3b9117fa14a 100644 --- a/reactos/lib/kernel32/misc/dllmain.c +++ b/reactos/lib/kernel32/misc/dllmain.c @@ -82,7 +82,8 @@ DllMain(HANDLE hDll, LPVOID lpReserved) { NTSTATUS Status; - + PTEB Teb = NtCurrentTeb(); + (void)lpReserved; DPRINT("DllMain(hInst %lx, dwReason %lu)\n", @@ -147,8 +148,13 @@ DllMain(HANDLE hDll, RtlInitializeCriticalSection(&ConsoleLock); SetConsoleCtrlHandler(DefaultConsoleCtrlHandler, TRUE); - /* Insert more dll attach stuff here! */ + Teb->StaticUnicodeString.Length = 0; + Teb->StaticUnicodeString.MaximumLength = sizeof(Teb->StaticUnicodeBuffer); + Teb->StaticUnicodeString.Buffer = Teb->StaticUnicodeBuffer; + + /* Insert more dll attach stuff here! */ + DllInitialized = TRUE; break; @@ -172,6 +178,14 @@ DllMain(HANDLE hDll, } break; + case DLL_THREAD_ATTACH: + + Teb->StaticUnicodeString.Length = 0; + Teb->StaticUnicodeString.MaximumLength = sizeof(Teb->StaticUnicodeBuffer); + Teb->StaticUnicodeString.Buffer = Teb->StaticUnicodeBuffer; + break; + + default: break; } diff --git a/reactos/lib/kernel32/misc/res.c b/reactos/lib/kernel32/misc/res.c index ff6907dc244..f0a0ed8fbb8 100644 --- a/reactos/lib/kernel32/misc/res.c +++ b/reactos/lib/kernel32/misc/res.c @@ -8,6 +8,7 @@ */ #include +#include #define NDEBUG #include "../include/debug.h" @@ -312,39 +313,172 @@ EnumResourceLanguagesA ( } -/* - * @unimplemented - */ -BOOL -STDCALL -EnumResourceNamesW ( - HINSTANCE hModule, - LPCWSTR lpType, - ENUMRESNAMEPROCW lpEnumFunc, - LONG lParam - ) + +/* retrieve the resource name to pass to the ntdll functions */ +static NTSTATUS get_res_nameA( LPCSTR name, UNICODE_STRING *str ) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + if (!HIWORD(name)) + { + str->Buffer = (LPWSTR)name; + return STATUS_SUCCESS; + } + if (name[0] == '#') + { + ULONG value; + if (RtlCharToInteger( name + 1, 10, &value ) != STATUS_SUCCESS || HIWORD(value)) + return STATUS_INVALID_PARAMETER; + str->Buffer = (LPWSTR)value; + return STATUS_SUCCESS; + } + RtlCreateUnicodeStringFromAsciiz( str, name ); + RtlUpcaseUnicodeString( str, str, FALSE ); + return STATUS_SUCCESS; +} + +/* retrieve the resource name to pass to the ntdll functions */ +static NTSTATUS get_res_nameW( LPCWSTR name, UNICODE_STRING *str ) +{ + if (!HIWORD(name)) + { + str->Buffer = (LPWSTR)name; + return STATUS_SUCCESS; + } + if (name[0] == '#') + { + ULONG value; + RtlInitUnicodeString( str, name + 1 ); + if (RtlUnicodeStringToInteger( str, 10, &value ) != STATUS_SUCCESS || HIWORD(value)) + return STATUS_INVALID_PARAMETER; + str->Buffer = (LPWSTR)value; + return STATUS_SUCCESS; + } + RtlCreateUnicodeString( str, name ); + RtlUpcaseUnicodeString( str, str, FALSE ); + return STATUS_SUCCESS; +} + +/********************************************************************** + * EnumResourceNamesA (KERNEL32.@) + */ +BOOL STDCALL EnumResourceNamesA( HMODULE hmod, LPCSTR type, ENUMRESNAMEPROCA lpfun, LONG_PTR lparam ) +{ + int i; + BOOL ret = FALSE; + DWORD len = 0, newlen; + LPSTR name = NULL; + NTSTATUS status; + UNICODE_STRING typeW; + LDR_RESOURCE_INFO info; + PIMAGE_RESOURCE_DIRECTORY basedir, resdir; + const IMAGE_RESOURCE_DIRECTORY_ENTRY *et; + const IMAGE_RESOURCE_DIR_STRING_U *str; + + DPRINT( "%p %s %p %lx\n", hmod, type, lpfun, lparam ); + + if (!hmod) hmod = GetModuleHandleA( NULL ); + typeW.Buffer = NULL; + if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS) + goto done; + if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS) + goto done; + info.Type = (ULONG)typeW.Buffer; + if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS) + goto done; + + et = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); + for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++) + { + if (et[i].NameIsString) + { + str = (IMAGE_RESOURCE_DIR_STRING_U *) ((LPBYTE) basedir + et[i].NameOffset); + newlen = WideCharToMultiByte(CP_ACP, 0, str->NameString, str->Length, NULL, 0, NULL, NULL); + if (newlen + 1 > len) + { + len = newlen + 1; + HeapFree( GetProcessHeap(), 0, name ); + if (!(name = HeapAlloc(GetProcessHeap(), 0, len + 1 ))) + { + ret = FALSE; + break; + } + } + WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, name, len, NULL, NULL ); + name[newlen] = 0; + ret = lpfun(hmod,type,name,lparam); + } + else + { + ret = lpfun( hmod, type, (LPSTR)(int)et[i].Id, lparam ); + } + if (!ret) break; + } +done: + HeapFree( GetProcessHeap(), 0, name ); + if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer ); + if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) ); + return ret; } -/* - * @unimplemented +/********************************************************************** + * EnumResourceNamesW (KERNEL32.@) */ -BOOL -STDCALL -EnumResourceNamesA ( - HINSTANCE hModule, - LPCSTR lpType, - ENUMRESNAMEPROCA lpEnumFunc, - LONG lParam - ) +BOOL STDCALL EnumResourceNamesW( HMODULE hmod, LPCWSTR type, ENUMRESNAMEPROCW lpfun, LONG_PTR lparam ) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} + int i, len = 0; + BOOL ret = FALSE; + LPWSTR name = NULL; + NTSTATUS status; + UNICODE_STRING typeW; + LDR_RESOURCE_INFO info; + PIMAGE_RESOURCE_DIRECTORY basedir, resdir; + const IMAGE_RESOURCE_DIRECTORY_ENTRY *et; + const IMAGE_RESOURCE_DIR_STRING_U *str; + DPRINT( "%p %s %p %lx\n", hmod, type, lpfun, lparam ); + + if (!hmod) hmod = GetModuleHandleW( NULL ); + typeW.Buffer = NULL; + if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS) + goto done; + if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS) + goto done; + info.Type = (ULONG)typeW.Buffer; + if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS) + goto done; + + et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1); + for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++) + { + if (et[i].NameIsString) + { + str = (IMAGE_RESOURCE_DIR_STRING_U *) ((LPBYTE) basedir + et[i].NameOffset); + if (str->Length + 1 > len) + { + len = str->Length + 1; + HeapFree( GetProcessHeap(), 0, name ); + if (!(name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) + { + ret = FALSE; + break; + } + } + memcpy(name, str->NameString, str->Length * sizeof (WCHAR)); + name[str->Length] = 0; + ret = lpfun(hmod,type,name,lparam); + } + else + { + ret = lpfun( hmod, type, (LPWSTR)(int)et[i].Id, lparam ); + } + if (!ret) break; + } +done: + HeapFree( GetProcessHeap(), 0, name ); + if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer ); + if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) ); + return ret; +} /* * @unimplemented diff --git a/reactos/lib/kernel32/misc/stubs.c b/reactos/lib/kernel32/misc/stubs.c index 5b963cb3c83..ae55a9378fb 100644 --- a/reactos/lib/kernel32/misc/stubs.c +++ b/reactos/lib/kernel32/misc/stubs.c @@ -788,25 +788,8 @@ QueueUserWorkItem( return 0; } -/* - * @unimplemented - */ -BOOL -STDCALL -ReadDirectoryChangesW( - HANDLE hDirectory, - LPVOID lpBuffer, - DWORD nBufferLength, - BOOL bWatchSubtree, - DWORD dwNotifyFilter, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped, - LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine - ) -{ - STUB; - return 0; -} + + /* * @unimplemented @@ -1156,20 +1139,7 @@ GetFirmwareEnvironmentVariableW( return 0; } -/* - * @unimplemented - */ -DWORD -STDCALL -GetLongPathNameW( - LPCWSTR lpszShortPath, - LPWSTR lpszLongPath, - DWORD cchBuffer - ) -{ - STUB; - return 0; -} + /* * @unimplemented @@ -1443,20 +1413,7 @@ GetFirmwareEnvironmentVariableA( return 0; } -/* - * @unimplemented - */ -DWORD -STDCALL -GetLongPathNameA( - LPCSTR lpszShortPath, - LPSTR lpszLongPath, - DWORD cchBuffer - ) -{ - STUB; - return 0; -} + /* * @unimplemented diff --git a/reactos/lib/ntdll/ldr/res.c b/reactos/lib/ntdll/ldr/res.c index 91676aa3554..46bc9cdf9f6 100644 --- a/reactos/lib/ntdll/ldr/res.c +++ b/reactos/lib/ntdll/ldr/res.c @@ -320,9 +320,9 @@ LdrAccessResource(IN PVOID BaseAddress, */ NTSTATUS STDCALL LdrFindResourceDirectory_U(IN PVOID BaseAddress, - WCHAR** name, - DWORD level, - OUT PVOID* addr) + IN PLDR_RESOURCE_INFO info, + IN ULONG level, + OUT PIMAGE_RESOURCE_DIRECTORY* addr) { PIMAGE_RESOURCE_DIRECTORY ResDir; PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry; @@ -330,6 +330,7 @@ LdrFindResourceDirectory_U(IN PVOID BaseAddress, ULONG i; NTSTATUS Status = STATUS_SUCCESS; WCHAR* ws; + PWCHAR* name = (PWCHAR*) info; /* Get the pointer to the resource directory */ ResDir = (PIMAGE_RESOURCE_DIRECTORY) diff --git a/reactos/lib/ntdll/rtl/path.c b/reactos/lib/ntdll/rtl/path.c index 3e60798b07b..6a7dd533dc3 100644 --- a/reactos/lib/ntdll/rtl/path.c +++ b/reactos/lib/ntdll/rtl/path.c @@ -241,59 +241,33 @@ RtlGetCurrentDirectory_U(ULONG MaximumLength, * @implemented */ NTSTATUS STDCALL -RtlSetCurrentDirectory_U(PUNICODE_STRING name) +RtlSetCurrentDirectory_U(PUNICODE_STRING dir) { UNICODE_STRING full; UNICODE_STRING envvar; + FILE_FS_DEVICE_INFORMATION device_info; OBJECT_ATTRIBUTES Attr; IO_STATUS_BLOCK iosb; PCURDIR cd; NTSTATUS Status; ULONG size; HANDLE handle = NULL; - PWSTR wcs; - PWSTR buf = 0; - PFILE_NAME_INFORMATION filenameinfo; - ULONG backslashcount = 0; - ULONG Index; WCHAR var[4]; + PWSTR ptr; - DPRINT ("RtlSetCurrentDirectory %wZ\n", name); + DPRINT("RtlSetCurrentDirectory %wZ\n", dir); RtlAcquirePebLock (); + cd = (PCURDIR)&NtCurrentPeb ()->ProcessParameters->CurrentDirectoryName; - size = cd->DosPath.MaximumLength; - buf = RtlAllocateHeap (RtlGetProcessHeap(), - 0, - size); - if (buf == NULL) - { - RtlReleasePebLock (); - return STATUS_NO_MEMORY; - } + if (!RtlDosPathNameToNtPathName_U (dir->Buffer, &full, 0, 0)) + { + RtlReleasePebLock (); + return STATUS_OBJECT_NAME_INVALID; + } - size = RtlGetFullPathName_U (name->Buffer, size, buf, 0); - if (!size) - { - RtlFreeHeap (RtlGetProcessHeap (), - 0, - buf); - RtlReleasePebLock (); - return STATUS_OBJECT_NAME_INVALID; - } - - if (!RtlDosPathNameToNtPathName_U (buf, &full, 0, 0)) - { - RtlFreeHeap (RtlGetProcessHeap (), - 0, - buf); - RtlFreeHeap (RtlGetProcessHeap (), - 0, - full.Buffer); - RtlReleasePebLock (); - return STATUS_OBJECT_NAME_INVALID; - } + DPRINT("RtlSetCurrentDirectory: full %wZ\n",&full); InitializeObjectAttributes (&Attr, &full, @@ -307,114 +281,124 @@ RtlSetCurrentDirectory_U(PUNICODE_STRING name) &iosb, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) - { - RtlFreeHeap (RtlGetProcessHeap (), - 0, - buf); - RtlFreeHeap (RtlGetProcessHeap (), - 0, - full.Buffer); - RtlReleasePebLock (); - return Status; - } + { + RtlFreeUnicodeString( &full); + RtlReleasePebLock (); + return Status; + } + /* don't keep the directory handle open on removable media */ + if (!NtQueryVolumeInformationFile( handle, &iosb, &device_info, + sizeof(device_info), FileFsDeviceInformation ) && + (device_info.Characteristics & FILE_REMOVABLE_MEDIA)) + { + DPRINT1("don't keep the directory handle open on removable media\n"); + NtClose( handle ); + handle = 0; + } + + +/* What the heck is this all about??? It looks like its getting the long path, + * and if does, ITS WRONG! If current directory is set with a short path, + * GetCurrentDir should return a short path. + * If anyone agrees with me, remove this stuff. + * -Gunnar + */ +#if 0 filenameinfo = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - MAX_PATH*sizeof(WCHAR)+sizeof(ULONG)); + 0, + MAX_PATH*sizeof(WCHAR)+sizeof(ULONG)); Status = NtQueryInformationFile(handle, - &iosb, - filenameinfo, - MAX_PATH*sizeof(WCHAR)+sizeof(ULONG), - FileNameInformation); + &iosb, + filenameinfo, + MAX_PATH*sizeof(WCHAR)+sizeof(ULONG), + FileNameInformation); if (!NT_SUCCESS(Status)) { - RtlFreeHeap(RtlGetProcessHeap(), - 0, - filenameinfo); - RtlFreeHeap(RtlGetProcessHeap(), - 0, - buf); - RtlFreeHeap(RtlGetProcessHeap(), - 0, - full.Buffer); - RtlReleasePebLock(); - return(Status); + RtlFreeHeap(RtlGetProcessHeap(), + 0, + filenameinfo); + RtlFreeHeap(RtlGetProcessHeap(), + 0, + buf); + RtlFreeHeap(RtlGetProcessHeap(), + 0, + full.Buffer); + RtlReleasePebLock(); + return(Status); } /* If it's just "\", we need special handling */ if (filenameinfo->FileNameLength > sizeof(WCHAR)) { - wcs = buf + size / sizeof(WCHAR) - 1; - if (*wcs == L'\\') - { - *(wcs) = 0; - wcs--; - size -= sizeof(WCHAR); - } - - for (Index = 0; - Index < filenameinfo->FileNameLength / sizeof(WCHAR); - Index++) - { - if (filenameinfo->FileName[Index] == '\\') backslashcount++; - } - - DPRINT("%d \n",backslashcount); - for (;backslashcount;wcs--) - { - if (*wcs=='\\') backslashcount--; - } - wcs++; - - RtlCopyMemory(wcs, filenameinfo->FileName, filenameinfo->FileNameLength); - wcs[filenameinfo->FileNameLength / sizeof(WCHAR)] = 0; - - size = (wcs - buf) * sizeof(WCHAR) + filenameinfo->FileNameLength; - } - - RtlFreeHeap (RtlGetProcessHeap (), - 0, - filenameinfo); - - /* append backslash if missing */ wcs = buf + size / sizeof(WCHAR) - 1; - if (*wcs != L'\\') + if (*wcs == L'\\') { - *(++wcs) = L'\\'; - *(++wcs) = 0; - size += sizeof(WCHAR); + *(wcs) = 0; + wcs--; + size -= sizeof(WCHAR); } - - memmove(cd->DosPath.Buffer, - buf, - size + sizeof(WCHAR)); - cd->DosPath.Length = size; + + for (Index = 0; + Index < filenameinfo->FileNameLength / sizeof(WCHAR); + Index++) + { + if (filenameinfo->FileName[Index] == '\\') backslashcount++; + } + + DPRINT("%d \n",backslashcount); + for (;backslashcount;wcs--) + { + if (*wcs=='\\') backslashcount--; + } + wcs++; + + RtlCopyMemory(wcs, filenameinfo->FileName, filenameinfo->FileNameLength); + wcs[filenameinfo->FileNameLength / sizeof(WCHAR)] = 0; + + size = (wcs - buf) * sizeof(WCHAR) + filenameinfo->FileNameLength; + } +#endif + + if (cd->Handle) - NtClose(cd->Handle); + NtClose(cd->Handle); cd->Handle = handle; - if (cd->DosPath.Buffer[1]==':') - { - envvar.Length = 2 * swprintf (var, L"=%c:", cd->DosPath.Buffer[0]); - envvar.MaximumLength = 8; - envvar.Buffer = var; + /* append trailing \ if missing */ + size = full.Length / sizeof(WCHAR); + ptr = full.Buffer; + ptr += 4; /* skip \??\ prefix */ + size -= 4; - RtlSetEnvironmentVariable(NULL, - &envvar, - &cd->DosPath); + /* This is ok because RtlDosPathNameToNtPathName_U returns a nullterminated string. + * So the nullterm is replaced with \ + * -Gunnar + */ + if (size && ptr[size - 1] != '\\') ptr[size++] = '\\'; + + memcpy( cd->DosPath.Buffer, ptr, size * sizeof(WCHAR)); + cd->DosPath.Buffer[size] = 0; + cd->DosPath.Length = size * sizeof(WCHAR); + + + /* FIXME: whats this all about??? Wine doesnt have this. -Gunnar */ + if (cd->DosPath.Buffer[1]==':') + { + envvar.Length = 2 * swprintf (var, L"=%c:", cd->DosPath.Buffer[0]); + envvar.MaximumLength = 8; + envvar.Buffer = var; + + RtlSetEnvironmentVariable(NULL, + &envvar, + &cd->DosPath); } - RtlFreeHeap (RtlGetProcessHeap (), - 0, - buf); - - RtlFreeHeap (RtlGetProcessHeap (), - 0, - full.Buffer); - + RtlFreeUnicodeString( &full); RtlReleasePebLock(); return STATUS_SUCCESS;