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では、先に
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に憑依するのもありですね。