以下是windows API GetModuleFileName的实现:
/*
*@implemented
*/
DWORD WINAPI GetModuleFileNameA(HINSTANCEhModule,
LPSTR lpFilename,
DWORD nSize)
{
UNICODE_STRING FilenameW;
ANSI_STRING FilenameA;
NTSTATUS Status;
DWORD Length = 0, LengthToCopy;
/* Allocate a unicode buffer */
FilenameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nSize *sizeof(WCHAR));
if (!FilenameW.Buffer)
{
BaseSetLastNTError(STATUS_NO_MEMORY);
return 0;
}
/* Call unicode API */
FilenameW.Length = GetModuleFileNameW(hModule, FilenameW.Buffer, nSize)* sizeof(WCHAR);
FilenameW.MaximumLength = FilenameW.Length + sizeof(WCHAR);
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;
}
/* Calculate size to copy */
Length = min(nSize, FilenameA.Length);
/* Include terminating zero */
if (nSize > Length)
LengthToCopy = Length + 1;
else
LengthToCopy = nSize;
/* Now copy back to the caller amount he asked */
RtlMoveMemory(lpFilename, FilenameA.Buffer, LengthToCopy);
/* Free ansi filename */
RtlFreeAnsiString(&FilenameA);
}
/* Free unicode filename */
RtlFreeHeap(RtlGetProcessHeap(), 0, FilenameW.Buffer);
/* Return length copied */
return Length;
}
/*
*@implemented
*/
DWORD WINAPI GetModuleFileNameW(HINSTANCEhModule,
LPWSTR lpFilename,
DWORD nSize)
{
PLIST_ENTRY ModuleListHead, Entry; //链表
PLDR_DATA_TABLE_ENTRY Module; //记录module的数据结构
ULONG Length = 0;
ULONG Cookie;
PPEB Peb;
hModule = BasepMapModuleHandle(hModule, FALSE);
/* Upscale nSize from chars to bytes */
nSize *= sizeof(WCHAR);
_SEH2_TRY
{
/* We don't use per-thread cur dir now */
//PRTL_PERTHREAD_CURDIR PerThreadCurdir =(PRTL_PERTHREAD_CURDIR)teb->NtTib.SubSystemTib;
Peb = NtCurrentPeb ();
/* 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);
/* Copy contents */
RtlMoveMemory(lpFilename,Module->FullDllName.Buffer, Length);
/* 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);
}
从上可以看出Windows Module的数据都记录在PLDR_DATA_TABLE_ENTRY数据结构中,当要获取具体module名称的时候,会根据它的句柄,遍历整个链表,来获取相应的信息。