2017-12-28 61 views
1

Windows APIでWindows API、つまりRegCreateKeyEx関数を使用して新しいレジストリキーを作成し、GetSecurityInfoを使用してそのDACLを取得しようとしています。無効なハンドル値エラー(エラー6)を返すGetSecurityInfo関数呼び出しになるまで、すべてのアサートは円滑に進みます。私は間違って何をしていますか?C++ windows API GetSecurityInfo無効なハンドルが指定されました

これは、私が唯一与えるより精巧なプロジェクトの一部である(または私はそれが何を考えて、私はあまりにも休息を追加することができます)ここに関連部分:出力を作るためにRegCreateKeyExにラッパー

協力し、発生したエラーを設定する方が簡単:

inline extern auto RegCreateKeyEx_safe(
    _In_  const HKEY     hKey, 
    _In_  const LPCTSTR    lpSubKey, 
    _Reserved_ const DWORD     Reserved, 
    _In_opt_ const LPTSTR    lpClass, 
    _In_  const DWORD     dwOptions, 
    _In_  const REGSAM    samDesired, 
    _In_opt_ const LPSECURITY_ATTRIBUTES lpSecurityAttributes, 
    _Out_  const PHKEY     phkResult, 
    _Out_opt_ const LPDWORD    lpdwDisposition) 
{ 
    const auto result = 
     RegCreateKeyEx(
      hKey, 
      lpSubKey, 
      Reserved, 
      lpClass, 
      dwOptions, 
      samDesired, 
      lpSecurityAttributes, 
      phkResult, 
      lpdwDisposition); 
    if (result != ERROR_SUCCESS) 
     SetLastError(result); 
    return result == ERROR_SUCCESS; 
} 

ラッパー、それが有効であるかどうかをチェックした後、作成したキーのハンドルを返す必要があります上記の機能に:

inline extern auto CreateNewRegKey(
    HKEY     hKey, 
    LPCTSTR    lpSubKey, 
    DWORD     Reserved, 
    LPTSTR    lpClass, 
    DWORD     dwOptions, 
    REGSAM    samDesired, 
    LPSECURITY_ATTRIBUTES lpSecurityAttributes, 
    LPDWORD    lpdwDisposition) 
{ 
    auto createdKey = static_cast<PHKEY>(malloc(sizeof HKEY)); 

    assert(
     RegCreateKeyEx_safe(
      hKey, 
      lpSubKey, 
      Reserved, 
      lpClass, 
      dwOptions, 
      samDesired, 
      lpSecurityAttributes, 
      createdKey, 
      lpdwDisposition)); 

    assert(createdKey != INVALID_HANDLE_VALUE); 

    return createdKey; 
} 

そしてRegCreateKeyバージョンとしてGetSecurityInfoのラッパー、同じ理由と機能:

inline extern auto GetSecurityInfo_safe(
    _In_  const HANDLE    handle, 
    _In_  const SE_OBJECT_TYPE  ObjectType, 
    _In_  const SECURITY_INFORMATION SecurityInfo, 
    _Out_opt_  PSID*     ppsidOwner, 
    _Out_opt_  PSID*     ppsidGroup, 
    _Out_opt_  PACL*     ppDacl, 
    _Out_opt_  PACL*     ppSacl, 
    _Out_opt_  PSECURITY_DESCRIPTOR* ppSecurityDescriptor) 
{ 
    const auto result = 
     GetSecurityInfo(
      handle, 
      ObjectType, 
      SecurityInfo, 
      ppsidOwner, 
      ppsidGroup, 
      ppDacl, 
      ppSacl, 
      ppSecurityDescriptor); 
    if (result != ERROR_SUCCESS) 
     SetLastError(result); 
    return result == EXIT_SUCCESS; 
} 

次のように今、これらの関数を呼び出すコードは次のとおりです。

const auto newRegKey = 
     CreateNewRegKey(
      HKEY_CURRENT_USER, 
      SUBKEY_PATH, 
      NULL, 
      nullptr, 
      REG_OPTION_NON_VOLATILE, 
      KEY_ALL_ACCESS, 
      NULL, //securityAttributes, 
      nullptr); 

    assert(
     GetSecurityInfo_safe(
      newRegKey, 
      SE_REGISTRY_KEY, 
      DACL_SECURITY_INFORMATION, 
      NULL, 
      NULL, 
      oldDacl, 
      NULL, 
      NULL)); 

出力が問題である場合にはかなり明確です(条件を確認した後、条件が満たされなかった場合のエラーテキストと共に、条件をチェックした後にそれを表示するというやや詳細なアサーションを実装しました):

SUCCESS:  RegCreateKeyEx_safe(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, createdKey, lpdwDisposition) 
SUCCESS:  createdKey != INVALID_HANDLE_VALUE 
FAILURE:  GetSecurityInfo_safe(newRegKey, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, oldDacl, NULL, NULL) 

ERROR-6:  The handle is invalid. 

アサート:

#define _VERBOSE   (1) 
#define assert(cond)  if((cond) == TRUE) \ 
           { if (_VERBOSE) cout << "SUCCESS:\t" << #cond << endl; } \ 
          else \ 
           {cout << "FAILURE:\t" << #cond << "\n\nERROR-" << GetLastError() << ":\t" << GetLastErrorAsString() << "\n\n"; exit(EXIT_FAILURE); } 

は、事前にありがとうございます!

+0

このラッパーでは、作業をより難しくする意味はなんですか? 'SetLastError'はここでは必要ありません - Reg APIはtrue/falseの代わりにエラーコードを返します。本当にはるかに優れたデザインで使いやすいです。 – RbMm

+0

@RbMmこれらのコードは、コードがより精巧なプロジェクトの一部であり、より大きなコードベースで作業するほうが簡単です:) –

+0

エラーコードを返す関数での作業 - 真/偽を返し、最後のエラーを返す関数よりはるかに簡単です – RbMm

答えて

3

機能CreateNewRegKeyは、値によってHKEYを返すべきHKEYポインタを返しています。代わりにHANDLEが必要なGetSecurityInfo()にこのポインタを渡します。 HANDLEtypedef void *HANDLE;と宣言されているため、コンパイラは通知しません。

HKEY createdKey = NULL; 

auto createdKey = static_cast<PHKEY>(malloc(sizeof HKEY)); 

をしてHKEYのアドレスを渡すために&createdKeyRegCreateKeyEx_safe()を呼び出す:交換するエラーを修正するには

+0

ありがとう!私は自分自身をポインタや自動変数などでしか働かせないようにしていますので、実際には 'GetSecurityInfo'関数呼び出しでnewRegKeyを参照解除することで修正しました。 ' GetSecurityInfo_safe( * newRegKey 、 SE_REGISTRY_KEY、 ... ' しかし、私はあなたの助けなしに、再び感謝しなかったでしょう! –

関連する問題