윈7 32비트 응용프로그램에서 64비트 DLL 호출 및 등록은 죽었다 깨어나도 안된다.
그리고 윈도우 95부터 등장한 32비트에서 16비트 하위 호환실행을 지원하기 위한 WOW(Windows-On-Windows) 시스템에 의해 이제는 64비트 os하의 32bit 어플들이 지원되긴 하는데 이 32비트 응용프로그램들은 (윈도우즈 파일들)모두 SysWOW64 폴더로 리다이렉션 되기 때문에 System32 하의 64비트 프로그램들은 호출이 기본적으로 안되게 되어 있다. 아래 소스를 참조 바란다.
따라서, 직접 DLL을 로드하여 DllRegisterServer 를 호출하려면 호출자 EXE도 같은 64비트여야 한다.
여기서는 간략하게 32비트 EXE에서 64비트 DLL을 등록하는 방법을 설명한다.
탐색기 팝업메뉴를 제어하기 위한 Shell Extension DLL 은 64비트 OS에선 반드시 64비트로 또한 작성되어야 함.
BOOL DEApp::RegisterShellCommand(BOOL bRegist)
{
TCHAR szOS[256];
int whatbit;
OSVERSIONINFOEX osvi;
TCHAR szDLL[MAX_PATH];
GetOSString(szOS,&osvi,&whatbit);
GetHomeDirectory(szDLL);
if(whatbit == 64)
lstrcat(szDLL,"DEShl64.dll");
else
lstrcat(szDLL,"DEShl.DLL");
int whatsize = sizeof(int);
typedef BOOL (WINAPI *LPFN_Wow64Disable)(PVOID* OldValue);
typedef BOOL (WINAPI *LPFN_Wow64Revert)(PVOID OldValue);
PVOID OldValue;
LPFN_Wow64Disable pWowDis = NULL;
LPFN_Wow64Revert pWowRev = NULL;
BOOL bRet = 0;
BOOL fc=1;
//i am 32bit app and os is 64bit,register 64bit dll and
//redirect folder.krkim
if(whatsize == 4 && whatbit == 64){
pWowDis = (LPFN_Wow64Disable) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
"Wow64DisableWow64FsRedirection");
pWowRev = (LPFN_Wow64Revert) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
"Wow64RevertWow64FsRedirection");
if(pWowDis)
bRet = pWowDis(&OldValue);
TCHAR szEXE[MAX_PATH*2];
if(bRegist){
wsprintf(szEXE,"/s \"%s\"",szDLL);
ShellExecute(NULL,_T("open"),"regsvr32",szEXE,NULL,SW_SHOWDEFAULT);
}
else{
wsprintf(szEXE,"/u /s \"%s\"",szDLL);
ShellExecute(NULL,_T("open"),"regsvr32",szEXE,NULL,SW_SHOWDEFAULT);
}
if(bRet && pWowRev)
bRet = pWowRev(OldValue);
}
else if((whatbit / whatsize) == 8){ //same bit
//don't call different bit between app and dll, 32<->64bit direct
fc = RegisterDll(szDLL,bRegist);
}
return fc;
}
*추가:
if(whatsize == 4 && whatbit == 64) 로 WOW64에서 실행중인 32비트 어플인지를 체크하는 부분을
다음 함수로 대체해도 된다.
#define WOW64API __fastcall
#define GetProc(m, n) ((PVOID)GetProcAddress(GetModuleHandleA(m), n))
BOOL WOW64API Wow64CheckProcess( )
{
typedef BOOL (WINAPI *PFNISWOW64PROCESS)( HANDLE hProcess, PBOOL Wow64Process );
PFNISWOW64PROCESS pfnIsWow64Process =(PFNISWOW64PROCESS)
GetProc("KERNEL32.dll", "IsWow64Process");
//fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(
// GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
BOOL bIsWow64;
if (pfnIsWow64Process && pfnIsWow64Process(GetCurrentProcess(), &bIsWow64))
return(bIsWow64);
return(FALSE);
}
아니면 위 로직을 아예 DLL 자체의 DllRegisterServer( ) 와 DllUnregisterServer( )에 심어서
WOW64를 구분하여,리다이렉션을 해제하고 원복하도록 레지스트리에 등록하는
실제 코드의 앞뒤로 Wrapping 하여 호출하게 해놓고,외부에서는 그냥 이 함수들을 원래대로 호출하게 해도 되겠다.
*RegisterDll는 단순히 해당경로의 dll을 LoadLibrary하여 DllRegisterServer 와 DllUnregisterServer를 호출하는 함수임.귀찮아서 나머지는 생략하고 올립니다.
출처: 나(http://krkim.net)
'OS > Windows' 카테고리의 다른 글
UAC 비스타 권한상승 예제 (0) | 2012.03.24 |
---|---|
ActiveX 권한 상승에 대한 일반적인 이야기와 솔루션들 (0) | 2012.03.20 |