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