3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT : ReactOS user mode libraries
5 * MODULE : kernel32.dll
6 * FILE : reactos/lib/kernel32/misc/ldr.c
7 * AUTHOR : Boudewijn Dekker
13 #include "../include/debug.h"
15 typedef struct tagLOADPARMS32
{
22 /* FUNCTIONS ****************************************************************/
25 * @name GetDllLoadPath
27 * Internal function to compute the load path to use for a given dll.
29 * @remarks Returned pointer must be freed by caller.
33 GetDllLoadPath(LPCWSTR lpModule
)
35 ULONG Pos
= 0, Length
= 0;
36 PWCHAR EnvironmentBufferW
= NULL
;
37 LPCWSTR lpModuleEnd
= NULL
;
38 UNICODE_STRING ModuleName
;
42 lpModuleEnd
= lpModule
+ wcslen(lpModule
);
46 ModuleName
= NtCurrentTeb()->Peb
->ProcessParameters
->ImagePathName
;
47 lpModule
= ModuleName
.Buffer
;
48 lpModuleEnd
= lpModule
+ (ModuleName
.Length
/ sizeof(WCHAR
));
53 while (lpModuleEnd
> lpModule
&& *lpModuleEnd
!= L
'/' &&
54 *lpModuleEnd
!= L
'\\' && *lpModuleEnd
!= L
':')
56 Length
= (lpModuleEnd
- lpModule
) + 1;
59 Length
+= GetCurrentDirectoryW(0, NULL
);
60 Length
+= GetSystemDirectoryW(NULL
, 0);
61 Length
+= GetWindowsDirectoryW(NULL
, 0);
62 Length
+= GetEnvironmentVariableW(L
"PATH", NULL
, 0);
64 EnvironmentBufferW
= RtlAllocateHeap(RtlGetProcessHeap(), 0,
65 Length
* sizeof(WCHAR
));
66 if (EnvironmentBufferW
== NULL
)
71 RtlCopyMemory(EnvironmentBufferW
, lpModule
,
72 (lpModuleEnd
- lpModule
) * sizeof(WCHAR
));
73 Pos
+= lpModuleEnd
- lpModule
;
74 EnvironmentBufferW
[Pos
++] = L
';';
76 Pos
+= GetCurrentDirectoryW(Length
, EnvironmentBufferW
+ Pos
);
77 EnvironmentBufferW
[Pos
++] = L
';';
78 Pos
+= GetSystemDirectoryW(EnvironmentBufferW
+ Pos
, Length
- Pos
);
79 EnvironmentBufferW
[Pos
++] = L
';';
80 Pos
+= GetWindowsDirectoryW(EnvironmentBufferW
+ Pos
, Length
- Pos
);
81 EnvironmentBufferW
[Pos
++] = L
';';
82 Pos
+= GetEnvironmentVariableW(L
"PATH", EnvironmentBufferW
+ Pos
, Length
- Pos
);
83 EnvironmentBufferW
[Pos
] = 0;
85 return EnvironmentBufferW
;
93 DisableThreadLibraryCalls (
99 Status
= LdrDisableThreadCalloutsForDll ((PVOID
)hLibModule
);
100 if (!NT_SUCCESS (Status
))
102 SetLastErrorByStatus (Status
);
118 return LoadLibraryExA (lpLibFileName
, 0, 0);
128 LPCSTR lpLibFileName
,
135 if (!(FileNameW
= FilenameA2W(lpLibFileName
, FALSE
)))
138 return LoadLibraryExW(FileNameW
, hFile
, dwFlags
);
148 LPCWSTR lpLibFileName
151 return LoadLibraryExW (lpLibFileName
, 0, 0);
161 LPCWSTR lpLibFileName
,
166 UNICODE_STRING DllName
;
173 if ( lpLibFileName
== NULL
)
177 DONT_RESOLVE_DLL_REFERENCES
|
178 LOAD_LIBRARY_AS_DATAFILE
|
179 LOAD_WITH_ALTERED_SEARCH_PATH
;
181 SearchPath
= GetDllLoadPath(
182 dwFlags
& LOAD_WITH_ALTERED_SEARCH_PATH
? lpLibFileName
: NULL
);
184 RtlInitUnicodeString(&DllName
, (LPWSTR
)lpLibFileName
);
185 Status
= LdrLoadDll(SearchPath
, dwFlags
, &DllName
, (PVOID
*)&hInst
);
186 RtlFreeHeap(RtlGetProcessHeap(), 0, SearchPath
);
187 if ( !NT_SUCCESS(Status
))
189 SetLastErrorByStatus (Status
);
202 GetProcAddress( HMODULE hModule
, LPCSTR lpProcName
)
204 ANSI_STRING ProcedureName
;
205 FARPROC fnExp
= NULL
;
207 if (HIWORD(lpProcName
) != 0)
209 RtlInitAnsiString (&ProcedureName
,
211 LdrGetProcedureAddress ((PVOID
)hModule
,
218 LdrGetProcedureAddress ((PVOID
)hModule
,
233 FreeLibrary( HMODULE hLibModule
)
235 LdrUnloadDll(hLibModule
);
245 FreeLibraryAndExitThread (
250 if ( FreeLibrary(hLibModule
) )
251 ExitThread(dwExitCode
);
268 ANSI_STRING FileName
;
269 PLIST_ENTRY ModuleListHead
;
271 PLDR_DATA_TABLE_ENTRY Module
;
275 Peb
= NtCurrentPeb ();
276 RtlEnterCriticalSection (Peb
->LoaderLock
);
279 hModule
= Peb
->ImageBaseAddress
;
281 ModuleListHead
= &Peb
->Ldr
->InLoadOrderModuleList
;
282 Entry
= ModuleListHead
->Flink
;
284 while (Entry
!= ModuleListHead
)
286 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderModuleList
);
287 if (Module
->DllBase
== (PVOID
)hModule
)
289 if (nSize
* sizeof(WCHAR
) < Module
->FullDllName
.Length
)
291 SetLastErrorByStatus (STATUS_BUFFER_TOO_SMALL
);
296 FileName
.MaximumLength
= nSize
* sizeof(WCHAR
);
297 FileName
.Buffer
= lpFilename
;
299 /* convert unicode string to ansi (or oem) */
301 RtlUnicodeStringToAnsiString (&FileName
,
302 &Module
->FullDllName
,
305 RtlUnicodeStringToOemString (&FileName
,
306 &Module
->FullDllName
,
308 Length
= Module
->FullDllName
.Length
/ sizeof(WCHAR
);
311 RtlLeaveCriticalSection (Peb
->LoaderLock
);
315 Entry
= Entry
->Flink
;
318 SetLastErrorByStatus (STATUS_DLL_NOT_FOUND
);
319 RtlLeaveCriticalSection (Peb
->LoaderLock
);
336 UNICODE_STRING FileName
;
337 PLIST_ENTRY ModuleListHead
;
339 PLDR_DATA_TABLE_ENTRY Module
;
343 Peb
= NtCurrentPeb ();
344 RtlEnterCriticalSection (Peb
->LoaderLock
);
347 hModule
= Peb
->ImageBaseAddress
;
349 ModuleListHead
= &Peb
->Ldr
->InLoadOrderModuleList
;
350 Entry
= ModuleListHead
->Flink
;
351 while (Entry
!= ModuleListHead
)
353 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderModuleList
);
355 if (Module
->DllBase
== (PVOID
)hModule
)
357 if (nSize
* sizeof(WCHAR
) < Module
->FullDllName
.Length
)
359 SetLastErrorByStatus (STATUS_BUFFER_TOO_SMALL
);
364 FileName
.MaximumLength
= nSize
* sizeof(WCHAR
);
365 FileName
.Buffer
= lpFilename
;
367 RtlCopyUnicodeString (&FileName
,
368 &Module
->FullDllName
);
369 Length
= Module
->FullDllName
.Length
/ sizeof(WCHAR
);
372 RtlLeaveCriticalSection (Peb
->LoaderLock
);
376 Entry
= Entry
->Flink
;
379 SetLastErrorByStatus (STATUS_DLL_NOT_FOUND
);
380 RtlLeaveCriticalSection (Peb
->LoaderLock
);
391 GetModuleHandleA ( LPCSTR lpModuleName
)
393 UNICODE_STRING UnicodeName
;
394 ANSI_STRING ModuleName
;
398 if (lpModuleName
== NULL
)
399 return ((HMODULE
)NtCurrentPeb()->ImageBaseAddress
);
400 RtlInitAnsiString (&ModuleName
,
401 (LPSTR
)lpModuleName
);
403 /* convert ansi (or oem) string to unicode */
405 RtlAnsiStringToUnicodeString (&UnicodeName
,
409 RtlOemStringToUnicodeString (&UnicodeName
,
413 Status
= LdrGetDllHandle (0,
418 RtlFreeUnicodeString (&UnicodeName
);
420 if (!NT_SUCCESS(Status
))
422 SetLastErrorByStatus (Status
);
426 return ((HMODULE
)BaseAddress
);
435 GetModuleHandleW (LPCWSTR lpModuleName
)
437 UNICODE_STRING ModuleName
;
441 if (lpModuleName
== NULL
)
442 return ((HMODULE
)NtCurrentPeb()->ImageBaseAddress
);
444 RtlInitUnicodeString (&ModuleName
,
445 (LPWSTR
)lpModuleName
);
447 Status
= LdrGetDllHandle (0,
451 if (!NT_SUCCESS(Status
))
453 SetLastErrorByStatus (Status
);
457 return ((HMODULE
)BaseAddress
);
468 LPVOID lpParameterBlock
471 STARTUPINFOA StartupInfo
;
472 PROCESS_INFORMATION ProcessInformation
;
473 LOADPARMS32
*LoadParams
;
474 char FileName
[MAX_PATH
];
475 char *CommandLine
, *t
;
478 LoadParams
= (LOADPARMS32
*)lpParameterBlock
;
479 if(!lpModuleName
|| !LoadParams
|| (((WORD
*)LoadParams
->lpCmdShow
)[0] != 2))
481 /* windows doesn't check parameters, we do */
482 SetLastError(ERROR_INVALID_PARAMETER
);
486 if(!SearchPathA(NULL
, lpModuleName
, ".exe", MAX_PATH
, FileName
, NULL
) &&
487 !SearchPathA(NULL
, lpModuleName
, NULL
, MAX_PATH
, FileName
, NULL
))
489 return ERROR_FILE_NOT_FOUND
;
492 Length
= (BYTE
)LoadParams
->lpCmdLine
[0];
493 if(!(CommandLine
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
494 strlen(lpModuleName
) + Length
+ 2)))
496 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
500 /* Create command line string */
501 strcpy(CommandLine
, lpModuleName
);
502 t
= CommandLine
+ strlen(CommandLine
);
504 memcpy(t
, LoadParams
->lpCmdLine
+ 1, Length
);
506 /* Build StartupInfo */
507 RtlZeroMemory(&StartupInfo
, sizeof(STARTUPINFOA
));
508 StartupInfo
.cb
= sizeof(STARTUPINFOA
);
509 StartupInfo
.dwFlags
= STARTF_USESHOWWINDOW
;
510 StartupInfo
.wShowWindow
= ((WORD
*)LoadParams
->lpCmdShow
)[1];
512 if(!CreateProcessA(FileName
, CommandLine
, NULL
, NULL
, FALSE
, 0, LoadParams
->lpEnvAddress
,
513 NULL
, &StartupInfo
, &ProcessInformation
))
517 HeapFree(GetProcessHeap(), 0, CommandLine
);
518 /* return the right value */
519 Error
= GetLastError();
522 case ERROR_BAD_EXE_FORMAT
:
524 return ERROR_BAD_FORMAT
;
526 case ERROR_FILE_NOT_FOUND
:
527 case ERROR_PATH_NOT_FOUND
:
535 HeapFree(GetProcessHeap(), 0, CommandLine
);
537 /* Wait up to 15 seconds for the process to become idle */
538 WaitForInputIdle(ProcessInformation
.hProcess
, 15000);
540 CloseHandle(ProcessInformation
.hThread
);
541 CloseHandle(ProcessInformation
.hProcess
);