ユーザーアカウントコントロールによる弊害
ユーザーアカウントコントロールはXP/2003までに作成したアプリケーションに大きな影響を及ぼします。
例えば、フックを利用する際は、注意が必要です。
スタンダード権限で動作しているアプリケーションが、管理者権限で動作しているアプリケーションをフックしようとしても失敗します。
以下は、Internet Explorerの「インターネット オプション」の「詳細設定」タブを隠すフックの例です。
■■■ inetcpl_hook DLLプロジェクト
■ main.cpp
//----------------------------------------------------------------------------------------------------
// inetcpl_hook サンプル
//----------------------------------------------------------------------------------------------------
#pragma warning ( disable : 4786 )
#include <windows.h>
#include <tchar.h>
#include <shlobj.h>
#include <vector>
#include <string>
HHOOK g_hHook = NULL;
BOOL g_fEnabled = TRUE;
std::vector < std::basic_string < _TCHAR > > g_vstrName;
BOOL AttachHook ( HHOOK hHook )
{
g_hHook = hHook;
return TRUE;
}
BOOL SetHook ( BOOL fEnable )
{
g_fEnabled = fEnable;
return TRUE;
}
BOOL HideTab ( HWND hWnd )
{
enum
{
MY_MAX_PATH = MAX_PATH + 1
};
_TCHAR szBuf[ MY_MAX_PATH ] = _TEXT ( "" );
BOOL bResult = FALSE;
HWND hTabWnd;
hTabWnd = FindWindowEx ( hWnd, NULL, _TEXT ( "SysTabControl32" ), _TEXT ( "" ) );
if ( NULL != hTabWnd )
{
int nCount = TabCtrl_GetItemCount ( hTabWnd );
int i;
for ( i = 0; i < nCount; i++)
{
PropSheet_SetCurSel ( hWnd, NULL, i );
HWND hDlgWnd;
hDlgWnd = PropSheet_GetCurrentPageHwnd ( hWnd );
GetWindowText ( hDlgWnd, szBuf, MAX_PATH );
std::vector < std::basic_string < _TCHAR > >::iterator it;
it = g_vstrName.begin ();
while ( it != g_vstrName.end () )
{
const _TCHAR *pcszTabText;
pcszTabText = ( *it ).c_str ();
if ( 0 == lstrcmp ( szBuf, pcszTabText ) )
{
HWND hFoundWnd;
hFoundWnd = FindWindowEx ( hDlgWnd,
NULL,
_TEXT ( "SysTreeView32" ),
NULL );
if ( NULL != hFoundWnd )
{
PropSheet_RemovePage ( hWnd, i, NULL );
bResult = TRUE;
break;
}
}
it++;
}
}
PropSheet_SetCurSel ( hWnd, NULL, 0 );
}
return bResult;
}
LRESULT CALLBACK CallWndRetProc ( int nCode, WPARAM wParam, LPARAM lParam )
{
if ( ( nCode >= 0 )
&& ( nCode == HC_ACTION )
&& g_fEnabled )
{
CWPRETSTRUCT *lpcrs = reinterpret_cast < CWPRETSTRUCT * > ( lParam );
if ( lpcrs != NULL
&& lpcrs->message == WM_INITDIALOG )
{
HMODULE hModule;
hModule = GetModuleHandle ( _TEXT ( "inetcpl.cpl" ) );
if ( NULL != hModule )
{
HideTab ( lpcrs->hwnd );
}
}
}
return CallNextHookEx ( g_hHook,
nCode,
wParam,
lParam );
}
BOOL WINAPI DllMain ( HINSTANCE hThisInstance,
DWORD dwReason,
void * )
{
switch ( dwReason ) {
case DLL_PROCESS_ATTACH:
g_vstrName.push_back ( _TEXT ( "詳細設定" ) );
}
return TRUE;
} |
■ inetcpl_hook.def
LIBRARY inetcpl_hook
EXPORTS
AttachHook @1
SetHook @2
CallWndRetProc @3
|
■resrc.rc
1 24 "write_prgf2.exe.manifest" |
■■ inetcpl_hook_app EXEプロジェクト
■ main.cpp
#include <windows.h>
#include <tchar.h>
#include <string>
const _TCHAR g_cszClassName[] = _TEXT ( "inetcpl_hook" );
const _TCHAR g_cszWndName[] = _TEXT ( "inetcpl_hook" );
HINSTANCE g_hInstance = NULL;
const _TCHAR f_cszDllName[] = _TEXT ( "inetcpl_hook.dll" );
typedef BOOL ( * ATTACHHOOK ) ( HHOOK );
typedef BOOL ( * SETHOOK ) ( BOOL );
static HINSTANCE g_hInstDll = NULL;
static HHOOK g_hHook = NULL;
BOOL CALLBACK ReleaseHookLibrary ( HWND hwnd, LPARAM lParam )
{
PostMessage ( hwnd, WM_NULL, 0, 0 );
EnumChildWindows ( hwnd, ReleaseHookLibrary, lParam );
return TRUE;
}
void UninitializeHook ()
{
if ( NULL != g_hHook )
{
UnhookWindowsHookEx ( g_hHook );
g_hHook = NULL;
}
if ( NULL != g_hInstDll )
{
FreeLibrary ( g_hInstDll );
g_hInstDll = NULL;
}
EnumWindows ( ReleaseHookLibrary, NULL );
}
BOOL InitializeHook ()
{
UninitializeHook ();
g_hInstDll = LoadLibrary ( g_cszDllName );
if ( NULL == g_hInstDll )
return FALSE;
HOOKPROC hkProc = ( HOOKPROC ) GetProcAddress ( g_hInstDll, _TEXT ( "CallWndRetProc" ) );
if ( NULL == hkProc )
{
return FALSE;
}
g_hHook = SetWindowsHookEx ( WH_CALLWNDPROCRET, hkProc, g_hInstDll, 0 );
if ( NULL == g_hHook )
{
return FALSE;
}
ATTACHHOOK AttachHook = ( ATTACHHOOK ) GetProcAddress ( g_hInstDll, _TEXT ( "AttachHook" ) );
AttachHook ( g_hHook );
return TRUE;
}
BOOL SetInetHook ( BOOL bEnable )
{
if ( NULL == g_hInstDll )
{
return FALSE;
}
SETHOOK SetHook = ( SETHOOK ) GetProcAddress ( g_hInstDll, _TEXT ( "SetHook" ) );
if ( NULL == SetHook )
{
return FALSE;
}
SetHook ( bEnable );
return TRUE;
}
long CALLBACK WindowProc ( HWND hWnd,
UINT nMessage,
WPARAM wParam,
LPARAM lParam )
{
switch ( nMessage ) {
case WM_CREATE:
InitializeHook ();
SetInetHook ( TRUE );
return 0;
case WM_DESTROY:
UninitializeHook ();
PostQuitMessage ( 0 );
return 0;
}
return DefWindowProc ( hWnd, nMessage, wParam, lParam );
}
// エントリポイント
int WINAPI _tWinMain ( HINSTANCE hThisInstance,
HINSTANCE,
_TCHAR *,
int )
{
g_hInstance = hThisInstance;
HANDLE hMutex;
hMutex = OpenMutex ( MUTEX_ALL_ACCESS, TRUE, g_cszClassName );
if ( NULL != hMutex )
{
// 2重起動禁止
return 0;
}
hMutex = CreateMutex ( NULL, TRUE, g_cszClassName );
WNDCLASSEX wcex;
wcex.cbSize = sizeof ( WNDCLASSEX );
wcex.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hThisInstance;
wcex.hIcon = LoadIcon ( NULL, IDI_APPLICATION );
wcex.hIconSm = LoadIcon ( NULL, IDI_APPLICATION );
wcex.hCursor = LoadCursor ( NULL, IDC_ARROW );
wcex.hbrBackground = reinterpret_cast < HBRUSH > ( COLOR_WINDOW );
wcex.lpszMenuName = NULL;
wcex.lpszClassName = g_cszClassName;
ATOM atom;
atom = RegisterClassEx ( &wcex );
if ( 0 == atom )
{
return 0;
}
HWND hWnd;
hWnd = CreateWindow ( g_cszClassName,
g_cszWndName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hThisInstance,
NULL );
if ( NULL == hWnd )
{
return 0;
}
ShowWindow ( hWnd, SW_SHOW );
UpdateWindow ( hWnd );
MSG msg;
while ( GetMessage ( &msg, NULL, 0, 0 ) )
{
TranslateMessage ( &msg );
DispatchMessage ( &msg );
}
ReleaseMutex ( hMutex );
CloseHandle ( hMutex );
return 0;
} |
DLLとEXEは同一フォルダに配置して実行してください。
inetcpl_hook_app.exeを権限上昇せずに実行した状態で、Internet Explorerを通常通り実行し、[ツール|インターネット オプション]メニューを開いてください。 「詳細設定」タブが表示されていないことがわかります。
inetcpl_hook_app.exeを権限上昇せずに実行した状態で、Internet Explorerを「管理者として実行」により実行し、[ツール|インターネット オプション]メニューを開いてください。
「詳細設定」タブ隠すことができていません。つまり、より強い権限のユーザーの画面をフックすることができないのです。
他にも、ユーザーアカウントコントロールによる弊害がいくつかあります。
例えば、サービス特権で動作している限り、Vistaではウィンドウをもてないようになりました。俗にセッション0の問題と呼ばれている問題です(ある特定のユーザーとして、サービスからウィンドウを作成することによりこの問題は解決できます)。 |