X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=dll%2Fwin32%2Fkernel32%2Fmisc%2Fldr.c;h=b383f1dd6a175741e997de9fef18bcd9c3589eb9;hp=9e324785454ec5cc7809dd44521504d2364d407a;hb=b726d7355f0aa394852fa8c56e59cfc9bbc4293c;hpb=f819794d7d55fe311c0f81d47d2b51bc74f65af3 diff --git a/dll/win32/kernel32/misc/ldr.c b/dll/win32/kernel32/misc/ldr.c index 9e324785454..b383f1dd6a1 100644 --- a/dll/win32/kernel32/misc/ldr.c +++ b/dll/win32/kernel32/misc/ldr.c @@ -1,10 +1,9 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory - * PROJECT : ReactOS user mode libraries + * PROJECT : ReactOS system libraries * MODULE : kernel32.dll - * FILE : reactos/lib/kernel32/misc/ldr.c - * AUTHOR : Ariadne + * FILE : reactos/dll/win32/kernel32/misc/ldr.c + * AUTHOR : Aleksey Bragin */ #include @@ -15,15 +14,82 @@ typedef struct tagLOADPARMS32 { LPSTR lpEnvAddress; LPSTR lpCmdLine; - LPSTR lpCmdShow; + WORD wMagicValue; + WORD wCmdShow; DWORD dwReserved; } LOADPARMS32; extern BOOLEAN InWindows; extern WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle; +#define BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR 1 +#define BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS 2 +#define BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE 3 + +VOID +NTAPI +BasepLocateExeLdrEntry(IN PLDR_DATA_TABLE_ENTRY Entry, + IN PVOID Context, + OUT BOOLEAN *StopEnumeration); + /* FUNCTIONS ****************************************************************/ +DWORD +WINAPI +BasepGetModuleHandleExParameterValidation(DWORD dwFlags, + LPCWSTR lpwModuleName, + HMODULE *phModule) +{ + /* Set phModule to 0 if it's not a NULL pointer */ + if (phModule) *phModule = 0; + + /* Check for invalid flags combination */ + if (dwFlags & ~(GET_MODULE_HANDLE_EX_FLAG_PIN | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) || + ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) && + (dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) || + (!lpwModuleName && (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)) + ) + { + BaseSetLastNTError(STATUS_INVALID_PARAMETER_1); + return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR; + } + + /* Check 2nd parameter */ + if (!phModule) + { + BaseSetLastNTError(STATUS_INVALID_PARAMETER_2); + return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR; + } + + /* Return what we have according to the module name */ + if (lpwModuleName) + { + return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE; + } + + /* No name given, so put ImageBaseAddress there */ + *phModule = (HMODULE)NtCurrentPeb()->ImageBaseAddress; + + return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS; +} + +PVOID +WINAPI +BasepMapModuleHandle(HMODULE hModule, BOOLEAN AsDataFile) +{ + /* If no handle is provided - use current image base address */ + if (!hModule) return NtCurrentPeb()->ImageBaseAddress; + + /* Check if it's a normal or a datafile one */ + if (LDR_IS_DATAFILE(hModule) && !AsDataFile) + return NULL; + + /* It'a a normal DLL, just return its handle */ + return hModule; +} + /** * @name GetDllLoadPath * @@ -41,6 +107,8 @@ GetDllLoadPath(LPCWSTR lpModule) UNICODE_STRING ModuleName; DWORD LastError = GetLastError(); /* GetEnvironmentVariable changes LastError */ + // FIXME: This function is used only by SearchPathW, and is deprecated and will be deleted ASAP. + if ((lpModule != NULL) && (wcslen(lpModule) > 2) && (lpModule[1] == ':')) { lpModuleEnd = lpModule + wcslen(lpModule); @@ -102,19 +170,23 @@ GetDllLoadPath(LPCWSTR lpModule) */ BOOL WINAPI -DisableThreadLibraryCalls ( - HMODULE hLibModule - ) +DisableThreadLibraryCalls( + IN HMODULE hLibModule) { - NTSTATUS Status; + NTSTATUS Status; - Status = LdrDisableThreadCalloutsForDll ((PVOID)hLibModule); - if (!NT_SUCCESS (Status)) - { - SetLastErrorByStatus (Status); - return FALSE; - } - return TRUE; + /* Disable thread library calls */ + Status = LdrDisableThreadCalloutsForDll((PVOID)hLibModule); + + /* If it wasn't success - set last error and return failure */ + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return FALSE; + } + + /* Return success */ + return TRUE; } @@ -123,112 +195,188 @@ DisableThreadLibraryCalls ( */ HINSTANCE WINAPI -LoadLibraryA ( - LPCSTR lpLibFileName - ) +LoadLibraryA(LPCSTR lpLibFileName) { - return LoadLibraryExA (lpLibFileName, 0, 0); -} + LPSTR PathBuffer; + UINT Len; + HINSTANCE Result; + /* Treat twain_32.dll in a special way (what a surprise...) */ + if (lpLibFileName && !_strcmpi(lpLibFileName, "twain_32.dll")) + { + /* Allocate space for the buffer */ + PathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH); + if (PathBuffer) + { + /* Get windows dir in this buffer */ + Len = GetWindowsDirectoryA(PathBuffer, MAX_PATH - 13); /* 13 is sizeof of '\\twain_32.dll' */ + if (Len && Len < (MAX_PATH - 13)) + { + /* We successfully got windows directory. Concatenate twain_32.dll to it */ + strncat(PathBuffer, "\\twain_32.dll", 13); + + /* And recursively call ourselves with a new string */ + Result = LoadLibraryA(PathBuffer); + + /* If it was successful - free memory and return result */ + if (Result) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer); + return Result; + } + } + + /* Free allocated buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer); + } + } + + /* Call the Ex version of the API */ + return LoadLibraryExA(lpLibFileName, 0, 0); +} /* * @implemented */ HINSTANCE WINAPI -LoadLibraryExA ( - LPCSTR lpLibFileName, - HANDLE hFile, - DWORD dwFlags - ) +LoadLibraryExA(LPCSTR lpLibFileName, + HANDLE hFile, + DWORD dwFlags) { - PWCHAR FileNameW; + PUNICODE_STRING FileNameW; - if (!(FileNameW = FilenameA2W(lpLibFileName, FALSE))) - return FALSE; + /* Convert file name to unicode */ + if (!(FileNameW = Basep8BitStringToStaticUnicodeString(lpLibFileName))) + return NULL; - return LoadLibraryExW(FileNameW, hFile, dwFlags); + /* And call W version of the API */ + return LoadLibraryExW(FileNameW->Buffer, hFile, dwFlags); } - /* * @implemented */ HINSTANCE WINAPI -LoadLibraryW ( - LPCWSTR lpLibFileName - ) +LoadLibraryW(LPCWSTR lpLibFileName) { - return LoadLibraryExW (lpLibFileName, 0, 0); + /* Call Ex version of the API */ + return LoadLibraryExW (lpLibFileName, 0, 0); } static NTSTATUS -LoadLibraryAsDatafile(PWSTR path, LPCWSTR name, HMODULE* hmod) +BasepLoadLibraryAsDatafile(PWSTR Path, LPCWSTR Name, HMODULE *hModule) { - static const WCHAR dotDLL[] = {'.','d','l','l',0}; - - WCHAR filenameW[MAX_PATH]; + WCHAR FilenameW[MAX_PATH]; HANDLE hFile = INVALID_HANDLE_VALUE; - HANDLE mapping; - HMODULE module; - - *hmod = 0; - - if (!SearchPathW( path, name, dotDLL, sizeof(filenameW) / sizeof(filenameW[0]), - filenameW, NULL )) + HANDLE hMapping; + NTSTATUS Status; + PVOID lpBaseAddress = NULL; + SIZE_T ViewSize = 0; + //PUNICODE_STRING OriginalName; + //UNICODE_STRING dotDLL = RTL_CONSTANT_STRING(L".DLL"); + + /* Zero out handle value */ + *hModule = 0; + + DPRINT("BasepLoadLibraryAsDatafile(%S %S %p)\n", Path, Name, hModule); + + /*Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + Name, + &dotDLL, + RedirName, + RedirName2, + &OriginalName2, + NULL, + NULL, + NULL);*/ + + /* Try to search for it */ + if (!SearchPathW(Path, + Name, + L".DLL", + sizeof(FilenameW) / sizeof(FilenameW[0]), + FilenameW, + NULL)) { + /* Return last status value directly */ return NtCurrentTeb()->LastStatusValue; } - hFile = CreateFileW( filenameW, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, 0, 0 ); + /* Open this file we found */ + hFile = CreateFileW(FilenameW, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + 0, + 0); + /* If opening failed - return last status value */ if (hFile == INVALID_HANDLE_VALUE) return NtCurrentTeb()->LastStatusValue; - mapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY, 0, 0, NULL ); - CloseHandle( hFile ); - if (!mapping) return NtCurrentTeb()->LastStatusValue; + /* Create file mapping */ + hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + + /* Close the file handle */ + CloseHandle(hFile); + + /* If creating file mapping failed - return last status value */ + if (!hMapping) return NtCurrentTeb()->LastStatusValue; - module = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); - CloseHandle( mapping ); - if (!module) return NtCurrentTeb()->LastStatusValue; + /* Map view of section */ + Status = NtMapViewOfSection(hMapping, + NtCurrentProcess(), + &lpBaseAddress, + 0, + 0, + 0, + &ViewSize, + ViewShare, + 0, + PAGE_READONLY); - /* make sure it's a valid PE file */ - if (!RtlImageNtHeader(module)) + /* Close handle to the section */ + CloseHandle(hMapping); + + /* If mapping view of section failed - return last status value */ + if (!NT_SUCCESS(Status)) return NtCurrentTeb()->LastStatusValue; + + /* Make sure it's a valid PE file */ + if (!RtlImageNtHeader(lpBaseAddress)) { - UnmapViewOfFile( module ); + /* Unmap the view and return failure status */ + UnmapViewOfFile(lpBaseAddress); return STATUS_INVALID_IMAGE_FORMAT; } - *hmod = (HMODULE)((char *)module + 1); /* set low bit of handle to indicate datafile module */ + + /* Set low bit of handle to indicate datafile module */ + *hModule = (HMODULE)((ULONG_PTR)lpBaseAddress | 1); + + /* Load alternate resource module */ + //LdrLoadAlternateResourceModule(*hModule, FilenameW); + return STATUS_SUCCESS; } - /* * @implemented */ HINSTANCE WINAPI -LoadLibraryExW ( - LPCWSTR lpLibFileName, - HANDLE hFile, - DWORD dwFlags - ) +LoadLibraryExW(LPCWSTR lpLibFileName, + HANDLE hFile, + DWORD dwFlags) { - UNICODE_STRING DllName; - HINSTANCE hInst; - NTSTATUS Status; - PWSTR SearchPath; - ULONG DllCharacteristics; - BOOL FreeString = FALSE; - - (void)hFile; - - if ( lpLibFileName == NULL ) - return NULL; + UNICODE_STRING DllName; + HINSTANCE hInst; + NTSTATUS Status; + PWSTR SearchPath; + ULONG DllCharacteristics = 0; + BOOL FreeString = FALSE; /* Check for any flags LdrLoadDll might be interested in */ if (dwFlags & DONT_RESOLVE_DLL_REFERENCES) @@ -237,67 +385,101 @@ LoadLibraryExW ( DllCharacteristics = IMAGE_FILE_EXECUTABLE_IMAGE; } - dwFlags &= - DONT_RESOLVE_DLL_REFERENCES | - LOAD_LIBRARY_AS_DATAFILE | - LOAD_WITH_ALTERED_SEARCH_PATH; - - SearchPath = GetDllLoadPath( - dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH ? lpLibFileName : NULL); + /* Build up a unicode dll name from null-terminated string */ + RtlInitUnicodeString(&DllName, (LPWSTR)lpLibFileName); - RtlInitUnicodeString(&DllName, (LPWSTR)lpLibFileName); + /* Lazy-initialize BasepExeLdrEntry */ + if (!BasepExeLdrEntry) + LdrEnumerateLoadedModules(0, BasepLocateExeLdrEntry, NtCurrentPeb()->ImageBaseAddress); - if (DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ') - { - RtlCreateUnicodeString(&DllName, (LPWSTR)lpLibFileName); - while (DllName.Length > sizeof(WCHAR) && - DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ') - { - DllName.Length -= sizeof(WCHAR); - } - DllName.Buffer[DllName.Length/sizeof(WCHAR)] = UNICODE_NULL; - FreeString = TRUE; - } + /* Check if that module is our exe*/ + if (BasepExeLdrEntry && !(dwFlags & LOAD_LIBRARY_AS_DATAFILE) && + DllName.Length == BasepExeLdrEntry->FullDllName.Length) + { + /* Lengths match and it's not a datafile, so perform name comparison */ + if (RtlEqualUnicodeString(&DllName, &BasepExeLdrEntry->FullDllName, TRUE)) + { + /* That's us! */ + return BasepExeLdrEntry->DllBase; + } + } - if (dwFlags & LOAD_LIBRARY_AS_DATAFILE) + /* Check for trailing spaces and remove them if necessary */ + if (DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ') { - Status = LdrGetDllHandle(SearchPath, NULL, &DllName, (PVOID*)&hInst); - if (!NT_SUCCESS(Status)) + RtlCreateUnicodeString(&DllName, (LPWSTR)lpLibFileName); + while (DllName.Length > sizeof(WCHAR) && + DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ') { - /* The method in load_library_as_datafile allows searching for the - * 'native' libraries only - */ - Status = LoadLibraryAsDatafile(SearchPath, DllName.Buffer, &hInst); - goto done; + DllName.Length -= sizeof(WCHAR); } + DllName.Buffer[DllName.Length/sizeof(WCHAR)] = UNICODE_NULL; + FreeString = TRUE; } - /* HACK!!! FIXME */ - if (InWindows) + /* Compute the load path */ + SearchPath = BasepGetDllPath((dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH) ? (LPWSTR)lpLibFileName : NULL, + NULL); + + if (!SearchPath) { - /* Call the API Properly */ - Status = LdrLoadDll(SearchPath, - &DllCharacteristics, - &DllName, - (PVOID*)&hInst); + /* Getting DLL path failed, so set last error, free mem and return */ + BaseSetLastNTError(STATUS_NO_MEMORY); + if (FreeString) RtlFreeUnicodeString(&DllName); + return NULL; } - else + + _SEH2_TRY { - /* Call the ROS API. NOTE: Don't fix this, I have a patch to merge later. */ - Status = LdrLoadDll(SearchPath, &dwFlags, &DllName, (PVOID*)&hInst); + if (dwFlags & LOAD_LIBRARY_AS_DATAFILE) + { + /* If the image is loaded as a datafile, try to get its handle */ + Status = LdrGetDllHandle(SearchPath, NULL, &DllName, (PVOID*)&hInst); + if (!NT_SUCCESS(Status)) + { + /* It's not loaded yet - so load it up */ + Status = BasepLoadLibraryAsDatafile(SearchPath, DllName.Buffer, &hInst); + _SEH2_YIELD(goto done;) + } + } + + /* HACK!!! FIXME */ + if (InWindows) + { + /* Call the API Properly */ + Status = LdrLoadDll(SearchPath, + &DllCharacteristics, + &DllName, + (PVOID*)&hInst); + } + else + { + /* Call the ROS API. NOTE: Don't fix this, I have a patch to merge later. */ + Status = LdrLoadDll(SearchPath, &dwFlags, &DllName, (PVOID*)&hInst); + } } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } _SEH2_END + done: - RtlFreeHeap(RtlGetProcessHeap(), 0, SearchPath); - if (FreeString) - RtlFreeUnicodeString(&DllName); - if ( !NT_SUCCESS(Status)) - { - SetLastErrorByStatus (Status); - return NULL; - } + /* Free SearchPath buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, SearchPath); + + /* Free DllName string if it was dynamically allocated */ + if (FreeString) RtlFreeUnicodeString(&DllName); + + /* Set last error in failure case */ + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return NULL; + } - return hInst; + /* Return loaded module handle */ + return hInst; } @@ -306,36 +488,56 @@ done: */ FARPROC WINAPI -GetProcAddress( HMODULE hModule, LPCSTR lpProcName ) +GetProcAddress(HMODULE hModule, LPCSTR lpProcName) { - ANSI_STRING ProcedureName; - FARPROC fnExp = NULL; - NTSTATUS Status; + ANSI_STRING ProcedureName, *ProcNamePtr = NULL; + FARPROC fnExp = NULL; + NTSTATUS Status; + PVOID hMapped; + ULONG Ordinal = 0; - if (HIWORD(lpProcName) != 0) - { - RtlInitAnsiString (&ProcedureName, - (LPSTR)lpProcName); - Status = LdrGetProcedureAddress ((PVOID)hModule, - &ProcedureName, - 0, - (PVOID*)&fnExp); - } - else - { - Status = LdrGetProcedureAddress ((PVOID)hModule, - NULL, - (ULONG)lpProcName, - (PVOID*)&fnExp); - } + if (HIWORD(lpProcName) != 0) + { + /* Look up by name */ + RtlInitAnsiString(&ProcedureName, (LPSTR)lpProcName); + ProcNamePtr = &ProcedureName; + } + else + { + /* Look up by ordinal */ + Ordinal = (ULONG)lpProcName; + } - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - fnExp = NULL; - } + /* Map provided handle */ + hMapped = BasepMapModuleHandle(hModule, FALSE); - return fnExp; + /* Get the proc address */ + Status = LdrGetProcedureAddress(hMapped, + ProcNamePtr, + Ordinal, + (PVOID*)&fnExp); + + if (!NT_SUCCESS(Status)) + { + BaseSetLastNTError(Status); + return NULL; + } + + /* Check for a special case when returned pointer is + the same as iamge's base address */ + if (fnExp == hMapped) + { + /* Set correct error code */ + if (HIWORD(lpProcName) != 0) + BaseSetLastNTError(STATUS_ENTRYPOINT_NOT_FOUND); + else + BaseSetLastNTError(STATUS_ORDINAL_NOT_FOUND); + + return NULL; + } + + /* All good, return procedure pointer */ + return fnExp; } @@ -345,28 +547,49 @@ GetProcAddress( HMODULE hModule, LPCSTR lpProcName ) BOOL WINAPI FreeLibrary(HINSTANCE hLibModule) { NTSTATUS Status; + PIMAGE_NT_HEADERS NtHeaders; - if (!hLibModule) + if (LDR_IS_DATAFILE(hLibModule)) { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } + // FIXME: This SEH should go inside RtlImageNtHeader instead + _SEH2_TRY + { + /* This is a LOAD_LIBRARY_AS_DATAFILE module, check if it's a valid one */ + NtHeaders = RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + NtHeaders = NULL; + } _SEH2_END - if ((ULONG_PTR)hLibModule & 1) + if (NtHeaders) + { + /* Unmap view */ + Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)((ULONG_PTR)hLibModule & ~1)); + + /* Unload alternate resource module */ + LdrUnloadAlternateResourceModule(hLibModule); + } + else + Status = STATUS_INVALID_IMAGE_FORMAT; + } + else { - /* this is a LOAD_LIBRARY_AS_DATAFILE module */ - char *ptr = (char *)hLibModule - 1; - UnmapViewOfFile(ptr); - return TRUE; + /* Just unload it */ + Status = LdrUnloadDll((PVOID)hLibModule); } - Status = LdrUnloadDll(hLibModule); + /* Check what kind of status we got */ if (!NT_SUCCESS(Status)) { - SetLastErrorByStatus(Status); + /* Set last error */ + BaseSetLastNTError(Status); + + /* Return failure */ return FALSE; } + /* Return success */ return TRUE; } @@ -376,12 +599,30 @@ BOOL WINAPI FreeLibrary(HINSTANCE hLibModule) */ VOID WINAPI -FreeLibraryAndExitThread ( - HMODULE hLibModule, - DWORD dwExitCode - ) +FreeLibraryAndExitThread(HMODULE hLibModule, + DWORD dwExitCode) { - FreeLibrary(hLibModule); + NTSTATUS Status; + + if (LDR_IS_DATAFILE(hLibModule)) + { + /* This is a LOAD_LIBRARY_AS_DATAFILE module */ + if (RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1))) + { + /* Unmap view */ + Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)((ULONG_PTR)hLibModule & ~1)); + + /* Unload alternate resource module */ + LdrUnloadAlternateResourceModule(hLibModule); + } + } + else + { + /* Just unload it */ + Status = LdrUnloadDll((PVOID)hLibModule); + } + + /* Exit thread */ ExitThread(dwExitCode); } @@ -391,155 +632,292 @@ FreeLibraryAndExitThread ( */ DWORD WINAPI -GetModuleFileNameA ( - HINSTANCE hModule, - LPSTR lpFilename, - DWORD nSize - ) +GetModuleFileNameA(HINSTANCE hModule, + LPSTR lpFilename, + DWORD nSize) { - ANSI_STRING FileName; - PLIST_ENTRY ModuleListHead; - PLIST_ENTRY Entry; - PLDR_DATA_TABLE_ENTRY Module; - PPEB Peb; - ULONG Length = 0; + UNICODE_STRING FilenameW; + ANSI_STRING FilenameA; + NTSTATUS Status; + DWORD Length = 0, LengthToCopy; - Peb = NtCurrentPeb (); - RtlEnterCriticalSection (Peb->LoaderLock); + /* Allocate a unicode buffer */ + FilenameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nSize * sizeof(WCHAR)); + if (!FilenameW.Buffer) + { + BaseSetLastNTError(STATUS_NO_MEMORY); + return 0; + } - if (hModule == NULL) - hModule = Peb->ImageBaseAddress; + /* Call unicode API */ + FilenameW.Length = GetModuleFileNameW(hModule, FilenameW.Buffer, nSize) * sizeof(WCHAR); + FilenameW.MaximumLength = FilenameW.Length + sizeof(WCHAR); - ModuleListHead = &Peb->Ldr->InLoadOrderModuleList; - Entry = ModuleListHead->Flink; + if (FilenameW.Length) + { + /* Convert to ansi string */ + Status = BasepUnicodeStringTo8BitString(&FilenameA, &FilenameW, TRUE); + if (!NT_SUCCESS(Status)) + { + /* Set last error, free string and retun failure */ + BaseSetLastNTError(Status); + RtlFreeUnicodeString(&FilenameW); + return 0; + } - while (Entry != ModuleListHead) - { - Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); - if (Module->DllBase == (PVOID)hModule) - { - Length = min(nSize, Module->FullDllName.Length / sizeof(WCHAR)); - FileName.Length = 0; - FileName.MaximumLength = (USHORT)Length * sizeof(WCHAR); - FileName.Buffer = lpFilename; - - /* convert unicode string to ansi (or oem) */ - if (bIsFileApiAnsi) - RtlUnicodeStringToAnsiString (&FileName, - &Module->FullDllName, - FALSE); - else - RtlUnicodeStringToOemString (&FileName, - &Module->FullDllName, - FALSE); - - if (nSize < Length) - SetLastErrorByStatus (STATUS_BUFFER_TOO_SMALL); - else - lpFilename[Length] = '\0'; - - RtlLeaveCriticalSection (Peb->LoaderLock); - return Length; - } + /* Calculate size to copy */ + Length = min(nSize, FilenameA.Length); - Entry = Entry->Flink; - } + /* Include terminating zero */ + if (nSize > Length) + LengthToCopy = Length + 1; + else + LengthToCopy = nSize; - SetLastErrorByStatus (STATUS_DLL_NOT_FOUND); - RtlLeaveCriticalSection (Peb->LoaderLock); + /* Now copy back to the caller amount he asked */ + RtlMoveMemory(lpFilename, FilenameA.Buffer, LengthToCopy); - return 0; -} + /* Free ansi filename */ + RtlFreeAnsiString(&FilenameA); + } + + /* Free unicode filename */ + RtlFreeHeap(RtlGetProcessHeap(), 0, FilenameW.Buffer); + /* Return length copied */ + return Length; +} /* * @implemented */ DWORD WINAPI -GetModuleFileNameW ( - HINSTANCE hModule, - LPWSTR lpFilename, - DWORD nSize - ) +GetModuleFileNameW(HINSTANCE hModule, + LPWSTR lpFilename, + DWORD nSize) { - UNICODE_STRING FileName; - PLIST_ENTRY ModuleListHead; - PLIST_ENTRY Entry; - PLDR_DATA_TABLE_ENTRY Module; - PPEB Peb; - ULONG Length = 0; - - Peb = NtCurrentPeb (); - RtlEnterCriticalSection (Peb->LoaderLock); - - if (hModule == NULL) - hModule = Peb->ImageBaseAddress; - - ModuleListHead = &Peb->Ldr->InLoadOrderModuleList; - Entry = ModuleListHead->Flink; - while (Entry != ModuleListHead) - { - Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); + PLIST_ENTRY ModuleListHead, Entry; + PLDR_DATA_TABLE_ENTRY Module; + ULONG Length = 0; + ULONG Cookie; + PPEB Peb; - if (Module->DllBase == (PVOID)hModule) - { - Length = min(nSize, Module->FullDllName.Length / sizeof(WCHAR)); - FileName.Length = 0; - FileName.MaximumLength = (USHORT) Length * sizeof(WCHAR); - FileName.Buffer = lpFilename; + hModule = BasepMapModuleHandle(hModule, FALSE); - RtlCopyUnicodeString (&FileName, - &Module->FullDllName); - if (nSize < Length) - SetLastErrorByStatus (STATUS_BUFFER_TOO_SMALL); - else - lpFilename[Length] = L'\0'; + /* Upscale nSize from chars to bytes */ + nSize *= sizeof(WCHAR); - RtlLeaveCriticalSection (Peb->LoaderLock); + _SEH2_TRY + { + /* We don't use per-thread cur dir now */ + //PRTL_PERTHREAD_CURDIR PerThreadCurdir = (PRTL_PERTHREAD_CURDIR)teb->NtTib.SubSystemTib; - return Length; - } + Peb = NtCurrentPeb (); - Entry = Entry->Flink; - } + /* Acquire a loader lock */ + LdrLockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, NULL, &Cookie); + + /* Traverse the module list */ + ModuleListHead = &Peb->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + while (Entry != ModuleListHead) + { + Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); + + /* Check if this is the requested module */ + if (Module->DllBase == (PVOID)hModule) + { + /* Calculate size to copy */ + Length = min(nSize, Module->FullDllName.MaximumLength); - SetLastErrorByStatus (STATUS_DLL_NOT_FOUND); - RtlLeaveCriticalSection (Peb->LoaderLock); + /* Copy contents */ + RtlMoveMemory(lpFilename, Module->FullDllName.Buffer, Length); - return 0; + /* Subtract a terminating zero */ + if (Length == Module->FullDllName.MaximumLength) + Length -= sizeof(WCHAR); + + /* Break out of the loop */ + break; + } + + /* Advance to the next entry */ + Entry = Entry->Flink; + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + BaseSetLastNTError(_SEH2_GetExceptionCode()); + Length = 0; + } _SEH2_END + + /* Release the loader lock */ + LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie); + + return Length / sizeof(WCHAR); } +HMODULE +WINAPI +GetModuleHandleForUnicodeString(PUNICODE_STRING ModuleName) +{ + NTSTATUS Status; + PVOID Module; + LPWSTR DllPath; + + /* Try to get a handle with a magic value of 1 for DllPath */ + Status = LdrGetDllHandle((LPWSTR)1, NULL, ModuleName, &Module); + + /* If that succeeded - we're done */ + if (NT_SUCCESS(Status)) return Module; + + /* If not, then the path should be computed */ + DllPath = BasepGetDllPath(NULL, 0); + + /* Call LdrGetHandle() again providing the computed DllPath + and wrapped into SEH */ + _SEH2_TRY + { + Status = LdrGetDllHandle(DllPath, NULL, ModuleName, &Module); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Fail with the SEH error */ + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + /* Free the DllPath */ + RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath); + + /* In case of error set last win32 error and return NULL */ + if (!NT_SUCCESS(Status)) + { + DPRINT("Failure acquiring DLL module '%wZ' handle, Status 0x%08X\n", ModuleName, Status); + SetLastErrorByStatus(Status); + Module = 0; + } + + /* Return module */ + return (HMODULE)Module; +} + +BOOLEAN +WINAPI +BasepGetModuleHandleExW(BOOLEAN NoLock, DWORD dwPublicFlags, LPCWSTR lpwModuleName, HMODULE *phModule) +{ + DWORD Cookie; + NTSTATUS Status = STATUS_SUCCESS, Status2; + HANDLE hModule = 0; + UNICODE_STRING ModuleNameU; + DWORD dwValid; + BOOLEAN Redirected = FALSE; // FIXME + + /* Validate parameters */ + dwValid = BasepGetModuleHandleExParameterValidation(dwPublicFlags, lpwModuleName, phModule); + ASSERT(dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE); + + /* Acquire lock if necessary */ + if (!NoLock) + { + Status = LdrLockLoaderLock(0, NULL, &Cookie); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + SetLastErrorByStatus(Status); + if (phModule) *phModule = 0; + return Status; + } + } + + if (!(dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)) + { + /* Create a unicode string out of module name */ + RtlInitUnicodeString(&ModuleNameU, lpwModuleName); + + // FIXME: Do some redirected DLL stuff? + if (Redirected) + { + UNIMPLEMENTED; + } + + if (!hModule) + { + hModule = GetModuleHandleForUnicodeString(&ModuleNameU); + if (!hModule) + { + /* Last error is already set, so just return failure by setting status */ + Status = STATUS_DLL_NOT_FOUND; + goto quickie; + } + } + } + else + { + /* Perform Pc to file header to get module instance */ + hModule = (HMODULE)RtlPcToFileHeader((PVOID)lpwModuleName, + (PVOID*)&hModule); + + /* Check if it succeeded */ + if (!hModule) + { + /* Set "dll not found" status and quit */ + Status = STATUS_DLL_NOT_FOUND; + goto quickie; + } + } + + /* Check if changing reference is not forbidden */ + if (!(dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) + { + /* Add reference to this DLL */ + Status = LdrAddRefDll((dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) ? LDR_PIN_MODULE : 0, + hModule); + } + + /* Set last error in case of failure */ + if (!NT_SUCCESS(Status)) + SetLastErrorByStatus(Status); + +quickie: + /* Unlock loader lock if it was acquired */ + if (!NoLock) + { + Status2 = LdrUnlockLoaderLock(0, Cookie); + ASSERT(NT_SUCCESS(Status2)); + } + + /* Set the module handle to the caller */ + if (phModule) *phModule = hModule; + + /* Return TRUE on success and FALSE otherwise */ + return NT_SUCCESS(Status); +} /* * @implemented */ HMODULE WINAPI -GetModuleHandleA ( LPCSTR lpModuleName ) +GetModuleHandleA(LPCSTR lpModuleName) { - ANSI_STRING ModuleName; - NTSTATUS Status; - PTEB pTeb = NtCurrentTeb(); - - if (lpModuleName == NULL) - { - return ((HMODULE)pTeb->ProcessEnvironmentBlock->ImageBaseAddress); - } + PUNICODE_STRING ModuleNameW; + PTEB pTeb = NtCurrentTeb(); - RtlInitAnsiString(&ModuleName, lpModuleName); + /* Check if we have no name to convert */ + if (!lpModuleName) + return ((HMODULE)pTeb->ProcessEnvironmentBlock->ImageBaseAddress); - Status = RtlAnsiStringToUnicodeString(&pTeb->StaticUnicodeString, - &ModuleName, - FALSE); + /* Convert module name to unicode */ + ModuleNameW = Basep8BitStringToStaticUnicodeString(lpModuleName); - if (NT_SUCCESS(Status)) - { - return GetModuleHandleW(pTeb->StaticUnicodeString.Buffer); - } + /* Call W version if conversion was successful */ + if (ModuleNameW) + return GetModuleHandleW(ModuleNameW->Buffer); - SetLastErrorByStatus(Status); - return FALSE; + /* Return failure */ + return 0; } @@ -548,29 +926,26 @@ GetModuleHandleA ( LPCSTR lpModuleName ) */ HMODULE WINAPI -GetModuleHandleW (LPCWSTR lpModuleName) +GetModuleHandleW(LPCWSTR lpModuleName) { - UNICODE_STRING ModuleName; - PVOID BaseAddress; - NTSTATUS Status; + HMODULE hModule; + NTSTATUS Status; - if (lpModuleName == NULL) - return ((HMODULE)NtCurrentPeb()->ImageBaseAddress); + /* If current module is requested - return it right away */ + if (!lpModuleName) + return ((HMODULE)NtCurrentPeb()->ImageBaseAddress); - RtlInitUnicodeString (&ModuleName, - (LPWSTR)lpModuleName); + /* Use common helper routine */ + Status = BasepGetModuleHandleExW(TRUE, + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + lpModuleName, + &hModule); - Status = LdrGetDllHandle (0, - 0, - &ModuleName, - &BaseAddress); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus (Status); - return NULL; - } + /* If it wasn't successful - return 0 */ + if (!NT_SUCCESS(Status)) hModule = 0; - return ((HMODULE)BaseAddress); + /* Return the handle */ + return hModule; } @@ -580,64 +955,31 @@ GetModuleHandleW (LPCWSTR lpModuleName) BOOL WINAPI GetModuleHandleExW(IN DWORD dwFlags, - IN LPCWSTR lpModuleName OPTIONAL, + IN LPCWSTR lpwModuleName OPTIONAL, OUT HMODULE* phModule) { - HMODULE hModule; NTSTATUS Status; + DWORD dwValid; BOOL Ret = FALSE; - if (phModule == NULL || - ((dwFlags & (GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) == - (GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT))) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } + /* Validate parameters */ + dwValid = BasepGetModuleHandleExParameterValidation(dwFlags, lpwModuleName, phModule); - if (lpModuleName == NULL) - { - hModule = NtCurrentPeb()->ImageBaseAddress; - } - else - { - if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) - { - hModule = (HMODULE)RtlPcToFileHeader((PVOID)lpModuleName, - (PVOID*)&hModule); - if (hModule == NULL) - { - SetLastErrorByStatus(STATUS_DLL_NOT_FOUND); - } - } - else - { - hModule = GetModuleHandleW(lpModuleName); - } - } + /* If result is invalid parameter - return failure */ + if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR) return FALSE; - if (hModule != NULL) - { - if (!(dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) - { - Status = LdrAddRefDll((dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) ? LDR_PIN_MODULE : 0, - hModule); + /* If result is 2, there is no need to do anything - return success. */ + if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS) return TRUE; - if (NT_SUCCESS(Status)) - { - Ret = TRUE; - } - else - { - SetLastErrorByStatus(Status); - hModule = NULL; - } - } - else - Ret = TRUE; - } + /* Use common helper routine */ + Status = BasepGetModuleHandleExW(FALSE, + dwFlags, + lpwModuleName, + phModule); + + /* Return TRUE in case of success */ + if (NT_SUCCESS(Status)) Ret = TRUE; - *phModule = hModule; return Ret; } @@ -647,41 +989,52 @@ GetModuleHandleExW(IN DWORD dwFlags, BOOL WINAPI GetModuleHandleExA(IN DWORD dwFlags, - IN LPCSTR lpModuleName OPTIONAL, + IN LPCSTR lpModuleName OPTIONAL, OUT HMODULE* phModule) { - ANSI_STRING ModuleName; - LPCWSTR lpModuleNameW; + PUNICODE_STRING lpModuleNameW; + DWORD dwValid; + BOOL Ret = FALSE; NTSTATUS Status; - BOOL Ret; - PTEB pTeb = NtCurrentTeb(); + /* Validate parameters */ + dwValid = BasepGetModuleHandleExParameterValidation(dwFlags, (LPCWSTR)lpModuleName, phModule); + + /* If result is invalid parameter - return failure */ + if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR) return FALSE; + /* If result is 2, there is no need to do anything - return success. */ + if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS) return TRUE; + + /* Check if we don't need to convert the name */ if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) { - lpModuleNameW = (LPCWSTR)lpModuleName; + /* Call the extended version of the API without conversion */ + Status = BasepGetModuleHandleExW(FALSE, + dwFlags, + (LPCWSTR)lpModuleName, + phModule); } else { - RtlInitAnsiString(&ModuleName, lpModuleName); + /* Convert module name to unicode */ + lpModuleNameW = Basep8BitStringToStaticUnicodeString(lpModuleName); - Status = RtlAnsiStringToUnicodeString(&pTeb->StaticUnicodeString, - &ModuleName, - FALSE); + /* Return FALSE if conversion failed */ + if (!lpModuleNameW) return FALSE; - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } - - lpModuleNameW = pTeb->StaticUnicodeString.Buffer; + /* Call the extended version of the API */ + Status = BasepGetModuleHandleExW(FALSE, + dwFlags, + lpModuleNameW->Buffer, + phModule); } - Ret = GetModuleHandleExW(dwFlags, - lpModuleNameW, - phModule); + /* If result was successful - return true */ + if (NT_SUCCESS(Status)) + Ret = TRUE; + /* Return result */ return Ret; } @@ -691,87 +1044,137 @@ GetModuleHandleExA(IN DWORD dwFlags, */ DWORD WINAPI -LoadModule ( - LPCSTR lpModuleName, - LPVOID lpParameterBlock - ) +LoadModule(LPCSTR lpModuleName, + LPVOID lpParameterBlock) { - STARTUPINFOA StartupInfo; - PROCESS_INFORMATION ProcessInformation; - LOADPARMS32 *LoadParams; - char FileName[MAX_PATH]; - char *CommandLine, *t; - BYTE Length; - - LoadParams = (LOADPARMS32*)lpParameterBlock; - if(!lpModuleName || !LoadParams || (((WORD*)LoadParams->lpCmdShow)[0] != 2)) - { - /* windows doesn't check parameters, we do */ - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - if(!SearchPathA(NULL, lpModuleName, ".exe", MAX_PATH, FileName, NULL) && - !SearchPathA(NULL, lpModuleName, NULL, MAX_PATH, FileName, NULL)) - { - return ERROR_FILE_NOT_FOUND; - } - - Length = (BYTE)LoadParams->lpCmdLine[0]; - if(!(CommandLine = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, - strlen(lpModuleName) + Length + 2))) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - - /* Create command line string */ - strcpy(CommandLine, lpModuleName); - t = CommandLine + strlen(CommandLine); - *(t++) = ' '; - memcpy(t, LoadParams->lpCmdLine + 1, Length); - - /* Build StartupInfo */ - RtlZeroMemory(&StartupInfo, sizeof(STARTUPINFOA)); - StartupInfo.cb = sizeof(STARTUPINFOA); - StartupInfo.dwFlags = STARTF_USESHOWWINDOW; - StartupInfo.wShowWindow = ((WORD*)LoadParams->lpCmdShow)[1]; - - if(!CreateProcessA(FileName, CommandLine, NULL, NULL, FALSE, 0, LoadParams->lpEnvAddress, - NULL, &StartupInfo, &ProcessInformation)) - { - DWORD Error; - - RtlFreeHeap(RtlGetProcessHeap(), 0, CommandLine); - /* return the right value */ - Error = GetLastError(); - switch(Error) - { - case ERROR_BAD_EXE_FORMAT: - { - return ERROR_BAD_FORMAT; - } - case ERROR_FILE_NOT_FOUND: - case ERROR_PATH_NOT_FOUND: - { - return Error; - } + STARTUPINFOA StartupInfo; + PROCESS_INFORMATION ProcessInformation; + LOADPARMS32 *LoadParams; + char FileName[MAX_PATH]; + LPSTR CommandLine; + DWORD Length, Error; + BOOL ProcessStatus; + ANSI_STRING AnsiStr; + UNICODE_STRING UnicStr; + RTL_PATH_TYPE PathType; + HANDLE Handle; + + LoadParams = (LOADPARMS32*)lpParameterBlock; + + /* Check load parameters */ + if (LoadParams->dwReserved || LoadParams->wMagicValue != 2) + { + /* Fail with invalid param error */ + BaseSetLastNTError(STATUS_INVALID_PARAMETER); + return 0; } - return 0; - } - RtlFreeHeap(RtlGetProcessHeap(), 0, CommandLine); + /* Search path */ + Length = SearchPathA(NULL, lpModuleName, ".exe", MAX_PATH, FileName, NULL); + + /* Check if path was found */ + if (Length && Length < MAX_PATH) + { + /* Build StartupInfo */ + RtlZeroMemory(&StartupInfo, sizeof(StartupInfo)); + + StartupInfo.cb = sizeof(STARTUPINFOA); + StartupInfo.dwFlags = STARTF_USESHOWWINDOW; + StartupInfo.wShowWindow = LoadParams->wCmdShow; + + /* Allocate command line buffer */ + CommandLine = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + (ULONG)LoadParams->lpCmdLine[0] + Length + 2); + + /* Put module name there, then a space, and then copy provided command line, + and null-terminate it */ + RtlCopyMemory(CommandLine, FileName, Length); + CommandLine[Length] = ' '; + RtlCopyMemory(&CommandLine[Length + 1], &LoadParams->lpCmdLine[1], (ULONG)LoadParams->lpCmdLine[0]); + CommandLine[Length + 1 + (ULONG)LoadParams->lpCmdLine[0]] = 0; + + /* Create the process */ + ProcessStatus = CreateProcessA(FileName, + CommandLine, + NULL, + NULL, + FALSE, + 0, + LoadParams->lpEnvAddress, + NULL, + &StartupInfo, + &ProcessInformation); + + /* Free the command line buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, CommandLine); + + if (!ProcessStatus) + { + /* Creating process failed, return right error code */ + Error = GetLastError(); + switch(Error) + { + case ERROR_BAD_EXE_FORMAT: + return ERROR_BAD_FORMAT; + + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + return Error; + } + + /* Return 0 otherwise */ + return 0; + } + + /* Wait up to 30 seconds for the process to become idle */ + if (lpfnGlobalRegisterWaitForInputIdle) + { + lpfnGlobalRegisterWaitForInputIdle(ProcessInformation.hProcess, 30000); + } - /* Wait up to 15 seconds for the process to become idle */ - if (NULL != lpfnGlobalRegisterWaitForInputIdle) - { - lpfnGlobalRegisterWaitForInputIdle(ProcessInformation.hProcess, 15000); - } + /* Close handles */ + NtClose(ProcessInformation.hThread); + NtClose(ProcessInformation.hProcess); - NtClose(ProcessInformation.hThread); - NtClose(ProcessInformation.hProcess); + /* Return magic success value (33) */ + return 33; + } + + /* The path was not found, create an ansi string from + the module name and convert it to unicode */ + RtlInitAnsiString(&AnsiStr, lpModuleName); + if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicStr,&AnsiStr,TRUE))) + return ERROR_FILE_NOT_FOUND; + + /* Determine path type */ + PathType = RtlDetermineDosPathNameType_U(UnicStr.Buffer); + + /* Free the unicode module name */ + RtlFreeUnicodeString(&UnicStr); + + /* If it's a relative path, return file not found */ + if (PathType == RtlPathTypeRelative) + return ERROR_FILE_NOT_FOUND; + + /* If not, try to open it */ + Handle = CreateFile(lpModuleName, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (Handle != INVALID_HANDLE_VALUE) + { + /* Opening file succeeded for some reason, close the handle and return file not found anyway */ + CloseHandle(Handle); + return ERROR_FILE_NOT_FOUND; + } - return 33; + /* Return last error which CreateFile set during an attempt to open it */ + return GetLastError(); } /* EOF */