Programming Windows Maniacs - プログラミング ウィンドウズ マニアックス ■ ご利用に際して ■ 更新履歴 ■ お問い合わせ ■ このホームページについて  
ホーム >> システム >> 各ユーザーのHKEY_CURRENT_USER(HKCU)へアクセスするには

各ユーザーの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>
  ■ ご利用に際して ■ 更新履歴 ■ お問い合わせ ■ このホームページについて Copyright © 2014 A.Morita