ほっしーの技術ネタ備忘録

技術ネタの備忘録です。基本的に私が忘れないためのものです。他の人の役にも立つといいなぁ。

スレッド開始アドレス

とある事情で「スレッドの開始アドレス」が必要になったので調べてみると
そのものズバリ!


GetThreadStartInformation API


…はい。対応は Windows Server 2003。しょんぼり。


で、色々調べてみたところ、
ntdll.dll の非公開 API を用いて取得できるようです。

static const int ThreadQuerySetWin32StartAddress = 9;
typedef int (WINAPI *typeNtQueryInformationThread)( HANDLE, int, PVOID, ULONG, PULONG );

PVOID GetThreadBeginAddress( HANDLE hThread )
{
	HMODULE hNtDll = LoadLibrary( "ntdll.dll" );
	if( hNtDll == NULL ) {
		printf("LoadLibrary() failed.\n");
		return NULL;
	}

	typeNtQueryInformationThread NtQueryInformationThread = (typeNtQueryInformationThread) GetProcAddress( hNtDll, "NtQueryInformationThread" );
	if( NtQueryInformationThread == NULL ) {
		printf("LoadLibrary() failed.\n");
		FreeLibrary( hNtDll );
		return NULL;
	}

	ULONG ulLength;
	PVOID pBeginAddress;
	NtQueryInformationThread( GetCurrentThread(), ThreadQuerySetWin32StartAddress, &pBeginAddress, sizeof(pBeginAddress), &ulLength );

	FreeLibrary( hNtDll );

	return pBeginAddress;
}


こんな感じの関数を用意しておいて

DWORD WINAPI ChildThread( void* )
{
	PVOID pBeginAddress = GetThreadBeginAddress( GetCurrentThread() );

	printf("BeginAddress: 0x%08X\n", pBeginAddress );

	printf("ChildThread: %08X\n", ChildThread );

	return 0;
}

int main()
{
	HANDLE hThread = CreateThread( NULL, 0, ChildThread, 0, 0, NULL );

	Sleep( 1000 );

	return 0;
}


これで

BeginAddress: 0x0040100A
ChildThread: 0040100A

うん、おっけー。