2017-02-20 6 views
1

をWindowsでラージ・ページを有効にする:管理者権限が上昇した一方で、私はインストール時に現在のユーザーのためのラージ・ページを有効にする予定私はこのように私のアプリでラージ・ページを使用するプログラムで

VirtualAlloc(NULL, n_bytes, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE, PAGE_READWRITE); 

。大規模なページをプログラムで有効にするコードは誰にもありますか?

+0

あなたは 'MEM_COMMIT'フラグを忘れています。 'VirtualAlloc(NULL、n_bytes、MEM_COMMIT | MEM_LARGE_PAGES、PAGE_READWRITE);'をどのような問題で呼びますか? – RbMm

+0

@RbMmが修正されました。とにかく、私はそれを呼び出す前に、ユーザーアカウントの 'SeLockMemoryPrivilege'特典を取得する必要がありますhttps://msdn.microsoft.com/en-us/library/windows/desktop/aa366720(v=vs.85).aspx –

+0

はい、必要。 'SeLockMemoryPrivilege'が問題になっていますか? – RbMm

答えて

1

私が集めたものを投稿しています。

一般的な考え方:

  1. 現在のユーザーアカウントのラージ・ページを有効にします。 (管理者権限が必要です)。
  2. 現在のプロセストークンに大きなページを有効にします。 (管理者権限が必要です)。
  3. メモリを割り当てます(実際は2Mbの大きなページサイズに細分化されています)。

あなたはUAC properly disabledお持ちの場合は、管理者権限で一度だけステップ1を実行する必要があります。 UACを有効にしている場合、管理者権限ですべてを実行する必要があります。

#define UNICODE 
#define _UNICODE 

#include <windows.h> 
#include <ntsecapi.h> 
#include <ntstatus.h> 
#include <Sddl.h> 

void InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String) 
{ 
    DWORD StringLength; 

    if (String == NULL) { 
     LsaString->Buffer = NULL; 
     LsaString->Length = 0; 
     LsaString->MaximumLength = 0; 
     return; 
    } 

    StringLength = wcslen(String); 
    LsaString->Buffer = String; 
    LsaString->Length = (USHORT)StringLength * sizeof(WCHAR); 
    LsaString->MaximumLength = (USHORT)(StringLength + 1) * sizeof(WCHAR); 
} 

NTSTATUS OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle) 
{ 
    LSA_OBJECT_ATTRIBUTES ObjectAttributes; 
    LSA_UNICODE_STRING ServerString; 
    PLSA_UNICODE_STRING Server = NULL; 

    // 
    // Always initialize the object attributes to all zeroes. 
    // 
    ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); 

    if (ServerName != NULL) { 
     // 
     // Make a LSA_UNICODE_STRING out of the LPWSTR passed in 
     // 
     InitLsaString(&ServerString, ServerName); 
     Server = &ServerString; 
    } 

    // 
    // Attempt to open the policy. 
    // 
    return LsaOpenPolicy(
     Server, 
     &ObjectAttributes, 
     DesiredAccess, 
     PolicyHandle 
    ); 
} 

NTSTATUS SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid, LPWSTR PrivilegeName, BOOL bEnable) 
{ 
    LSA_UNICODE_STRING PrivilegeString; 

    // 
    // Create a LSA_UNICODE_STRING for the privilege name. 
    // 
    InitLsaString(&PrivilegeString, PrivilegeName); 

    // 
    // grant or revoke the privilege, accordingly 
    // 
    if (bEnable) { 
     return LsaAddAccountRights(
      PolicyHandle,  // open policy handle 
      AccountSid,   // target SID 
      &PrivilegeString, // privileges 
      1     // privilege count 
     ); 
    } 
    else { 
     return LsaRemoveAccountRights(
      PolicyHandle,  // open policy handle 
      AccountSid,   // target SID 
      FALSE,    // do not disable all rights 
      &PrivilegeString, // privileges 
      1     // privilege count 
     ); 
    } 
} 

void main() 
{ 
    HANDLE hToken = NULL; 

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) 
    { 
     applog(LOG_INFO, "OpenProcessToken failed. GetLastError returned: %d\n", GetLastError()); 
     return -1; 
    } 

    DWORD dwBufferSize = 0; 

    // Probe the buffer size reqired for PTOKEN_USER structure 
    if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwBufferSize) && 
     (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) 
    { 
     applog(LOG_INFO, "GetTokenInformation failed. GetLastError returned: %d\n", GetLastError()); 

     // Cleanup 
     CloseHandle(hToken); 
     hToken = NULL; 

     return -1; 
    } 

    PTOKEN_USER pTokenUser = (PTOKEN_USER) malloc(dwBufferSize); 

    // Retrieve the token information in a TOKEN_USER structure 
    if (!GetTokenInformation(
     hToken, 
     TokenUser, 
     pTokenUser, 
     dwBufferSize, 
     &dwBufferSize)) 
    { 
     applog(LOG_INFO, "GetTokenInformation failed. GetLastError returned: %d\n", GetLastError()); 

     // Cleanup 
     CloseHandle(hToken); 
     hToken = NULL; 

     return -1; 
    } 

    // Print SID string 
    LPWSTR strsid; 
    ConvertSidToStringSid(pTokenUser->User.Sid, &strsid); 
    applog(LOG_INFO, "User SID: %S\n", strsid); 

    // Cleanup 
    CloseHandle(hToken); 
    hToken = NULL; 

    NTSTATUS status; 
    LSA_HANDLE policyHandle; 

    if (status = OpenPolicy(NULL, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &policyHandle)) 
    { 
     applog(LOG_INFO, "OpenPolicy %d", status); 
    } 

    // Add new privelege to the account 
    if (status = SetPrivilegeOnAccount(policyHandle, pTokenUser->User.Sid, SE_LOCK_MEMORY_NAME, TRUE)) 
    { 
     applog(LOG_INFO, "OpenPSetPrivilegeOnAccountolicy %d", status); 
    } 

    // Enable this priveledge for the current process 
    hToken = NULL; 
    TOKEN_PRIVILEGES tp; 

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) 
    { 
     applog(LOG_INFO, "OpenProcessToken #2 failed. GetLastError returned: %d\n", GetLastError()); 
     return -1; 
    } 

    tp.PrivilegeCount = 1; 
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 

    if (!LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &tp.Privileges[0].Luid)) 
    { 
     applog(LOG_INFO, "LookupPrivilegeValue failed. GetLastError returned: %d\n", GetLastError()); 
     return -1; 
    } 

    BOOL result = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0); 
    DWORD error = GetLastError(); 

    if (!result || (error != ERROR_SUCCESS)) 
    { 
     applog(LOG_INFO, "AdjustTokenPrivileges failed. GetLastError returned: %d\n", error); 
     return -1; 
    } 

    // Cleanup 
    CloseHandle(hToken); 
    hToken = NULL; 

    SIZE_T pageSize = GetLargePageMinimum(); 

    // Finally allocate the memory 
    char *largeBuffer = VirtualAlloc(NULL, pageSize * N_PAGES_TO_ALLOC, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); 
    if (largeBuffer) 
    { 
     applog(LOG_INFO, "VirtualAlloc failed, error 0x%x", GetLastError()); 
    } 
} 
関連する問題