2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT : ReactOS system libraries
4 * MODULE : kernel32.dll
5 * FILE : reactos/dll/win32/kernel32/misc/ldr.c
6 * AUTHOR : Aleksey Bragin <aleksey@reactos.org>
14 /* FUNCTIONS ****************************************************************/
18 BasepGetModuleHandleExParameterValidation(DWORD dwFlags
,
19 LPCWSTR lpwModuleName
,
22 /* Set phModule to 0 if it's not a NULL pointer */
23 if (phModule
) *phModule
= 0;
25 /* Check for invalid flags combination */
26 if (dwFlags
& ~(GET_MODULE_HANDLE_EX_FLAG_PIN
|
27 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
|
28 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
) ||
29 ((dwFlags
& GET_MODULE_HANDLE_EX_FLAG_PIN
) &&
30 (dwFlags
& GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
)) ||
31 (!lpwModuleName
&& (dwFlags
& GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
))
34 BaseSetLastNTError(STATUS_INVALID_PARAMETER_1
);
35 return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR
;
38 /* Check 2nd parameter */
41 BaseSetLastNTError(STATUS_INVALID_PARAMETER_2
);
42 return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR
;
45 /* Return what we have according to the module name */
48 return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE
;
51 /* No name given, so put ImageBaseAddress there */
52 *phModule
= (HMODULE
)NtCurrentPeb()->ImageBaseAddress
;
54 return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS
;
59 BasepMapModuleHandle(HMODULE hModule
, BOOLEAN AsDataFile
)
61 /* If no handle is provided - use current image base address */
62 if (!hModule
) return NtCurrentPeb()->ImageBaseAddress
;
64 /* Check if it's a normal or a datafile one */
65 if (LDR_IS_DATAFILE(hModule
) && !AsDataFile
)
68 /* It'a a normal DLL, just return its handle */
77 DisableThreadLibraryCalls(
78 IN HMODULE hLibModule
)
82 /* Disable thread library calls */
83 Status
= LdrDisableThreadCalloutsForDll((PVOID
)hLibModule
);
85 /* If it wasn't success - set last error and return failure */
86 if (!NT_SUCCESS(Status
))
88 BaseSetLastNTError(Status
);
102 LoadLibraryA(LPCSTR lpLibFileName
)
108 /* Treat twain_32.dll in a special way (what a surprise...) */
109 if (lpLibFileName
&& !_strcmpi(lpLibFileName
, "twain_32.dll"))
111 /* Allocate space for the buffer */
112 PathBuffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH
);
115 /* Get windows dir in this buffer */
116 Len
= GetWindowsDirectoryA(PathBuffer
, MAX_PATH
- 13); /* 13 is sizeof of '\\twain_32.dll' */
117 if (Len
&& Len
< (MAX_PATH
- 13))
119 /* We successfully got windows directory. Concatenate twain_32.dll to it */
120 strncat(PathBuffer
, "\\twain_32.dll", 13);
122 /* And recursively call ourselves with a new string */
123 Result
= LoadLibraryA(PathBuffer
);
125 /* If it was successful - free memory and return result */
128 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer
);
133 /* Free allocated buffer */
134 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer
);
138 /* Call the Ex version of the API */
139 return LoadLibraryExA(lpLibFileName
, 0, 0);
147 LoadLibraryExA(LPCSTR lpLibFileName
,
151 PUNICODE_STRING FileNameW
;
153 /* Convert file name to unicode */
154 if (!(FileNameW
= Basep8BitStringToStaticUnicodeString(lpLibFileName
)))
157 /* And call W version of the API */
158 return LoadLibraryExW(FileNameW
->Buffer
, hFile
, dwFlags
);
166 LoadLibraryW(LPCWSTR lpLibFileName
)
168 /* Call Ex version of the API */
169 return LoadLibraryExW (lpLibFileName
, 0, 0);
175 BasepLoadLibraryAsDatafile(PWSTR Path
, LPCWSTR Name
, HMODULE
*hModule
)
177 WCHAR FilenameW
[MAX_PATH
];
178 HANDLE hFile
= INVALID_HANDLE_VALUE
;
181 PVOID lpBaseAddress
= NULL
;
183 //PUNICODE_STRING OriginalName;
184 //UNICODE_STRING dotDLL = RTL_CONSTANT_STRING(L".DLL");
186 /* Zero out handle value */
189 DPRINT("BasepLoadLibraryAsDatafile(%S %S %p)\n", Path
, Name
, hModule
);
191 /*Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
201 /* Try to search for it */
202 if (!SearchPathW(Path
,
205 sizeof(FilenameW
) / sizeof(FilenameW
[0]),
209 /* Return last status value directly */
210 return NtCurrentTeb()->LastStatusValue
;
213 /* Open this file we found */
214 hFile
= CreateFileW(FilenameW
,
216 FILE_SHARE_READ
| FILE_SHARE_DELETE
,
222 /* If opening failed - return last status value */
223 if (hFile
== INVALID_HANDLE_VALUE
) return NtCurrentTeb()->LastStatusValue
;
225 /* Create file mapping */
226 hMapping
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
228 /* Close the file handle */
231 /* If creating file mapping failed - return last status value */
232 if (!hMapping
) return NtCurrentTeb()->LastStatusValue
;
234 /* Map view of section */
235 Status
= NtMapViewOfSection(hMapping
,
246 /* Close handle to the section */
247 CloseHandle(hMapping
);
249 /* If mapping view of section failed - return last status value */
250 if (!NT_SUCCESS(Status
)) return NtCurrentTeb()->LastStatusValue
;
252 /* Make sure it's a valid PE file */
253 if (!RtlImageNtHeader(lpBaseAddress
))
255 /* Unmap the view and return failure status */
256 UnmapViewOfFile(lpBaseAddress
);
257 return STATUS_INVALID_IMAGE_FORMAT
;
260 /* Set low bit of handle to indicate datafile module */
261 *hModule
= (HMODULE
)((ULONG_PTR
)lpBaseAddress
| 1);
263 /* Load alternate resource module */
264 //LdrLoadAlternateResourceModule(*hModule, FilenameW);
266 return STATUS_SUCCESS
;
274 LoadLibraryExW(LPCWSTR lpLibFileName
,
278 UNICODE_STRING DllName
;
282 ULONG DllCharacteristics
= 0;
283 BOOL FreeString
= FALSE
;
285 /* Check for any flags LdrLoadDll might be interested in */
286 if (dwFlags
& DONT_RESOLVE_DLL_REFERENCES
)
288 /* Tell LDR to treat it as an EXE */
289 DllCharacteristics
= IMAGE_FILE_EXECUTABLE_IMAGE
;
292 /* Build up a unicode dll name from null-terminated string */
293 RtlInitUnicodeString(&DllName
, (LPWSTR
)lpLibFileName
);
295 /* Lazy-initialize BasepExeLdrEntry */
296 if (!BasepExeLdrEntry
)
297 LdrEnumerateLoadedModules(0, BasepLocateExeLdrEntry
, NtCurrentPeb()->ImageBaseAddress
);
299 /* Check if that module is our exe*/
300 if (BasepExeLdrEntry
&& !(dwFlags
& LOAD_LIBRARY_AS_DATAFILE
) &&
301 DllName
.Length
== BasepExeLdrEntry
->FullDllName
.Length
)
303 /* Lengths match and it's not a datafile, so perform name comparison */
304 if (RtlEqualUnicodeString(&DllName
, &BasepExeLdrEntry
->FullDllName
, TRUE
))
307 return BasepExeLdrEntry
->DllBase
;
311 /* Check for trailing spaces and remove them if necessary */
312 if (DllName
.Buffer
[DllName
.Length
/sizeof(WCHAR
) - 1] == L
' ')
314 RtlCreateUnicodeString(&DllName
, (LPWSTR
)lpLibFileName
);
315 while (DllName
.Length
> sizeof(WCHAR
) &&
316 DllName
.Buffer
[DllName
.Length
/sizeof(WCHAR
) - 1] == L
' ')
318 DllName
.Length
-= sizeof(WCHAR
);
320 DllName
.Buffer
[DllName
.Length
/sizeof(WCHAR
)] = UNICODE_NULL
;
324 /* Compute the load path */
325 SearchPath
= BaseComputeProcessDllPath((dwFlags
& LOAD_WITH_ALTERED_SEARCH_PATH
) ?
326 DllName
.Buffer
: NULL
,
330 /* Getting DLL path failed, so set last error, free mem and return */
331 BaseSetLastNTError(STATUS_NO_MEMORY
);
332 if (FreeString
) RtlFreeUnicodeString(&DllName
);
338 if (dwFlags
& LOAD_LIBRARY_AS_DATAFILE
)
340 /* If the image is loaded as a datafile, try to get its handle */
341 Status
= LdrGetDllHandleEx(0, SearchPath
, NULL
, &DllName
, (PVOID
*)&hInst
);
342 if (!NT_SUCCESS(Status
))
344 /* It's not loaded yet - so load it up */
345 Status
= BasepLoadLibraryAsDatafile(SearchPath
, DllName
.Buffer
, &hInst
);
347 _SEH2_YIELD(goto done
;)
350 /* Call the API Properly */
351 Status
= LdrLoadDll(SearchPath
,
356 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
358 Status
= _SEH2_GetExceptionCode();
363 /* Free SearchPath buffer */
364 RtlFreeHeap(RtlGetProcessHeap(), 0, SearchPath
);
366 /* Free DllName string if it was dynamically allocated */
367 if (FreeString
) RtlFreeUnicodeString(&DllName
);
369 /* Set last error in failure case */
370 if (!NT_SUCCESS(Status
))
372 BaseSetLastNTError(Status
);
376 /* Return loaded module handle */
386 GetProcAddress(HMODULE hModule
, LPCSTR lpProcName
)
388 ANSI_STRING ProcedureName
, *ProcNamePtr
= NULL
;
389 FARPROC fnExp
= NULL
;
394 if (HIWORD(lpProcName
) != 0)
396 /* Look up by name */
397 RtlInitAnsiString(&ProcedureName
, (LPSTR
)lpProcName
);
398 ProcNamePtr
= &ProcedureName
;
402 /* Look up by ordinal */
403 Ordinal
= (ULONG
)lpProcName
;
406 /* Map provided handle */
407 hMapped
= BasepMapModuleHandle(hModule
, FALSE
);
409 /* Get the proc address */
410 Status
= LdrGetProcedureAddress(hMapped
,
415 if (!NT_SUCCESS(Status
))
417 BaseSetLastNTError(Status
);
421 /* Check for a special case when returned pointer is
422 the same as iamge's base address */
423 if (fnExp
== hMapped
)
425 /* Set correct error code */
426 if (HIWORD(lpProcName
) != 0)
427 BaseSetLastNTError(STATUS_ENTRYPOINT_NOT_FOUND
);
429 BaseSetLastNTError(STATUS_ORDINAL_NOT_FOUND
);
434 /* All good, return procedure pointer */
442 BOOL WINAPI
FreeLibrary(HINSTANCE hLibModule
)
445 PIMAGE_NT_HEADERS NtHeaders
;
447 if (LDR_IS_DATAFILE(hLibModule
))
449 // FIXME: This SEH should go inside RtlImageNtHeader instead
452 /* This is a LOAD_LIBRARY_AS_DATAFILE module, check if it's a valid one */
453 NtHeaders
= RtlImageNtHeader((PVOID
)((ULONG_PTR
)hLibModule
& ~1));
455 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
463 Status
= NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)((ULONG_PTR
)hLibModule
& ~1));
465 /* Unload alternate resource module */
466 LdrUnloadAlternateResourceModule(hLibModule
);
469 Status
= STATUS_INVALID_IMAGE_FORMAT
;
474 Status
= LdrUnloadDll((PVOID
)hLibModule
);
477 /* Check what kind of status we got */
478 if (!NT_SUCCESS(Status
))
481 BaseSetLastNTError(Status
);
497 FreeLibraryAndExitThread(HMODULE hLibModule
,
501 if (LDR_IS_DATAFILE(hLibModule
))
503 /* This is a LOAD_LIBRARY_AS_DATAFILE module */
504 if (RtlImageNtHeader((PVOID
)((ULONG_PTR
)hLibModule
& ~1)))
507 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)((ULONG_PTR
)hLibModule
& ~1));
509 /* Unload alternate resource module */
510 LdrUnloadAlternateResourceModule(hLibModule
);
516 LdrUnloadDll((PVOID
)hLibModule
);
520 ExitThread(dwExitCode
);
529 GetModuleFileNameA(HINSTANCE hModule
,
533 UNICODE_STRING FilenameW
;
534 ANSI_STRING FilenameA
;
536 DWORD Length
= 0, LengthToCopy
;
538 /* Allocate a unicode buffer */
539 FilenameW
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, nSize
* sizeof(WCHAR
));
540 if (!FilenameW
.Buffer
)
542 BaseSetLastNTError(STATUS_NO_MEMORY
);
546 /* Call unicode API */
547 FilenameW
.Length
= GetModuleFileNameW(hModule
, FilenameW
.Buffer
, nSize
) * sizeof(WCHAR
);
548 FilenameW
.MaximumLength
= FilenameW
.Length
+ sizeof(WCHAR
);
550 if (FilenameW
.Length
)
552 /* Convert to ansi string */
553 Status
= BasepUnicodeStringTo8BitString(&FilenameA
, &FilenameW
, TRUE
);
554 if (!NT_SUCCESS(Status
))
556 /* Set last error, free string and retun failure */
557 BaseSetLastNTError(Status
);
558 RtlFreeUnicodeString(&FilenameW
);
562 /* Calculate size to copy */
563 Length
= min(nSize
, FilenameA
.Length
);
565 /* Include terminating zero */
567 LengthToCopy
= Length
+ 1;
569 LengthToCopy
= nSize
;
571 /* Now copy back to the caller amount he asked */
572 RtlMoveMemory(lpFilename
, FilenameA
.Buffer
, LengthToCopy
);
574 /* Free ansi filename */
575 RtlFreeAnsiString(&FilenameA
);
578 /* Free unicode filename */
579 RtlFreeHeap(RtlGetProcessHeap(), 0, FilenameW
.Buffer
);
581 /* Return length copied */
590 GetModuleFileNameW(HINSTANCE hModule
,
594 PLIST_ENTRY ModuleListHead
, Entry
;
595 PLDR_DATA_TABLE_ENTRY Module
;
600 hModule
= BasepMapModuleHandle(hModule
, FALSE
);
602 /* Upscale nSize from chars to bytes */
603 nSize
*= sizeof(WCHAR
);
607 /* We don't use per-thread cur dir now */
608 //PRTL_PERTHREAD_CURDIR PerThreadCurdir = (PRTL_PERTHREAD_CURDIR)teb->NtTib.SubSystemTib;
610 Peb
= NtCurrentPeb ();
612 /* Acquire a loader lock */
613 LdrLockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS
, NULL
, &Cookie
);
615 /* Traverse the module list */
616 ModuleListHead
= &Peb
->Ldr
->InLoadOrderModuleList
;
617 Entry
= ModuleListHead
->Flink
;
618 while (Entry
!= ModuleListHead
)
620 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
622 /* Check if this is the requested module */
623 if (Module
->DllBase
== (PVOID
)hModule
)
625 /* Calculate size to copy */
626 Length
= min(nSize
, Module
->FullDllName
.MaximumLength
);
629 RtlMoveMemory(lpFilename
, Module
->FullDllName
.Buffer
, Length
);
631 /* Subtract a terminating zero */
632 if (Length
== Module
->FullDllName
.MaximumLength
)
633 Length
-= sizeof(WCHAR
);
635 /* Break out of the loop */
639 /* Advance to the next entry */
640 Entry
= Entry
->Flink
;
643 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
645 BaseSetLastNTError(_SEH2_GetExceptionCode());
649 /* Release the loader lock */
650 LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS
, Cookie
);
652 return Length
/ sizeof(WCHAR
);
657 GetModuleHandleForUnicodeString(PUNICODE_STRING ModuleName
)
663 /* Try to get a handle with a magic value of 1 for DllPath */
664 Status
= LdrGetDllHandle((LPWSTR
)1, NULL
, ModuleName
, &Module
);
666 /* If that succeeded - we're done */
667 if (NT_SUCCESS(Status
)) return Module
;
669 /* If not, then the path should be computed */
670 DllPath
= BaseComputeProcessDllPath(NULL
, 0);
673 Status
= STATUS_NO_MEMORY
;
679 Status
= LdrGetDllHandle(DllPath
, NULL
, ModuleName
, &Module
);
681 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
683 /* Fail with the SEH error */
684 Status
= _SEH2_GetExceptionCode();
689 /* Free the DllPath */
690 RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath
);
692 /* In case of error set last win32 error and return NULL */
693 if (!NT_SUCCESS(Status
))
695 DPRINT("Failure acquiring DLL module '%wZ' handle, Status 0x%08X\n", ModuleName
, Status
);
696 BaseSetLastNTError(Status
);
701 return (HMODULE
)Module
;
706 BasepGetModuleHandleExW(BOOLEAN NoLock
, DWORD dwPublicFlags
, LPCWSTR lpwModuleName
, HMODULE
*phModule
)
709 NTSTATUS Status
= STATUS_SUCCESS
, Status2
;
711 UNICODE_STRING ModuleNameU
;
713 BOOLEAN Redirected
= FALSE
; // FIXME
715 /* Validate parameters */
716 dwValid
= BasepGetModuleHandleExParameterValidation(dwPublicFlags
, lpwModuleName
, phModule
);
717 ASSERT(dwValid
== BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE
);
719 /* Acquire lock if necessary */
722 Status
= LdrLockLoaderLock(0, NULL
, &Cookie
);
723 if (!NT_SUCCESS(Status
))
726 BaseSetLastNTError(Status
);
727 if (phModule
) *phModule
= 0;
728 return NT_SUCCESS(Status
);
732 if (!(dwPublicFlags
& GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
))
734 /* Create a unicode string out of module name */
735 RtlInitUnicodeString(&ModuleNameU
, lpwModuleName
);
737 // FIXME: Do some redirected DLL stuff?
745 hModule
= GetModuleHandleForUnicodeString(&ModuleNameU
);
748 /* Last error is already set, so just return failure by setting status */
749 Status
= STATUS_DLL_NOT_FOUND
;
756 /* Perform Pc to file header to get module instance */
757 hModule
= (HMODULE
)RtlPcToFileHeader((PVOID
)lpwModuleName
,
760 /* Check if it succeeded */
763 /* Set "dll not found" status and quit */
764 Status
= STATUS_DLL_NOT_FOUND
;
769 /* Check if changing reference is not forbidden */
770 if (!(dwPublicFlags
& GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
))
772 /* Add reference to this DLL */
773 Status
= LdrAddRefDll((dwPublicFlags
& GET_MODULE_HANDLE_EX_FLAG_PIN
) ? LDR_ADDREF_DLL_PIN
: 0,
777 /* Set last error in case of failure */
778 if (!NT_SUCCESS(Status
))
779 BaseSetLastNTError(Status
);
782 /* Unlock loader lock if it was acquired */
785 Status2
= LdrUnlockLoaderLock(0, Cookie
);
786 ASSERT(NT_SUCCESS(Status2
));
789 /* Set the module handle to the caller */
790 if (phModule
) *phModule
= hModule
;
792 /* Return TRUE on success and FALSE otherwise */
793 return NT_SUCCESS(Status
);
801 GetModuleHandleA(LPCSTR lpModuleName
)
803 PUNICODE_STRING ModuleNameW
;
804 PTEB pTeb
= NtCurrentTeb();
806 /* Check if we have no name to convert */
808 return ((HMODULE
)pTeb
->ProcessEnvironmentBlock
->ImageBaseAddress
);
810 /* Convert module name to unicode */
811 ModuleNameW
= Basep8BitStringToStaticUnicodeString(lpModuleName
);
813 /* Call W version if conversion was successful */
815 return GetModuleHandleW(ModuleNameW
->Buffer
);
827 GetModuleHandleW(LPCWSTR lpModuleName
)
832 /* If current module is requested - return it right away */
834 return ((HMODULE
)NtCurrentPeb()->ImageBaseAddress
);
836 /* Use common helper routine */
837 Status
= BasepGetModuleHandleExW(TRUE
,
838 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
,
842 /* If it wasn't successful - return 0 */
843 if (!NT_SUCCESS(Status
)) hModule
= 0;
845 /* Return the handle */
855 GetModuleHandleExW(IN DWORD dwFlags
,
856 IN LPCWSTR lpwModuleName OPTIONAL
,
857 OUT HMODULE
* phModule
)
863 /* Validate parameters */
864 dwValid
= BasepGetModuleHandleExParameterValidation(dwFlags
, lpwModuleName
, phModule
);
866 /* If result is invalid parameter - return failure */
867 if (dwValid
== BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR
) return FALSE
;
869 /* If result is 2, there is no need to do anything - return success. */
870 if (dwValid
== BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS
) return TRUE
;
872 /* Use common helper routine */
873 Status
= BasepGetModuleHandleExW(FALSE
,
878 /* Return TRUE in case of success */
879 if (NT_SUCCESS(Status
)) Ret
= TRUE
;
889 GetModuleHandleExA(IN DWORD dwFlags
,
890 IN LPCSTR lpModuleName OPTIONAL
,
891 OUT HMODULE
* phModule
)
893 PUNICODE_STRING lpModuleNameW
;
898 /* Validate parameters */
899 dwValid
= BasepGetModuleHandleExParameterValidation(dwFlags
, (LPCWSTR
)lpModuleName
, phModule
);
901 /* If result is invalid parameter - return failure */
902 if (dwValid
== BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR
) return FALSE
;
904 /* If result is 2, there is no need to do anything - return success. */
905 if (dwValid
== BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS
) return TRUE
;
907 /* Check if we don't need to convert the name */
908 if (dwFlags
& GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
)
910 /* Call the extended version of the API without conversion */
911 Status
= BasepGetModuleHandleExW(FALSE
,
913 (LPCWSTR
)lpModuleName
,
918 /* Convert module name to unicode */
919 lpModuleNameW
= Basep8BitStringToStaticUnicodeString(lpModuleName
);
921 /* Return FALSE if conversion failed */
922 if (!lpModuleNameW
) return FALSE
;
924 /* Call the extended version of the API */
925 Status
= BasepGetModuleHandleExW(FALSE
,
927 lpModuleNameW
->Buffer
,
931 /* If result was successful - return true */
932 if (NT_SUCCESS(Status
))
945 LoadModule(LPCSTR lpModuleName
,
946 LPVOID lpParameterBlock
)
948 STARTUPINFOA StartupInfo
;
949 PROCESS_INFORMATION ProcessInformation
;
950 LOADPARMS32
*LoadParams
;
951 char FileName
[MAX_PATH
];
956 UNICODE_STRING UnicStr
;
957 RTL_PATH_TYPE PathType
;
960 LoadParams
= (LOADPARMS32
*)lpParameterBlock
;
962 /* Check load parameters */
963 if (LoadParams
->dwReserved
|| LoadParams
->wMagicValue
!= 2)
965 /* Fail with invalid param error */
966 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
971 Length
= SearchPathA(NULL
, lpModuleName
, ".exe", MAX_PATH
, FileName
, NULL
);
973 /* Check if path was found */
974 if (Length
&& Length
< MAX_PATH
)
976 /* Build StartupInfo */
977 RtlZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
979 StartupInfo
.cb
= sizeof(STARTUPINFOA
);
980 StartupInfo
.dwFlags
= STARTF_USESHOWWINDOW
;
981 StartupInfo
.wShowWindow
= LoadParams
->wCmdShow
;
983 /* Allocate command line buffer */
984 CommandLine
= RtlAllocateHeap(RtlGetProcessHeap(),
986 (ULONG
)LoadParams
->lpCmdLine
[0] + Length
+ 2);
988 /* Put module name there, then a space, and then copy provided command line,
989 and null-terminate it */
990 RtlCopyMemory(CommandLine
, FileName
, Length
);
991 CommandLine
[Length
] = ' ';
992 RtlCopyMemory(&CommandLine
[Length
+ 1], &LoadParams
->lpCmdLine
[1], (ULONG
)LoadParams
->lpCmdLine
[0]);
993 CommandLine
[Length
+ 1 + (ULONG
)LoadParams
->lpCmdLine
[0]] = 0;
995 /* Create the process */
996 ProcessStatus
= CreateProcessA(FileName
,
1002 LoadParams
->lpEnvAddress
,
1005 &ProcessInformation
);
1007 /* Free the command line buffer */
1008 RtlFreeHeap(RtlGetProcessHeap(), 0, CommandLine
);
1012 /* Creating process failed, return right error code */
1013 Error
= GetLastError();
1016 case ERROR_BAD_EXE_FORMAT
:
1017 return ERROR_BAD_FORMAT
;
1019 case ERROR_FILE_NOT_FOUND
:
1020 case ERROR_PATH_NOT_FOUND
:
1024 /* Return 0 otherwise */
1028 /* Wait up to 30 seconds for the process to become idle */
1029 if (UserWaitForInputIdleRoutine
)
1031 UserWaitForInputIdleRoutine(ProcessInformation
.hProcess
, 30000);
1035 NtClose(ProcessInformation
.hThread
);
1036 NtClose(ProcessInformation
.hProcess
);
1038 /* Return magic success value (33) */
1042 /* The path was not found, create an ansi string from
1043 the module name and convert it to unicode */
1044 RtlInitAnsiString(&AnsiStr
, lpModuleName
);
1045 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicStr
,&AnsiStr
,TRUE
)))
1046 return ERROR_FILE_NOT_FOUND
;
1048 /* Determine path type */
1049 PathType
= RtlDetermineDosPathNameType_U(UnicStr
.Buffer
);
1051 /* Free the unicode module name */
1052 RtlFreeUnicodeString(&UnicStr
);
1054 /* If it's a relative path, return file not found */
1055 if (PathType
== RtlPathTypeRelative
)
1056 return ERROR_FILE_NOT_FOUND
;
1058 /* If not, try to open it */
1059 Handle
= CreateFile(lpModuleName
,
1061 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1064 FILE_ATTRIBUTE_NORMAL
,
1067 if (Handle
!= INVALID_HANDLE_VALUE
)
1069 /* Opening file succeeded for some reason, close the handle and return file not found anyway */
1070 CloseHandle(Handle
);
1071 return ERROR_FILE_NOT_FOUND
;
1074 /* Return last error which CreateFile set during an attempt to open it */
1075 return GetLastError();
1081 FARPROC WINAPI
DelayLoadFailureHook(LPCSTR pszDllName
, LPCSTR pszProcName
)
1090 BOOL WINAPI
UTRegister( HMODULE hModule
, LPSTR lpsz16BITDLL
,
1091 LPSTR lpszInitName
, LPSTR lpszProcName
,
1092 FARPROC
*ppfn32Thunk
, FARPROC pfnUT32CallBack
,
1102 VOID WINAPI
UTUnRegister( HMODULE hModule
)
1112 BaseQueryModuleData(IN LPSTR ModuleName
,
1118 DPRINT1("BaseQueryModuleData called: %s %s %x %x %x\n",
1132 BaseProcessInitPostImport(VOID
)
1134 /* FIXME: Initialize TS pointers */
1135 return STATUS_SUCCESS
;