Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)
How to tell if the current user is in administrators group programmatically
; https://learn.microsoft.com/en-us/archive/blogs/junfeng/how-to-tell-if-the-current-user-is-in-administrators-group-programmatically

기존에는 CheckTokenMembership API를 이용해서 현재 로그인한 계정이 관리자 그룹에 속해 있는지 알아내기 위해서 다음과 같은 예제 코드를 제시하고 있습니다.

BOOL IsUserAdmin(VOID)
{
BOOL b;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID AdministratorsGroup; 
b = AllocateAndInitializeSid(
    &NtAuthority,
    2,
    SECURITY_BUILTIN_DOMAIN_RID,
    DOMAIN_ALIAS_RID_ADMINS,
    0, 0, 0, 0, 0, 0,
    &AdministratorsGroup); 
if(b) 
{
    if (!CheckTokenMembership( NULL, AdministratorsGroup, &b)) 
    {
         b = FALSE;
    } 
    FreeSid(AdministratorsGroup); 
}

return(b);
}

그런데, Vista에서는 "filtered user token"의 값으로 CheckTokenMembership에 의해 체크되기 때문에 정상적으로 검사가 안 될 테니, 대신에 다음과 같은 코드를 이용해서 확인을 하라고 합니다. (Windows SDK가 설치되어져 있어야 빌드가 됩니다.)

HRESULT IsUserAdmin(BOOL *pIsAdmin)
{
    int b;
    HANDLE hProcess = NULL;
    HANDLE hProcessToken = NULL;
    HANDLE hLinkedToken = NULL;
    BOOL fIsAdmin = FALSE;
    DWORD dwLength = 0;
    OSVERSIONINFO osver = {sizeof(OSVERSIONINFO)};
    HRESULT hr = S_OK;

    *pIsAdmin = FALSE;

    hProcess = GetCurrentProcess();
    if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken))
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }

    char AdminSID[SECURITY_MAX_SID_SIZE];
    dwLength = sizeof(AdminSID);
    if(!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &AdminSID, &dwLength)) 
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    } 

    if (!CheckTokenMembership( NULL, &AdminSID, &fIsAdmin)) 
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }

    if (fIsAdmin) 
    {
        *pIsAdmin = TRUE;
        goto Exit;
    }

    if (!GetVersionEx(&osver))
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }

    if (osver.dwMajorVersion < 6) 
    {
        goto Exit;        
    }

    if (!GetTokenInformation(   hProcessToken,
                                TokenLinkedToken,
                                (VOID*) &hLinkedToken,
                                sizeof(HANDLE),
                                &dwLength) )
    {
        b = GetLastError();
        if  (   b == ERROR_NO_SUCH_LOGON_SESSION
            ||  b == ERROR_PRIVILEGE_NOT_HELD)
        {
            goto Exit;
        }

        hr = HRESULT_FROM_WIN32(b); // a real error
        goto Exit;
    } 

    if (!CheckTokenMembership(   hLinkedToken, &AdminSID, &fIsAdmin))
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }

    if (fIsAdmin)
    {
        *pIsAdmin = TRUE;
    }
    else 
    {
    }

Exit:
    if (hProcess) 
    {
        CloseHandle(hProcess);
    }

    if (hProcessToken)
    {
        CloseHandle(hProcessToken);
    }

    if (hLinkedToken)
    {
        CloseHandle(hLinkedToken);
    }

    return hr;
}



[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 12/22/2022]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.

비밀번호

댓글 작성자
 



2025-01-22 12시54분
본문의 CheckTokenMembership의 래퍼로 제공하는 IsUserAnAdmin API를 이용해 1줄 코드로 작성할 수 있습니다.

IsUserAnAdmin function
; https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-isuseranadmin

또한, (관리자 권한이 아닌) 단순히 권한 상승된 여부를 알고자 한다면 다음의 코드를 사용할 수 있습니다.

BOOL ret = FALSE;
HANDLE hToken = nullptr;

if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) == TRUE) {
    TOKEN_ELEVATION elevation;
    DWORD cbSize = sizeof(TOKEN_INFORMATION);
    if (GetTokenInformation(hToken, TokenElevation, &elevation, sizeof(elevation), &cbSize) == TRUE) {
        ret = elevation.TokenIsElevated;
    }
}

if (hToken) {
    CloseHandle(hToken);
}

// if elevated: ret == TRUE, or FALSE
정성태

[1]  2  3  4  5  6  7  8 
NoWriterDateCnt.TitleFile(s)
197정성태7/30/20215793.NET : 63. Spectre.Console
196정성태10/28/20197657장치 관리자처럼 각 장치들에 할당된 리소스(예: Memory Range) 상태를 코드로 알아내는 방법
195정성태4/25/20197851Extracting Text from an Image Using Tesseract in C#
194정성태4/25/20197462Parse the Command Line with System.CommandLine
193정성태8/2/201710176.NET : 62. github - C# to JavaScript, WPF to JavaScript and Samples
192정성태6/29/20169808.NET : 61. TreeLib: Balanced Binary Trees ? Rank Augmented, for .NET
191정성태10/13/201510963.NET : 60. MICROSOFT TRANSLATOR HUB
190정성태6/20/201511590Win32 : 6. UMDH Visualizer - Memory profile viewer
189정성태1/19/201413445.NET : 59. QR 코드를 ASP.NET과 WPF에서 사용하는 방법
188정성태1/15/201413597.NET : 58. 윈도우폰 7 - 안면인식, Cartooning...
187정성태1/14/201413295.NET : 57. BCL에서 제공되는 컬렉션에 만족하지 못한다면? [1]
186정성태6/26/201313553.NET : 56. The managed way to retrieve text under the cursor (mouse pointer)
185정성태9/27/201214814.NET : 55. Face Detection with Emgu CV in C# and WPF
184정성태9/23/201212911.NET : 54. What was that sound Visual Studio? Audio Editor Beta For VS 2012 (plus free sounds library too!)
183정성태4/19/201214970.NET : 53. Virtual Router 소스 코드 및 실행 파일 (C#)
182정성태4/16/201215653.NET : 52. SharpDX [1]
181정성태3/3/201219089.NET : 51. .NET에서 DirectX를 이용하여 스크린 캡쳐를 빠르게 하는 방법 [3]
180정성태3/3/201214072.NET : 50. Restart Manager 를 이용하여 .NET 에서 잠긴 파일을 소유하고 있는 프로세스 찾는 방법
179정성태1/14/201213338.NET : 49. WebAPI Developer Preview 6: Self Hosted Mode Example
178정성태10/31/201115267.NET : 48. app.config의 supportedRuntime 예시
177정성태10/15/201114495.NET : 47. Irony - Language Implementation Kit
176정성태7/22/201114439.NET : 46. Manual Validation with Data Annotations
175정성태5/18/201116042Win32 : 5. UuidCreateSequential
174정성태5/4/201114653.NET : 45. NTrace v2 now available (think Managed VS2010/.Net 4 Event Tracing for Windows)
173정성태4/12/201116780레지스트리 : 11. BHO를 IE와 탐색기에서 선택적으로 로드하고 싶다면?
[1]  2  3  4  5  6  7  8