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 BasepInitializeTermsrvFpns(VOID
)
21 return STATUS_NOT_IMPLEMENTED
;
26 BasepGetModuleHandleExParameterValidation(DWORD dwFlags
,
27 LPCWSTR lpwModuleName
,
30 /* Set phModule to 0 if it's not a NULL pointer */
31 if (phModule
) *phModule
= 0;
33 /* Check for invalid flags combination */
34 if (dwFlags
& ~(GET_MODULE_HANDLE_EX_FLAG_PIN
|
35 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
|
36 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
) ||
37 ((dwFlags
& GET_MODULE_HANDLE_EX_FLAG_PIN
) &&
38 (dwFlags
& GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
)) ||
39 (!lpwModuleName
&& (dwFlags
& GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
))
42 BaseSetLastNTError(STATUS_INVALID_PARAMETER_1
);
43 return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR
;
46 /* Check 2nd parameter */
49 BaseSetLastNTError(STATUS_INVALID_PARAMETER_2
);
50 return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR
;
53 /* Return what we have according to the module name */
56 return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE
;
59 /* No name given, so put ImageBaseAddress there */
60 *phModule
= (HMODULE
)NtCurrentPeb()->ImageBaseAddress
;
62 return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS
;
67 BasepMapModuleHandle(HMODULE hModule
, BOOLEAN AsDataFile
)
69 /* If no handle is provided - use current image base address */
70 if (!hModule
) return NtCurrentPeb()->ImageBaseAddress
;
72 /* Check if it's a normal or a datafile one */
73 if (LDR_IS_DATAFILE(hModule
) && !AsDataFile
)
76 /* It'a a normal DLL, just return its handle */
85 DisableThreadLibraryCalls(
86 IN HMODULE hLibModule
)
90 /* Disable thread library calls */
91 Status
= LdrDisableThreadCalloutsForDll((PVOID
)hLibModule
);
93 /* If it wasn't success - set last error and return failure */
94 if (!NT_SUCCESS(Status
))
96 BaseSetLastNTError(Status
);
111 LoadLibraryA(LPCSTR lpLibFileName
)
117 /* Treat twain_32.dll in a special way (what a surprise...) */
118 if (lpLibFileName
&& !_strcmpi(lpLibFileName
, "twain_32.dll"))
120 /* Allocate space for the buffer */
121 PathBuffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH
);
124 /* Get windows dir in this buffer */
125 Len
= GetWindowsDirectoryA(PathBuffer
, MAX_PATH
- 13); /* 13 is sizeof of '\\twain_32.dll' */
126 if (Len
&& Len
< (MAX_PATH
- 13))
128 /* We successfully got windows directory. Concatenate twain_32.dll to it */
129 strncat(PathBuffer
, "\\twain_32.dll", 13);
131 /* And recursively call ourselves with a new string */
132 Result
= LoadLibraryA(PathBuffer
);
134 /* If it was successful - free memory and return result */
137 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer
);
142 /* Free allocated buffer */
143 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer
);
147 /* Call the Ex version of the API */
148 return LoadLibraryExA(lpLibFileName
, 0, 0);
157 LoadLibraryExA(LPCSTR lpLibFileName
,
161 PUNICODE_STRING FileNameW
;
163 /* Convert file name to unicode */
164 if (!(FileNameW
= Basep8BitStringToStaticUnicodeString(lpLibFileName
)))
167 /* And call W version of the API */
168 return LoadLibraryExW(FileNameW
->Buffer
, hFile
, dwFlags
);
177 LoadLibraryW(LPCWSTR lpLibFileName
)
179 /* Call Ex version of the API */
180 return LoadLibraryExW (lpLibFileName
, 0, 0);
186 BasepLoadLibraryAsDatafile(PWSTR Path
, LPCWSTR Name
, HMODULE
*hModule
)
188 WCHAR FilenameW
[MAX_PATH
];
189 HANDLE hFile
= INVALID_HANDLE_VALUE
;
192 PVOID lpBaseAddress
= NULL
;
194 //PUNICODE_STRING OriginalName;
195 //UNICODE_STRING dotDLL = RTL_CONSTANT_STRING(L".DLL");
197 /* Zero out handle value */
200 DPRINT("BasepLoadLibraryAsDatafile(%S %S %p)\n", Path
, Name
, hModule
);
202 /*Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
212 /* Try to search for it */
213 if (!SearchPathW(Path
,
216 sizeof(FilenameW
) / sizeof(FilenameW
[0]),
220 /* Return last status value directly */
221 return NtCurrentTeb()->LastStatusValue
;
224 /* Open this file we found */
225 hFile
= CreateFileW(FilenameW
,
227 FILE_SHARE_READ
| FILE_SHARE_DELETE
,
233 /* If opening failed - return last status value */
234 if (hFile
== INVALID_HANDLE_VALUE
) return NtCurrentTeb()->LastStatusValue
;
236 /* Create file mapping */
237 hMapping
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
239 /* Close the file handle */
242 /* If creating file mapping failed - return last status value */
243 if (!hMapping
) return NtCurrentTeb()->LastStatusValue
;
245 /* Map view of section */
246 Status
= NtMapViewOfSection(hMapping
,
257 /* Close handle to the section */
258 CloseHandle(hMapping
);
260 /* If mapping view of section failed - return last status value */
261 if (!NT_SUCCESS(Status
)) return NtCurrentTeb()->LastStatusValue
;
263 /* Make sure it's a valid PE file */
264 if (!RtlImageNtHeader(lpBaseAddress
))
266 /* Unmap the view and return failure status */
267 UnmapViewOfFile(lpBaseAddress
);
268 return STATUS_INVALID_IMAGE_FORMAT
;
271 /* Set low bit of handle to indicate datafile module */
272 *hModule
= (HMODULE
)((ULONG_PTR
)lpBaseAddress
| 1);
274 /* Load alternate resource module */
275 //LdrLoadAlternateResourceModule(*hModule, FilenameW);
277 return STATUS_SUCCESS
;
286 LoadLibraryExW(LPCWSTR lpLibFileName
,
290 UNICODE_STRING DllName
;
294 ULONG DllCharacteristics
= 0;
295 BOOL FreeString
= FALSE
;
297 /* Check for any flags LdrLoadDll might be interested in */
298 if (dwFlags
& DONT_RESOLVE_DLL_REFERENCES
)
300 /* Tell LDR to treat it as an EXE */
301 DllCharacteristics
= IMAGE_FILE_EXECUTABLE_IMAGE
;
304 /* Build up a unicode dll name from null-terminated string */
305 RtlInitUnicodeString(&DllName
, (LPWSTR
)lpLibFileName
);
307 /* Lazy-initialize BasepExeLdrEntry */
308 if (!BasepExeLdrEntry
)
309 LdrEnumerateLoadedModules(0, BasepLocateExeLdrEntry
, NtCurrentPeb()->ImageBaseAddress
);
311 /* Check if that module is our exe*/
312 if (BasepExeLdrEntry
&& !(dwFlags
& LOAD_LIBRARY_AS_DATAFILE
) &&
313 DllName
.Length
== BasepExeLdrEntry
->FullDllName
.Length
)
315 /* Lengths match and it's not a datafile, so perform name comparison */
316 if (RtlEqualUnicodeString(&DllName
, &BasepExeLdrEntry
->FullDllName
, TRUE
))
319 return BasepExeLdrEntry
->DllBase
;
323 /* Check for trailing spaces and remove them if necessary */
324 if (DllName
.Buffer
[DllName
.Length
/sizeof(WCHAR
) - 1] == L
' ')
326 RtlCreateUnicodeString(&DllName
, (LPWSTR
)lpLibFileName
);
327 while (DllName
.Length
> sizeof(WCHAR
) &&
328 DllName
.Buffer
[DllName
.Length
/sizeof(WCHAR
) - 1] == L
' ')
330 DllName
.Length
-= sizeof(WCHAR
);
332 DllName
.Buffer
[DllName
.Length
/sizeof(WCHAR
)] = UNICODE_NULL
;
336 /* Compute the load path */
337 SearchPath
= BaseComputeProcessDllPath((dwFlags
& LOAD_WITH_ALTERED_SEARCH_PATH
) ?
338 DllName
.Buffer
: NULL
,
342 /* Getting DLL path failed, so set last error, free mem and return */
343 BaseSetLastNTError(STATUS_NO_MEMORY
);
344 if (FreeString
) RtlFreeUnicodeString(&DllName
);
350 if (dwFlags
& LOAD_LIBRARY_AS_DATAFILE
)
352 /* If the image is loaded as a datafile, try to get its handle */
353 Status
= LdrGetDllHandleEx(0, SearchPath
, NULL
, &DllName
, (PVOID
*)&hInst
);
354 if (!NT_SUCCESS(Status
))
356 /* It's not loaded yet - so load it up */
357 Status
= BasepLoadLibraryAsDatafile(SearchPath
, DllName
.Buffer
, &hInst
);
359 _SEH2_YIELD(goto done
;)
362 /* Call the API Properly */
363 Status
= LdrLoadDll(SearchPath
,
368 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
370 Status
= _SEH2_GetExceptionCode();
375 /* Free SearchPath buffer */
376 RtlFreeHeap(RtlGetProcessHeap(), 0, SearchPath
);
378 /* Free DllName string if it was dynamically allocated */
379 if (FreeString
) RtlFreeUnicodeString(&DllName
);
381 /* Set last error in failure case */
382 if (!NT_SUCCESS(Status
))
384 BaseSetLastNTError(Status
);
388 /* Return loaded module handle */
398 GetProcAddress(HMODULE hModule
, LPCSTR lpProcName
)
400 ANSI_STRING ProcedureName
, *ProcNamePtr
= NULL
;
401 FARPROC fnExp
= NULL
;
406 if (HIWORD(lpProcName
) != 0)
408 /* Look up by name */
409 RtlInitAnsiString(&ProcedureName
, (LPSTR
)lpProcName
);
410 ProcNamePtr
= &ProcedureName
;
414 /* Look up by ordinal */
415 Ordinal
= (ULONG
)lpProcName
;
418 /* Map provided handle */
419 hMapped
= BasepMapModuleHandle(hModule
, FALSE
);
421 /* Get the proc address */
422 Status
= LdrGetProcedureAddress(hMapped
,
427 if (!NT_SUCCESS(Status
))
429 BaseSetLastNTError(Status
);
433 /* Check for a special case when returned pointer is
434 the same as iamge's base address */
435 if (fnExp
== hMapped
)
437 /* Set correct error code */
438 if (HIWORD(lpProcName
) != 0)
439 BaseSetLastNTError(STATUS_ENTRYPOINT_NOT_FOUND
);
441 BaseSetLastNTError(STATUS_ORDINAL_NOT_FOUND
);
446 /* All good, return procedure pointer */
457 FreeLibrary(HINSTANCE hLibModule
)
460 PIMAGE_NT_HEADERS NtHeaders
;
462 if (LDR_IS_DATAFILE(hLibModule
))
464 // FIXME: This SEH should go inside RtlImageNtHeader instead
467 /* This is a LOAD_LIBRARY_AS_DATAFILE module, check if it's a valid one */
468 NtHeaders
= RtlImageNtHeader((PVOID
)((ULONG_PTR
)hLibModule
& ~1));
470 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
478 Status
= NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)((ULONG_PTR
)hLibModule
& ~1));
480 /* Unload alternate resource module */
481 LdrUnloadAlternateResourceModule(hLibModule
);
484 Status
= STATUS_INVALID_IMAGE_FORMAT
;
489 Status
= LdrUnloadDll((PVOID
)hLibModule
);
492 /* Check what kind of status we got */
493 if (!NT_SUCCESS(Status
))
496 BaseSetLastNTError(Status
);
512 FreeLibraryAndExitThread(HMODULE hLibModule
,
516 if (LDR_IS_DATAFILE(hLibModule
))
518 /* This is a LOAD_LIBRARY_AS_DATAFILE module */
519 if (RtlImageNtHeader((PVOID
)((ULONG_PTR
)hLibModule
& ~1)))
522 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)((ULONG_PTR
)hLibModule
& ~1));
524 /* Unload alternate resource module */
525 LdrUnloadAlternateResourceModule(hLibModule
);
531 LdrUnloadDll((PVOID
)hLibModule
);
535 ExitThread(dwExitCode
);
544 GetModuleFileNameA(HINSTANCE hModule
,
548 UNICODE_STRING FilenameW
;
549 ANSI_STRING FilenameA
;
551 DWORD Length
= 0, LengthToCopy
;
553 /* Allocate a unicode buffer */
554 FilenameW
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, nSize
* sizeof(WCHAR
));
555 if (!FilenameW
.Buffer
)
557 BaseSetLastNTError(STATUS_NO_MEMORY
);
561 /* Call unicode API */
562 FilenameW
.Length
= (USHORT
)GetModuleFileNameW(hModule
, FilenameW
.Buffer
, nSize
) * sizeof(WCHAR
);
563 FilenameW
.MaximumLength
= FilenameW
.Length
+ sizeof(WCHAR
);
565 if (FilenameW
.Length
)
567 /* Convert to ansi string */
568 Status
= BasepUnicodeStringTo8BitString(&FilenameA
, &FilenameW
, TRUE
);
569 if (!NT_SUCCESS(Status
))
571 /* Set last error, free string and retun failure */
572 BaseSetLastNTError(Status
);
573 RtlFreeUnicodeString(&FilenameW
);
577 /* Calculate size to copy */
578 Length
= min(nSize
, FilenameA
.Length
);
580 /* Include terminating zero */
582 LengthToCopy
= Length
+ 1;
584 LengthToCopy
= nSize
;
586 /* Now copy back to the caller amount he asked */
587 RtlMoveMemory(lpFilename
, FilenameA
.Buffer
, LengthToCopy
);
589 /* Free ansi filename */
590 RtlFreeAnsiString(&FilenameA
);
593 /* Free unicode filename */
594 RtlFreeHeap(RtlGetProcessHeap(), 0, FilenameW
.Buffer
);
596 /* Return length copied */
605 GetModuleFileNameW(HINSTANCE hModule
,
609 PLIST_ENTRY ModuleListHead
, Entry
;
610 PLDR_DATA_TABLE_ENTRY Module
;
615 hModule
= BasepMapModuleHandle(hModule
, FALSE
);
617 /* Upscale nSize from chars to bytes */
618 nSize
*= sizeof(WCHAR
);
622 /* We don't use per-thread cur dir now */
623 //PRTL_PERTHREAD_CURDIR PerThreadCurdir = (PRTL_PERTHREAD_CURDIR)teb->NtTib.SubSystemTib;
625 Peb
= NtCurrentPeb ();
627 /* Acquire a loader lock */
628 LdrLockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS
, NULL
, &Cookie
);
630 /* Traverse the module list */
631 ModuleListHead
= &Peb
->Ldr
->InLoadOrderModuleList
;
632 Entry
= ModuleListHead
->Flink
;
633 while (Entry
!= ModuleListHead
)
635 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
637 /* Check if this is the requested module */
638 if (Module
->DllBase
== (PVOID
)hModule
)
640 /* Calculate size to copy */
641 Length
= min(nSize
, Module
->FullDllName
.MaximumLength
);
644 RtlMoveMemory(lpFilename
, Module
->FullDllName
.Buffer
, Length
);
646 /* Subtract a terminating zero */
647 if (Length
== Module
->FullDllName
.MaximumLength
)
648 Length
-= sizeof(WCHAR
);
650 /* Break out of the loop */
654 /* Advance to the next entry */
655 Entry
= Entry
->Flink
;
658 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
660 BaseSetLastNTError(_SEH2_GetExceptionCode());
664 /* Release the loader lock */
665 LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS
, Cookie
);
667 return Length
/ sizeof(WCHAR
);
672 GetModuleHandleForUnicodeString(PUNICODE_STRING ModuleName
)
678 /* Try to get a handle with a magic value of 1 for DllPath */
679 Status
= LdrGetDllHandle((LPWSTR
)1, NULL
, ModuleName
, &Module
);
681 /* If that succeeded - we're done */
682 if (NT_SUCCESS(Status
)) return Module
;
684 /* If not, then the path should be computed */
685 DllPath
= BaseComputeProcessDllPath(NULL
, 0);
688 Status
= STATUS_NO_MEMORY
;
694 Status
= LdrGetDllHandle(DllPath
, NULL
, ModuleName
, &Module
);
696 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
698 /* Fail with the SEH error */
699 Status
= _SEH2_GetExceptionCode();
704 /* Free the DllPath */
705 RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath
);
707 /* In case of error set last win32 error and return NULL */
708 if (!NT_SUCCESS(Status
))
710 DPRINT("Failure acquiring DLL module '%wZ' handle, Status 0x%08X\n", ModuleName
, Status
);
711 BaseSetLastNTError(Status
);
716 return (HMODULE
)Module
;
721 BasepGetModuleHandleExW(BOOLEAN NoLock
, DWORD dwPublicFlags
, LPCWSTR lpwModuleName
, HMODULE
*phModule
)
724 NTSTATUS Status
= STATUS_SUCCESS
, Status2
;
726 UNICODE_STRING ModuleNameU
;
728 BOOLEAN Redirected
= FALSE
; // FIXME
730 /* Validate parameters */
731 dwValid
= BasepGetModuleHandleExParameterValidation(dwPublicFlags
, lpwModuleName
, phModule
);
732 ASSERT(dwValid
== BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE
);
734 /* Acquire lock if necessary */
737 Status
= LdrLockLoaderLock(0, NULL
, &Cookie
);
738 if (!NT_SUCCESS(Status
))
741 BaseSetLastNTError(Status
);
742 if (phModule
) *phModule
= 0;
743 return NT_SUCCESS(Status
);
747 if (!(dwPublicFlags
& GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
))
749 /* Create a unicode string out of module name */
750 RtlInitUnicodeString(&ModuleNameU
, lpwModuleName
);
752 // FIXME: Do some redirected DLL stuff?
760 hModule
= GetModuleHandleForUnicodeString(&ModuleNameU
);
763 /* Last error is already set, so just return failure by setting status */
764 Status
= STATUS_DLL_NOT_FOUND
;
771 /* Perform Pc to file header to get module instance */
772 hModule
= (HMODULE
)RtlPcToFileHeader((PVOID
)lpwModuleName
,
775 /* Check if it succeeded */
778 /* Set "dll not found" status and quit */
779 Status
= STATUS_DLL_NOT_FOUND
;
784 /* Check if changing reference is not forbidden */
785 if (!(dwPublicFlags
& GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
))
787 /* Add reference to this DLL */
788 Status
= LdrAddRefDll((dwPublicFlags
& GET_MODULE_HANDLE_EX_FLAG_PIN
) ? LDR_ADDREF_DLL_PIN
: 0,
792 /* Set last error in case of failure */
793 if (!NT_SUCCESS(Status
))
794 BaseSetLastNTError(Status
);
797 /* Unlock loader lock if it was acquired */
800 Status2
= LdrUnlockLoaderLock(0, Cookie
);
801 ASSERT(NT_SUCCESS(Status2
));
804 /* Set the module handle to the caller */
805 if (phModule
) *phModule
= hModule
;
807 /* Return TRUE on success and FALSE otherwise */
808 return NT_SUCCESS(Status
);
817 GetModuleHandleA(LPCSTR lpModuleName
)
819 PUNICODE_STRING ModuleNameW
;
820 PTEB pTeb
= NtCurrentTeb();
822 /* Check if we have no name to convert */
824 return ((HMODULE
)pTeb
->ProcessEnvironmentBlock
->ImageBaseAddress
);
826 /* Convert module name to unicode */
827 ModuleNameW
= Basep8BitStringToStaticUnicodeString(lpModuleName
);
829 /* Call W version if conversion was successful */
831 return GetModuleHandleW(ModuleNameW
->Buffer
);
843 GetModuleHandleW(LPCWSTR lpModuleName
)
848 /* If current module is requested - return it right away */
850 return ((HMODULE
)NtCurrentPeb()->ImageBaseAddress
);
852 /* Use common helper routine */
853 Status
= BasepGetModuleHandleExW(TRUE
,
854 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
,
858 /* If it wasn't successful - return 0 */
859 if (!NT_SUCCESS(Status
)) hModule
= 0;
861 /* Return the handle */
871 GetModuleHandleExW(IN DWORD dwFlags
,
872 IN LPCWSTR lpwModuleName OPTIONAL
,
873 OUT HMODULE
* phModule
)
879 /* Validate parameters */
880 dwValid
= BasepGetModuleHandleExParameterValidation(dwFlags
, lpwModuleName
, phModule
);
882 /* If result is invalid parameter - return failure */
883 if (dwValid
== BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR
) return FALSE
;
885 /* If result is 2, there is no need to do anything - return success. */
886 if (dwValid
== BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS
) return TRUE
;
888 /* Use common helper routine */
889 Status
= BasepGetModuleHandleExW(FALSE
,
894 /* Return TRUE in case of success */
895 if (NT_SUCCESS(Status
)) Ret
= TRUE
;
905 GetModuleHandleExA(IN DWORD dwFlags
,
906 IN LPCSTR lpModuleName OPTIONAL
,
907 OUT HMODULE
* phModule
)
909 PUNICODE_STRING lpModuleNameW
;
914 /* Validate parameters */
915 dwValid
= BasepGetModuleHandleExParameterValidation(dwFlags
, (LPCWSTR
)lpModuleName
, phModule
);
917 /* If result is invalid parameter - return failure */
918 if (dwValid
== BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR
) return FALSE
;
920 /* If result is 2, there is no need to do anything - return success. */
921 if (dwValid
== BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS
) return TRUE
;
923 /* Check if we don't need to convert the name */
924 if (dwFlags
& GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
)
926 /* Call the extended version of the API without conversion */
927 Status
= BasepGetModuleHandleExW(FALSE
,
929 (LPCWSTR
)lpModuleName
,
934 /* Convert module name to unicode */
935 lpModuleNameW
= Basep8BitStringToStaticUnicodeString(lpModuleName
);
937 /* Return FALSE if conversion failed */
938 if (!lpModuleNameW
) return FALSE
;
940 /* Call the extended version of the API */
941 Status
= BasepGetModuleHandleExW(FALSE
,
943 lpModuleNameW
->Buffer
,
947 /* If result was successful - return true */
948 if (NT_SUCCESS(Status
))
961 LoadModule(LPCSTR lpModuleName
,
962 LPVOID lpParameterBlock
)
964 STARTUPINFOA StartupInfo
;
965 PROCESS_INFORMATION ProcessInformation
;
966 LOADPARMS32
*LoadParams
;
967 char FileName
[MAX_PATH
];
972 UNICODE_STRING UnicStr
;
973 RTL_PATH_TYPE PathType
;
976 LoadParams
= (LOADPARMS32
*)lpParameterBlock
;
978 /* Check load parameters */
979 if (LoadParams
->dwReserved
|| LoadParams
->wMagicValue
!= 2)
981 /* Fail with invalid param error */
982 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
987 Length
= SearchPathA(NULL
, lpModuleName
, ".exe", MAX_PATH
, FileName
, NULL
);
989 /* Check if path was found */
990 if (Length
&& Length
< MAX_PATH
)
992 /* Build StartupInfo */
993 RtlZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
995 StartupInfo
.cb
= sizeof(STARTUPINFOA
);
996 StartupInfo
.dwFlags
= STARTF_USESHOWWINDOW
;
997 StartupInfo
.wShowWindow
= LoadParams
->wCmdShow
;
999 /* Allocate command line buffer */
1000 CommandLine
= RtlAllocateHeap(RtlGetProcessHeap(),
1002 (ULONG
)LoadParams
->lpCmdLine
[0] + Length
+ 2);
1004 /* Put module name there, then a space, and then copy provided command line,
1005 and null-terminate it */
1006 RtlCopyMemory(CommandLine
, FileName
, Length
);
1007 CommandLine
[Length
] = ' ';
1008 RtlCopyMemory(&CommandLine
[Length
+ 1], &LoadParams
->lpCmdLine
[1], (ULONG
)LoadParams
->lpCmdLine
[0]);
1009 CommandLine
[Length
+ 1 + (ULONG
)LoadParams
->lpCmdLine
[0]] = 0;
1011 /* Create the process */
1012 ProcessStatus
= CreateProcessA(FileName
,
1018 LoadParams
->lpEnvAddress
,
1021 &ProcessInformation
);
1023 /* Free the command line buffer */
1024 RtlFreeHeap(RtlGetProcessHeap(), 0, CommandLine
);
1028 /* Creating process failed, return right error code */
1029 Error
= GetLastError();
1032 case ERROR_BAD_EXE_FORMAT
:
1033 return ERROR_BAD_FORMAT
;
1035 case ERROR_FILE_NOT_FOUND
:
1036 case ERROR_PATH_NOT_FOUND
:
1040 /* Return 0 otherwise */
1044 /* Wait up to 30 seconds for the process to become idle */
1045 if (UserWaitForInputIdleRoutine
)
1047 UserWaitForInputIdleRoutine(ProcessInformation
.hProcess
, 30000);
1051 NtClose(ProcessInformation
.hThread
);
1052 NtClose(ProcessInformation
.hProcess
);
1054 /* Return magic success value (33) */
1058 /* The path was not found, create an ansi string from
1059 the module name and convert it to unicode */
1060 RtlInitAnsiString(&AnsiStr
, lpModuleName
);
1061 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicStr
,&AnsiStr
,TRUE
)))
1062 return ERROR_FILE_NOT_FOUND
;
1064 /* Determine path type */
1065 PathType
= RtlDetermineDosPathNameType_U(UnicStr
.Buffer
);
1067 /* Free the unicode module name */
1068 RtlFreeUnicodeString(&UnicStr
);
1070 /* If it's a relative path, return file not found */
1071 if (PathType
== RtlPathTypeRelative
)
1072 return ERROR_FILE_NOT_FOUND
;
1074 /* If not, try to open it */
1075 Handle
= CreateFile(lpModuleName
,
1077 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1080 FILE_ATTRIBUTE_NORMAL
,
1083 if (Handle
!= INVALID_HANDLE_VALUE
)
1085 /* Opening file succeeded for some reason, close the handle and return file not found anyway */
1086 CloseHandle(Handle
);
1087 return ERROR_FILE_NOT_FOUND
;
1090 /* Return last error which CreateFile set during an attempt to open it */
1091 return GetLastError();
1097 FARPROC WINAPI
DelayLoadFailureHook(LPCSTR pszDllName
, LPCSTR pszProcName
)
1106 BOOL WINAPI
UTRegister( HMODULE hModule
, LPSTR lpsz16BITDLL
,
1107 LPSTR lpszInitName
, LPSTR lpszProcName
,
1108 FARPROC
*ppfn32Thunk
, FARPROC pfnUT32CallBack
,
1118 VOID WINAPI
UTUnRegister( HMODULE hModule
)
1128 BaseQueryModuleData(IN LPSTR ModuleName
,
1134 DPRINT1("BaseQueryModuleData called: %s %s %p %p %p\n",
1148 BaseProcessInitPostImport(VOID
)
1150 /* Check if this is a terminal server */
1151 DPRINT1("Post-init called\n");
1152 if (SharedUserData
->SuiteMask
& VER_SUITE_TERMINAL
)
1154 /* Initialize TS pointers */
1155 return BasepInitializeTermsrvFpns();
1158 /* FIXME: Initialize TS pointers */
1159 return STATUS_SUCCESS
;