各ユーザーのHKEY_CURRENT_USER(HKCU)へアクセスするには
現在のWindowsアカウント(ユーザー)で、各ユーザーのHKEY_CURRENT_USERにアクセスするためには、いくつかの手順が必要です。
手順は下記の通りです。
(1) SE_RESTORE_NAME特権を有効化する。
(2) Windowsアカウントの一覧を取得する(Net APIを使用します。netapi32.libへのリンクが必要です)。
(3) 各ユーザーのレジストリファイル(ntuser.dat)へのパスを取得する。
(4) ユーザーごとのレジストリ情報を 特定のレジストリキー以下にマッピングする。
(5) マッピングしたキーを操作する。
(6) マッピングを解除する。
以下、サンプルになります。
※ ConvertSidToStringSidはWindows 2000からのみ使用できるので、NT4のときは独自実装してください。
※ Windows Vistaでは管理者権限への権限上昇が必要です。権限上昇manifestの実装方法は、Vistaの項目を参照してください。
■■■ hkcus プロジェクト
■ main.cpp
//----------------------------------------------------------------------------------------------------
// 各ユーザーのHKEY_CURRENT_USERを操作する
// Windows 2000以降でテスト済み
// Netapi32.lib リンク必須
// 管理者権限で実行してください(Vistaでは権限上昇必須)
//----------------------------------------------------------------------------------------------------
#pragma warning ( disable : 4786 )
#define _WIN32_WINNT 0x0500 // ConvertSidToStringSid用 (Windows2000以降用。独自実装も可)
#include <windows.h>
#include <shlobj.h>
#include <string>
#include <lmaccess.h>
#include <lm.h>
#include <lmapibuf.h>
#include <Sddl.h>
//----------------------------------------------------------------------------------------------------
// レジストリファイルへのパスを取得する (存在するかどうかもチェックする)
//----------------------------------------------------------------------------------------------------
BOOL GetRegistryFilePath ( LPCTSTR pszUserName, std::basic_string < char > &rstrPath )
{
enum
{
MY_MAX_PATH = 4096
};
// パス作成
// 自分のフォルダを取得 ( C:\\Documents and Settings\\<user name> )
char szPath[ MY_MAX_PATH ];
if ( !SHGetSpecialFolderPath ( NULL, szPath, CSIDL_PROFILE, TRUE ) )
{
return FALSE;
}
// ユーザー名を削除し、Documents and Settingsパスを取得する
char *pszPtr = szPath;
char *pKept = pszPtr;
while ( *pszPtr != '\0' )
{
// 2バイト文字の先頭はスキップ
if ( 0 == IsDBCSLeadByte ( *pszPtr ) )
{
//[\],[/],[:]を見つけたら現在地+1のポインタを保存
if( (*pszPtr == '\\') || (*pszPtr == '/'))
{
pKept = pszPtr + 1;
}
}
//次の文字へ
pszPtr = CharNext ( pszPtr );
}
char szRetPath[ MY_MAX_PATH ];
lstrcpyn ( szRetPath, szPath, lstrlen ( szPath ) - lstrlen ( pKept ) );
// ユーザ名を追加
std::basic_string < char > strRetPath ( szRetPath );
strRetPath += "\\";
strRetPath += pszUserName;
strRetPath += "\\";
const char cszNtUserDat[] = "ntuser.dat";
strRetPath += cszNtUserDat;
// ファイルがあるか調査
WIN32_FIND_DATA win32FindData;
HANDLE hFindFile;
hFindFile = FindFirstFile ( strRetPath.c_str (), &win32FindData );
if ( INVALID_HANDLE_VALUE == hFindFile )
{
return FALSE;
}
FindClose ( hFindFile );
// フォルダでないことを確認
if ( 0 != ( FILE_ATTRIBUTE_DIRECTORY & win32FindData.dwFileAttributes ) )
{
return FALSE;
}
// 結果を代入
rstrPath = strRetPath;
return TRUE;
}
//----------------------------------------------------------------------------------------------------
// 指定の特権を有効/無効にする
//----------------------------------------------------------------------------------------------------
BOOL ChangePrivilege ( LPTSTR pszPrivilege, BOOL bEnable )
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
if ( !OpenProcessToken ( GetCurrentProcess (),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken ) )
{
return FALSE;
}
if ( !LookupPrivilegeValue ( NULL,
pszPrivilege,
&tp.Privileges[0].Luid ) )
{
return FALSE;
}
tp.PrivilegeCount = 1;
if ( bEnable )
{
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
}
else
{
tp.Privileges[0].Attributes = 0;
}
if ( !AdjustTokenPrivileges ( hToken,
FALSE,
&tp,
0,
( PTOKEN_PRIVILEGES ) NULL,
0 ) )
{
return FALSE;
}
if ( !CloseHandle ( hToken ) )
{
return FALSE;
}
return TRUE;
}
//----------------------------------------------------------------------------------------------------
// エントリポイント
//----------------------------------------------------------------------------------------------------
int WINAPI WinMain ( HINSTANCE,
HINSTANCE,
char *,
int )
{
// Windows 2000 以降でなければ終了
// そもそもNTでなければ、各ユーザーのデータを各ユーザーのレジストリに持つ必要がないため 9xは実装しない
DWORD dwOSVersionInfoSize;
dwOSVersionInfoSize = sizeof ( OSVERSIONINFO );
OSVERSIONINFO ovi;
memset ( &ovi, 0, dwOSVersionInfoSize );
ovi.dwOSVersionInfoSize = dwOSVersionInfoSize;
GetVersionEx ( &ovi );
if ( ! ( VER_PLATFORM_WIN32_NT == ovi.dwPlatformId
&& 5 <= ovi.dwMajorVersion ) )
{
MessageBox ( NULL,
"Windows 2000以降で実行してください",
"エラー",
MB_OK | MB_ICONSTOP );
return 1;
}
// SE_RESTORE_NAME 特権 有効化
if ( !ChangePrivilege ( SE_RESTORE_NAME, TRUE ) )
{
MessageBox ( NULL,
"SE_RESTORE_NAME 特権を有効化できませんでした",
"エラー",
MB_OK | MB_ICONSTOP );
return 1;
}
// SIDとユーザ名を列挙
LPBYTE pBuffer;
DWORD EntriesRead = 0;
DWORD TotalEntries = 0;
DWORD ResumeHandle = 0;
DWORD i;
PSID pSid;
DWORD cbSid;
PWSTR pReferencedDomainName;
DWORD cbReferencedDomainName;
SID_NAME_USE eUse;
const char cszSettingsSubKey[] = "Software\\WindowsManiacProgramming";
const char cszValueName[] = "Sample";
const char cszValue[] = "data";
HKEY hSubKey;
DWORD dwNotUsed;
NET_API_STATUS netApiStatus;
netApiStatus = NetUserEnum ( NULL,
0,
0,
&pBuffer,
MAX_PREFERRED_LENGTH,
&EntriesRead,
&TotalEntries,
&ResumeHandle );
if ( ERROR_ACCESS_DENIED == netApiStatus || NERR_InvalidComputer == netApiStatus )
{
return 1;
}
if ( ERROR_MORE_DATA == netApiStatus )
{
NetApiBufferFree ( pBuffer );
return 1;
}
USER_INFO_0 *pUser = ( USER_INFO_0 * ) pBuffer;
for ( i = 0; i < EntriesRead; i++ )
{
enum
{
MY_MAX_BUFFER = 1024
};
pSid = ( PSID ) malloc ( MY_MAX_BUFFER );
cbSid = MY_MAX_BUFFER;
pReferencedDomainName = ( PWSTR ) malloc ( MY_MAX_BUFFER * sizeof ( WCHAR ) );
cbReferencedDomainName = MY_MAX_BUFFER;
// アカウントを取得
if ( LookupAccountNameW ( NULL,
pUser[i].usri0_name,
pSid,
&cbSid,
pReferencedDomainName,
&cbReferencedDomainName,
&eUse ) )
{
char *pszSid = NULL;
if ( ConvertSidToStringSid ( pSid,&pszSid ) )
{
//char sz[ MY_MAX_BUFFER * 2 ];
//wsprintf( sz, "%ls\t%s\n",pUser[i].usri0_name, pszSid );
// パス取得
char szUser[ MY_MAX_BUFFER ];
wsprintf ( szUser, "%ls", pUser[i].usri0_name );
// 自分自身ではないとき
char szUserBuf[ UNLEN + 1 ];
DWORD dwUnLen = UNLEN + 1;
GetUserName ( szUserBuf, &dwUnLen );
if ( 0 != lstrcmpi ( szUser, szUserBuf ) )
{
std::basic_string < char > strPath;
if ( GetRegistryFilePath ( szUser, strPath ) )
{
// ユーザーのレジストリをマッピング
if ( ERROR_SUCCESS == RegLoadKey ( HKEY_LOCAL_MACHINE, pszSid, strPath.c_str () ) )
{
// ここで自分以外の HKEY_CURRENT_USER レジストリ操作処理を行う!!!!!!
std::basic_string < char > strSubKey ( pszSid );
strSubKey += "\\";
strSubKey += cszSettingsSubKey;
if ( ERROR_SUCCESS == RegCreateKeyEx ( HKEY_LOCAL_MACHINE,
strSubKey.c_str (),
0,
NULL,
REG_OPTION_NON_VOLATILE /* 保存 */,
KEY_ALL_ACCESS,
NULL,
&hSubKey,
&dwNotUsed ) )
{
// テスト書き込み
const char cszValueName[] = "Sample";
const char cszValue[] = "data";
if ( ERROR_SUCCESS == RegSetValueEx ( hSubKey,
cszValueName,
0,
REG_SZ,
reinterpret_cast < const BYTE * > ( cszValue ),
lstrlenA ( cszValue ) + 1 ) )
{
MessageBox ( NULL,
szUser,
"Written",
MB_OK );
}
RegCloseKey ( hSubKey );
}
// マッピング解除 (念のためループ処理)
UINT nCount = 0;
while ( ERROR_SUCCESS != RegUnLoadKey ( HKEY_LOCAL_MACHINE, pszSid ) && nCount <= 5 )
{
Sleep ( 100 );
nCount++;
}
}
}
}
LocalFree ( pszSid );
}
}
free ( pSid );
free ( pReferencedDomainName );
}
NetApiBufferFree ( pBuffer );
// 自分自身の HKEY_CURRENT_USER を操作
if ( ERROR_SUCCESS == RegCreateKeyEx ( HKEY_LOCAL_MACHINE,
cszSettingsSubKey,
0,
NULL,
REG_OPTION_NON_VOLATILE /* 保存 */,
KEY_ALL_ACCESS,
NULL,
&hSubKey,
&dwNotUsed ) )
{
// テスト書き込み
if ( ERROR_SUCCESS == RegSetValueEx ( hSubKey,
cszValueName,
0,
REG_SZ,
reinterpret_cast < const BYTE * > ( cszValue ),
lstrlenA ( cszValue ) + 1 ) )
{
MessageBox ( NULL,
"自分自身",
"Written",
MB_OK );
}
RegCloseKey ( hSubKey );
}
return 0;
} |
■resrc.rc
1 24 "hkcus.exe.manifest" |
■mnfst.exe.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0"
processorArchitecture="X86"
name="hkcus.exe"
type="win32"/>
<description>Privilege's elevation for hkcus</description>
<!-- Identify the application security requirements. -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="requireAdministrator"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
|
|