Rundll32について

Rundll32.exeについてのメモ。
おそるべきことにRundll32.exeは、渡されたDLLがx86かx64か判断している。
このため、以下のような関係になる。

Rundll32のType 渡すDLLのType 起動プロセス
x86 x86 x86
x86 x64 x86,x64
x64 x86 x86,x64
x64 x64 x64


すなわち、%windir%\system32\Rundll32.exeに渡しても、%windir%\sysWOW64\Rundll32.exeに渡しても、DLLを読み込んでくれるのです。
ううむ、さすが。



Rundll32で呼び出せる関数について


にありますが、

void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);

と、WinMainと同じ形の模様。
ただ、Unicode対応しているOSでは、先にWを探すそうなので、9x系を捨てるなら

void CALLBACK EntryPointW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow);

のみ定義すれば良いらしい。
どちらも、マルチバイト文字も問題なくいけました。


サンプルソース
Rundll.h

// Rundll.h
#pragma once
#ifndef RUNDLL_H
#define RUNDLL_H

#ifdef		RUNDLL_EXPORT
#define		RUNDLL_EXPORT_ATTR		__declspec(dllexport)
#else
#define		RUNDLL_EXPORT_ATTR		__declspec(dllimport)
#endif


#ifdef  __cplusplus
extern "C" {
#endif


RUNDLL_EXPORT_ATTR int EntryPointW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow);
RUNDLL_EXPORT_ATTR int EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);


#ifdef  __cplusplus
}
#endif

#endif	// #ifndef RUNDLL_H

Rundll.cpp

// Rundll.cpp
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define RUNDLL_EXPORT
#include "Rundll.h"



RUNDLL_EXPORT_ATTR int EntryPointW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow)
{
	WCHAR buf[1024];
	wsprintfW(buf, TEXT("HWND:%016x HINST:%016x CmdLine:%s Show:%d W"), hwnd, hinst, lpszCmdLine, nCmdShow);
	return MessageBoxW(hwnd, buf, TEXT("Rundll Sample"), MB_OK);
}

RUNDLL_EXPORT_ATTR int EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
{
	char buf[1024];
	wsprintfA(buf, "HWND:%016x HINST:%016x CmdLine:%s Show:%d A", hwnd, hinst, lpszCmdLine, nCmdShow);
	return MessageBoxA(hwnd, buf, "Rundll Sample", MB_OK);
}


// メイン関数
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
	switch(dwReason)
	{
		case DLL_PROCESS_ATTACH:
			break;
		case DLL_PROCESS_DETACH:
			break;
		case DLL_THREAD_ATTACH:
			break;
		case DLL_THREAD_DETACH:
			break;
	}

	return TRUE;
}

サンプルソースは、諸事情によりvoidをintにしてたりします。
が、問題ないですし、リターンは無視されるようです。


もちろん、DllMain関数も呼ばれます。
exe更新時に、一時的にRundll32に憑依するのもありですね。