From: Marc-Aurel Zent mzent@codeweavers.com
--- dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/path.c | 49 ++++++++++++++++++++++++++++++++++--------- include/winternl.h | 1 + 3 files changed, 41 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 83589a47ac8..a51cab8263f 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -750,6 +750,7 @@ # @ stub RtlGetFirstRange @ stdcall RtlGetFrame() @ stdcall RtlGetFullPathName_U(wstr long ptr ptr) +@ stdcall RtlGetFullPathName_UEx(wstr long ptr ptr ptr) @ stdcall RtlGetGroupSecurityDescriptor(ptr ptr ptr) @ stdcall RtlGetLastNtStatus() @ stdcall RtlGetLastWin32Error() diff --git a/dlls/ntdll/path.c b/dlls/ntdll/path.c index e96597ab429..3c10467b5b2 100644 --- a/dlls/ntdll/path.c +++ b/dlls/ntdll/path.c @@ -420,7 +420,7 @@ ULONG WINAPI RtlDosSearchPath_U(LPCWSTR paths, LPCWSTR search, LPCWSTR ext, /****************************************************************** * collapse_path * - * Helper for RtlGetFullPathName_U. + * Helper for RtlGetFullPathName_UEx. * Get rid of . and .. components in the path. */ static inline void collapse_path( WCHAR *path, UINT mark ) @@ -511,10 +511,10 @@ static const WCHAR *skip_unc_prefix( const WCHAR *ptr ) /****************************************************************** * get_full_path_helper * - * Helper for RtlGetFullPathName_U + * Helper for RtlGetFullPathName_UEx. * Note: name and buffer are allowed to point to the same memory spot */ -static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size) +static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size, RTL_PATH_TYPE type) { ULONG reqsize = 0, mark = 0, dep = 0, deplen; LPWSTR ins_str = NULL; @@ -533,7 +533,7 @@ static ULONG get_full_path_helper(LPCWSTR name, LPWSTR buffer, ULONG size) else cd = &NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory.DosPath;
- switch (RtlDetermineDosPathNameType_U(name)) + switch (type) { case RtlPathTypeUncAbsolute: /* \foo */ ptr = skip_unc_prefix( name ); @@ -705,6 +705,7 @@ done: return reqsize; }
+ /****************************************************************** * RtlGetFullPathName_U (NTDLL.@) * @@ -719,16 +720,43 @@ done: DWORD WINAPI RtlGetFullPathName_U(const WCHAR* name, ULONG size, WCHAR* buffer, WCHAR** file_part) { - WCHAR* ptr; - DWORD dosdev; - DWORD reqsize; - TRACE("(%s %lu %p %p)\n", debugstr_w(name), size, buffer, file_part);
+ return RtlGetFullPathName_UEx(name, size, buffer, file_part, NULL); +} + + +/****************************************************************** + * RtlGetFullPathName_UEx (NTDLL.@) + * + * Returns the number of bytes written to buffer (not including the + * terminating NULL) if the function succeeds, or the required number of bytes + * (including the terminating NULL) if the buffer is too small. + * + * file_part will point to the filename part inside buffer (except if we use + * DOS device name, in which case file_in_buf is NULL) + * + * type is an optional parameter that will receive the type of the path + * + */ +ULONG WINAPI RtlGetFullPathName_UEx(const WCHAR* name, ULONG size, WCHAR* buffer, + WCHAR** file_part, RTL_PATH_TYPE* type) +{ + WCHAR* ptr; + DWORD dosdev; + DWORD reqsize; + RTL_PATH_TYPE path_type; + + TRACE("(%s %lu %p %p %p)\n", debugstr_w(name), size, buffer, file_part, type); + if (!name || !*name) return 0;
if (file_part) *file_part = NULL;
+ path_type = RtlDetermineDosPathNameType_U(name); + + if (type) *type = path_type; + /* check for DOS device name */ dosdev = RtlIsDosDeviceName_U(name); if (dosdev) @@ -744,12 +772,12 @@ DWORD WINAPI RtlGetFullPathName_U(const WCHAR* name, ULONG size, WCHAR* buffer, return sz + 8; }
- reqsize = get_full_path_helper(name, buffer, size); + reqsize = get_full_path_helper(name, buffer, size, path_type); if (!reqsize) return 0; if (reqsize > size) { LPWSTR tmp = RtlAllocateHeap(GetProcessHeap(), 0, reqsize); - reqsize = get_full_path_helper(name, tmp, reqsize); + reqsize = get_full_path_helper(name, tmp, reqsize, path_type); if (reqsize + sizeof(WCHAR) > size) /* it may have worked the second time */ { RtlFreeHeap(GetProcessHeap(), 0, tmp); @@ -765,6 +793,7 @@ DWORD WINAPI RtlGetFullPathName_U(const WCHAR* name, ULONG size, WCHAR* buffer, return reqsize; }
+ /************************************************************************* * RtlGetLongestNtPathLength [NTDLL.@] * diff --git a/include/winternl.h b/include/winternl.h index 6107035dcf7..2b1e3d029ed 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -4933,6 +4933,7 @@ NTSYSAPI NTSTATUS WINAPI RtlGetExtendedContextLength2(ULONG,ULONG*,ULONG64); NTSYSAPI ULONG64 WINAPI RtlGetExtendedFeaturesMask(CONTEXT_EX*); NTSYSAPI TEB_ACTIVE_FRAME * WINAPI RtlGetFrame(void); NTSYSAPI ULONG WINAPI RtlGetFullPathName_U(PCWSTR,ULONG,PWSTR,PWSTR*); +NTSYSAPI ULONG WINAPI RtlGetFullPathName_UEx(PCWSTR,ULONG,PWSTR,PWSTR*,RTL_PATH_TYPE*); NTSYSAPI NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR,PSID *,PBOOLEAN); NTSYSAPI NTSTATUS WINAPI RtlGetLastNtStatus(void); NTSYSAPI DWORD WINAPI RtlGetLastWin32Error(void);