ディレクトリオブジェクトピッカーの利用方法

ディレクトリ・オブジェクト・ピッカー (Directory Object Picker) を利用すると、ディレクトリ内の ユーザーやコンピュータを簡単に選択することが出来ます。

今回紹介するサンプルコードの実行画面は以下の通りです。

上記のオブジェクト (ユーザー) を選択すると、そのオブジェクトの情報 (名前、クラス、パス、SID) 等が返されます。 ここではコンソールにそれらの情報を表示しています。

> objpick.exe
[0]
  Name  'Guest'
  Class 'User'
  Path  'WinNT://WORKGROUP/KEISUKEO-HP/Guest'
  UPN   ''
  SID   'S-1-5-21-2117744208-4131696419-2932557158-501'
[1]
  Name  'IUSR_KEISUKEO-HP'
  Class 'User'
  Path  'WinNT://WORKGROUP/KEISUKEO-HP/IUSR_KEISUKEO-HP'
  UPN   ''
  SID   'S-1-5-21-2117744208-4131696419-2932557158-1002'

>

コードはほぼ MSDN のサンプルに近いのですが、SID を表示できる形に直して画面に出力しているところが違います。

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

#include <tchar.h>
#include <stdio.h>
#include <assert.h>
#include <objbase.h>
#include <Objsel.h>


HRESULT InitObjectPicker(IDsObjectPicker *pDsObjectPicker);
HRESULT ProcessSelectedObjects(IDataObject *pdo);


///////////////////////////////////////////////////////////////////////////////


void main( int argc, char* argv[] ) {

     HRESULT hr = S_OK;
     IDsObjectPicker *pDsObjectPicker = NULL;
     IDataObject *pdo = NULL;

     hr = CoInitialize(NULL);

     if(FAILED(hr)) {
          return;
     }
  
     // オブジェクトピッカーのインスタンスを作成
     hr = CoCreateInstance(
          CLSID_DsObjectPicker,
          NULL,
          CLSCTX_INPROC_SERVER,
          IID_IDsObjectPicker,
          (void**) &pDsObjectPicker);
     
     if( SUCCEEDED(hr) ) {

          // オブジェクトピッカーインスタンスの初期化
          hr = InitObjectPicker(pDsObjectPicker);

          if( SUCCEEDED(hr) ) {

               HWND hwndParent = GetConsoleWindow();

               // モーダルダイアログボックスの表示
               hr = pDsObjectPicker->InvokeDialog(hwndParent, &pdo);
               if ( SUCCEEDED(hr) ) {

                    ProcessSelectedObjects(pdo);
                    pdo->Release();

               }
               else {

                    printf("User canceled object picker dialog\n");

               }

          }

     }

     pDsObjectPicker->Release();

     CoUninitialize();

}


///////////////////////////////////////////////////////////////////////////////


HRESULT InitObjectPicker(IDsObjectPicker *pDsObjectPicker) {

     if(NULL == pDsObjectPicker){
          return E_INVALIDARG;
     }

     DSOP_SCOPE_INIT_INFO aScopeInit[2];
     DSOP_INIT_INFO  InitInfo;
  
     // DSOP_SCOPE_INIT_INFO 配列の初期化
     ZeroMemory(aScopeInit, sizeof(aScopeInit));
  
     aScopeInit[0].cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
     aScopeInit[0].flType = DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN
                               | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN;
  
     aScopeInit[0].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS; 
     aScopeInit[0].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS; 

     aScopeInit[1].cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
     aScopeInit[1].flType = DSOP_SCOPE_TYPE_TARGET_COMPUTER;
     aScopeInit[1].flScope = DSOP_SCOPE_FLAG_STARTING_SCOPE;
     aScopeInit[1].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS;
     aScopeInit[1].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS;
  
     // DSOP_INIT_INFO 構造体の初期化
     ZeroMemory(&InitInfo, sizeof(InitInfo));
  
     InitInfo.cbSize = sizeof(InitInfo);
     InitInfo.pwzTargetComputer = NULL;  // ターゲットはローカルコンピュータ
     InitInfo.cDsScopeInfos = sizeof(aScopeInit)/sizeof(DSOP_SCOPE_INIT_INFO);
     InitInfo.aDsScopeInfos = aScopeInit;
     InitInfo.flOptions = DSOP_FLAG_MULTISELECT;

     LPCTSTR attrs[] = { TEXT("ObjectSid") };
     InitInfo.cAttributesToFetch = sizeof (attrs) / sizeof (attrs[0]);
     InitInfo.apwzAttributeNames = attrs;

     return pDsObjectPicker->Initialize(&InitInfo);
     
}


///////////////////////////////////////////////////////////////////////////////


HRESULT ProcessSelectedObjects(IDataObject *pdo) {

     if( !pdo ) {
          return E_INVALIDARG;
     }
     
     HRESULT      hr;
     STGMEDIUM   stm;
     FORMATETC   fe;
  
     fe.cfFormat = RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
     fe.ptd = NULL;
     fe.dwAspect = DVASPECT_CONTENT;
     fe.lindex = -1;
     fe.tymed = TYMED_HGLOBAL;

     hr = pdo->GetData(&fe, &stm);

     if( SUCCEEDED(hr) ) {
          
          PDS_SELECTION_LIST pDsSelList = NULL;

          pDsSelList = (PDS_SELECTION_LIST)GlobalLock(stm.hGlobal);
          if(NULL != pDsSelList) {

               ULONG i;

               for (i = 0; i < pDsSelList->cItems; i++) {

                    DS_SELECTION* pDsSel = & (pDsSelList->aDsSelection[i]);
                    
                    printf("[%u]\n", i);
                    printf("  Name  '%ws'\n", pDsSel->pwzName);
                    printf("  Class '%ws'\n", pDsSel->pwzClass);
                    printf("  Path  '%ws'\n", pDsSel->pwzADsPath);
                    printf("  UPN   '%ws'\n", pDsSel->pwzUPN);

                    if ( V_VT(pDsSel->pvarFetchedAttributes) != VT_EMPTY ) {

                         PSID pSid;
                         HRESULT hr = SafeArrayAccessData (
                              V_ARRAY(pDsSel->pvarFetchedAttributes), &pSid);
                         LPTSTR pStringSid;
          
                         if ( ConvertSidToStringSid (pSid, &pStringSid) ) {
                              _tprintf (TEXT("  SID   '%s'\n"), pStringSid);
                              LocalFree (pStringSid);
                         }
                         else {
                              printf (
                                   "SID Error - ConvertSidToStringSid Failed %d\n", 
                                   GetLastError());
                         }
                    }
                    else {
                         printf ("No SID\n");
                    }

               }

               GlobalUnlock(stm.hGlobal);
               
          }
          else {
               hr = E_POINTER;
          }

          ReleaseStgMedium(&stm);

     }

     return hr;
}

今回はリンクするライブラリが多いので、makefile も示します。これをそのまま使うのでしたら、 上記コードは objpick.cpp として保存してください。

TARGETNAME=objpick
OUTDIR=.\chk
LINK32=link.exe

ALL : "$(OUTDIR)\$(TARGETNAME).exe"

CPPFLAGS=\
	/nologo\
	/MT\
	/W4\
	/Fo"$(OUTDIR)\\"\
	/Fd"$(OUTDIR)\\"\
	/c\
	/Zi\
	/DUNICODE\
	/D_UNICODE\
	/DWIN32\
	/D_WIN32_WINNT=0x0600
		
LINK32_FLAGS=\
	ole32.lib\
	user32.lib\
	advapi32.lib\
	oleaut32.lib\
	/nologo\
	/subsystem:console\
	/pdb:"$(OUTDIR)\$(TARGETNAME).pdb"\
	/machine:I386\
	/out:"$(OUTDIR)\$(TARGETNAME).exe"\
	/DEBUG
	
LINK32_OBJS= \
	"$(OUTDIR)\$(TARGETNAME).obj"

"$(OUTDIR)\$(TARGETNAME).exe" : "$(OUTDIR)" $(LINK32_OBJS)
    $(LINK32) $(LINK32_FLAGS) $(LINK32_OBJS)

"$(OUTDIR)" :
    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"


.cpp{$(OUTDIR)}.obj:
   $(CPP) $(CPPFLAGS) $<

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Web/DB プログラミング徹底解説