📄 ldr.c
字号:
/* $Id: ldr.c 25633 2007-01-26 07:22:19Z ion $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT : ReactOS user mode libraries
* MODULE : kernel32.dll
* FILE : reactos/lib/kernel32/misc/ldr.c
* AUTHOR : Ariadne
*/
#include <k32.h>
#define NDEBUG
#include "../include/debug.h"
typedef struct tagLOADPARMS32 {
LPSTR lpEnvAddress;
LPSTR lpCmdLine;
LPSTR lpCmdShow;
DWORD dwReserved;
} LOADPARMS32;
extern BOOLEAN InWindows;
/* FUNCTIONS ****************************************************************/
/**
* @name GetDllLoadPath
*
* Internal function to compute the load path to use for a given dll.
*
* @remarks Returned pointer must be freed by caller.
*/
LPWSTR STDCALL
GetDllLoadPath(LPCWSTR lpModule)
{
ULONG Pos = 0, Length = 0;
PWCHAR EnvironmentBufferW = NULL;
LPCWSTR lpModuleEnd = NULL;
UNICODE_STRING ModuleName;
if (lpModule != NULL)
{
lpModuleEnd = lpModule + wcslen(lpModule);
}
else
{
ModuleName = NtCurrentTeb()->ProcessEnvironmentBlock->ProcessParameters->ImagePathName;
lpModule = ModuleName.Buffer;
lpModuleEnd = lpModule + (ModuleName.Length / sizeof(WCHAR));
}
if (lpModule != NULL)
{
while (lpModuleEnd > lpModule && *lpModuleEnd != L'/' &&
*lpModuleEnd != L'\\' && *lpModuleEnd != L':')
--lpModuleEnd;
Length = (lpModuleEnd - lpModule) + 1;
}
Length += GetCurrentDirectoryW(0, NULL);
Length += GetSystemDirectoryW(NULL, 0);
Length += GetWindowsDirectoryW(NULL, 0);
Length += GetEnvironmentVariableW(L"PATH", NULL, 0);
EnvironmentBufferW = RtlAllocateHeap(RtlGetProcessHeap(), 0,
Length * sizeof(WCHAR));
if (EnvironmentBufferW == NULL)
return NULL;
if (lpModule)
{
RtlCopyMemory(EnvironmentBufferW, lpModule,
(lpModuleEnd - lpModule) * sizeof(WCHAR));
Pos += lpModuleEnd - lpModule;
EnvironmentBufferW[Pos++] = L';';
}
Pos += GetCurrentDirectoryW(Length, EnvironmentBufferW + Pos);
EnvironmentBufferW[Pos++] = L';';
Pos += GetSystemDirectoryW(EnvironmentBufferW + Pos, Length - Pos);
EnvironmentBufferW[Pos++] = L';';
Pos += GetWindowsDirectoryW(EnvironmentBufferW + Pos, Length - Pos);
EnvironmentBufferW[Pos++] = L';';
Pos += GetEnvironmentVariableW(L"PATH", EnvironmentBufferW + Pos, Length - Pos);
EnvironmentBufferW[Pos] = 0;
return EnvironmentBufferW;
}
/*
* @implemented
*/
BOOL
STDCALL
DisableThreadLibraryCalls (
HMODULE hLibModule
)
{
NTSTATUS Status;
Status = LdrDisableThreadCalloutsForDll ((PVOID)hLibModule);
if (!NT_SUCCESS (Status))
{
SetLastErrorByStatus (Status);
return FALSE;
}
return TRUE;
}
/*
* @implemented
*/
HINSTANCE
STDCALL
LoadLibraryA (
LPCSTR lpLibFileName
)
{
return LoadLibraryExA (lpLibFileName, 0, 0);
}
/*
* @implemented
*/
HINSTANCE
STDCALL
LoadLibraryExA (
LPCSTR lpLibFileName,
HANDLE hFile,
DWORD dwFlags
)
{
PWCHAR FileNameW;
if (!(FileNameW = FilenameA2W(lpLibFileName, FALSE)))
return FALSE;
return LoadLibraryExW(FileNameW, hFile, dwFlags);
}
/*
* @implemented
*/
HINSTANCE
STDCALL
LoadLibraryW (
LPCWSTR lpLibFileName
)
{
return LoadLibraryExW (lpLibFileName, 0, 0);
}
/*
* @implemented
*/
HINSTANCE
STDCALL
LoadLibraryExW (
LPCWSTR lpLibFileName,
HANDLE hFile,
DWORD dwFlags
)
{
UNICODE_STRING DllName;
HINSTANCE hInst;
NTSTATUS Status;
PWSTR SearchPath;
ULONG DllCharacteristics;
(void)hFile;
if ( lpLibFileName == NULL )
return NULL;
/* Check for any flags LdrLoadDll might be interested in */
if (dwFlags & DONT_RESOLVE_DLL_REFERENCES)
{
/* Tell LDR to treat it as an EXE */
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);
RtlInitUnicodeString(&DllName, (LPWSTR)lpLibFileName);
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);
}
RtlFreeHeap(RtlGetProcessHeap(), 0, SearchPath);
if ( !NT_SUCCESS(Status))
{
SetLastErrorByStatus (Status);
return NULL;
}
return hInst;
}
/*
* @implemented
*/
FARPROC
STDCALL
GetProcAddress( HMODULE hModule, LPCSTR lpProcName )
{
ANSI_STRING ProcedureName;
FARPROC fnExp = NULL;
if (HIWORD(lpProcName) != 0)
{
RtlInitAnsiString (&ProcedureName,
(LPSTR)lpProcName);
LdrGetProcedureAddress ((PVOID)hModule,
&ProcedureName,
0,
(PVOID*)&fnExp);
}
else
{
LdrGetProcedureAddress ((PVOID)hModule,
NULL,
(ULONG)lpProcName,
(PVOID*)&fnExp);
}
return fnExp;
}
/*
* @implemented
*/
BOOL
STDCALL
FreeLibrary( HMODULE hLibModule )
{
LdrUnloadDll(hLibModule);
return TRUE;
}
/*
* @implemented
*/
VOID
STDCALL
FreeLibraryAndExitThread (
HMODULE hLibModule,
DWORD dwExitCode
)
{
if ( FreeLibrary(hLibModule) )
ExitThread(dwExitCode);
for (;;)
;
}
/*
* @implemented
*/
DWORD
STDCALL
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;
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);
if (Module->DllBase == (PVOID)hModule)
{
if (nSize * sizeof(WCHAR) < Module->FullDllName.Length)
{
SetLastErrorByStatus (STATUS_BUFFER_TOO_SMALL);
}
else
{
FileName.Length = 0;
FileName.MaximumLength = (USHORT)nSize * 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);
Length = Module->FullDllName.Length / sizeof(WCHAR);
}
RtlLeaveCriticalSection (Peb->LoaderLock);
return Length;
}
Entry = Entry->Flink;
}
SetLastErrorByStatus (STATUS_DLL_NOT_FOUND);
RtlLeaveCriticalSection (Peb->LoaderLock);
return 0;
}
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -