ディレクトリオブジェクトピッカーの利用方法
ディレクトリ・オブジェクト・ピッカー (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) $<