diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 676fa2c890..cefa911394 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -348,9 +348,9 @@ @ stub RtlDestroyProcessParameters @ stub RtlDestroyQueryDebugBuffer @ stdcall RtlDetermineDosPathNameType_U(wstr) -@ stub RtlDoesFileExists_U #(wstr) +@ stdcall RtlDoesFileExists_U(wstr) @ stdcall RtlDosPathNameToNtPathName_U(wstr ptr ptr ptr) -@ stub RtlDosSearchPath_U #(wstr wstr wstr long ptr ptr) +@ stdcall RtlDosSearchPath_U(wstr wstr wstr long ptr ptr) @ stdcall RtlDowncaseUnicodeChar(long) @ stdcall RtlDowncaseUnicodeString(ptr ptr long) @ stdcall RtlDumpResource(ptr) diff --git a/dlls/ntdll/path.c b/dlls/ntdll/path.c index 08be65fc28..6b1e863bcb 100644 --- a/dlls/ntdll/path.c +++ b/dlls/ntdll/path.c @@ -55,6 +55,18 @@ DOS_PATHNAME_TYPE WINAPI RtlDetermineDosPathNameType_U( PCWSTR path ) } } +/****************************************************************** + * RtlDoesFileExists_U + * + * + */ +BOOLEAN WINAPI RtlDoesFileExists_U(LPCWSTR file_name) +{ + FIXME("(%s): stub\n", debugstr_w(file_name)); + + return TRUE; +} + /*********************************************************************** * RtlIsDosDeviceName_U (NTDLL.@) * @@ -222,6 +234,68 @@ BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(PWSTR dos_path, return TRUE; } +/****************************************************************** + * RtlDosSearchPath_U + * + * Searchs a file of name 'name' into a ';' separated list of paths + * (stored in paths) + * Doesn't seem to search elsewhere than the paths list + * Stores the result in buffer (file_part will point to the position + * of the file name in the buffer) + * FIXME: + * - how long shall the paths be ??? (MAX_PATH or larger with \\?\ constructs ???) + */ +ULONG WINAPI RtlDosSearchPath_U(LPCWSTR paths, LPCWSTR search, LPCWSTR ext, + ULONG buffer_size, LPWSTR buffer, + LPWSTR* file_part) +{ + DOS_PATHNAME_TYPE type = RtlDetermineDosPathNameType_U(search); + ULONG len = 0; + + if (type == RELATIVE_PATH) + { + ULONG allocated = 0, needed, filelen; + WCHAR* name = NULL; + + filelen = 1 /* for \ */ + strlenW(search) + 1 /* \0 */; + + if (strchrW(search, '.') != NULL) ext = NULL; + if (ext != NULL) filelen += strlenW(ext); + + while (*paths) + { + LPCWSTR ptr; + + for (needed = 0, ptr = paths; *ptr != 0 && *ptr++ != ';'; needed++); + if (needed + filelen > allocated) + { + name = (WCHAR*)RtlReAllocateHeap(ntdll_get_process_heap(), 0, + name, (needed + filelen) * sizeof(WCHAR)); + if (!name) return 0; + allocated = needed + filelen; + } + memmove(name, paths, needed * sizeof(WCHAR)); + /* append '\\' if none is present */ + if (needed > 0 && name[needed - 1] != '\\') name[needed++] = '\\'; + strcpyW(&name[needed], search); + if (ext) strcatW(&name[needed], ext); + if (RtlDoesFileExists_U(name)) + { + len = RtlGetFullPathName_U(name, buffer_size, buffer, file_part); + break; + } + paths = ptr; + } + RtlFreeHeap(ntdll_get_process_heap(), 0, name); + } + else if (RtlDoesFileExists_U(search)) + { + len = RtlGetFullPathName_U(search, buffer_size, buffer, file_part); + } + + return len; +} + /****************************************************************** * get_full_path_helper * diff --git a/include/winternl.h b/include/winternl.h index 2e6c04147f..4cac308450 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -1037,7 +1037,9 @@ DWORD WINAPI RtlDeleteSecurityObject(DWORD); NTSTATUS WINAPI RtlDestroyEnvironment(PWSTR); HANDLE WINAPI RtlDestroyHeap(HANDLE); DOS_PATHNAME_TYPE WINAPI RtlDetermineDosPathNameType_U(PCWSTR); +BOOLEAN WINAPI RtlDoesFileExists_U(LPCWSTR); BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(LPWSTR,PUNICODE_STRING,PWSTR*,CURDIR*); +ULONG WINAPI RtlDosSearchPath_U(LPCWSTR, LPCWSTR, LPCWSTR, ULONG, LPWSTR, LPWSTR*); WCHAR WINAPI RtlDowncaseUnicodeChar(WCHAR); NTSTATUS WINAPI RtlDowncaseUnicodeString(UNICODE_STRING*,const UNICODE_STRING*,BOOLEAN); void WINAPI RtlDumpResource(LPRTL_RWLOCK);