Programming Windows Maniacs - プログラミング ウィンドウズ マニアックス ■ ご利用に際して ■ 更新履歴 ■ お問い合わせ ■ このホームページについて  
ホーム >> システム >> Windows アカウント名、SIDを列挙するためには

Windows アカウント名、SIDを列挙するためには

  Windows アカウント名、SIDを取得するには、まず SE_RESTORE_NAME 特権を有効化する必要があります。
  その後、NetAPI を使用して、取得することができます。

  NetAPI を使用するには、netapi32.libをリンクする必要があります。

  サンプルは下記になります。

   ConvertSidToStringSid () API は独自実装すれば、下記はNT4でも動作します。NT4には関数が存在しないので、下記を実行すると関数が見つからず、すぐにエラーになります。

   #pragma warning ( disable : 4786 ) は、std::basic_string < char > を使用したときに、255文字切り捨てのwarningをdisableするためです。

■■■ enumusers プロジェクト
■ main.cpp

#pragma warning ( disable : 4786 )

#define _WIN32_WINNT 0x0500 // ConvertSidToStringSid用 (Windows2000以降用。独自実装も可)

#include <windows.h>

#include <lmaccess.h>
#include <lm.h>
#include <lmapibuf.h>
#include <Sddl.h>

//----------------------------------------------------------------------------------------------------
// 指定の特権を有効/無効にする
//----------------------------------------------------------------------------------------------------
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 0;
    }

// 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;

    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 );

                MessageBox ( NULL,
                    sz,
                    "ユーザー名    SID",
                    MB_OK );
                LocalFree ( pszSid );
            }
        }

        free ( pSid );
        free ( pReferencedDomainName );

    }

    NetApiBufferFree ( pBuffer );

    return 0;
}
  ■ ご利用に際して ■ 更新履歴 ■ お問い合わせ ■ このホームページについて Copyright © 2014 A.Morita