/* * Process Hacker - * DS object picker wrapper * * Copyright (C) 2010 wj32 * * This file is part of Process Hacker. * * Process Hacker is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Process Hacker is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Process Hacker. If not, see . */ #include #include #include #include #include #define CINTERFACE #define COBJMACROS #include #define IDataObject_AddRef(This) ((This)->lpVtbl->AddRef(This)) #define IDataObject_Release(This) ((This)->lpVtbl->Release(This)) #define IDataObject_GetData(This, pformatetcIn, pmedium) ((This)->lpVtbl->GetData(This, pformatetcIn, pmedium)) #define IDsObjectPicker_QueryInterface(This, riid, ppvObject) ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) #define IDsObjectPicker_AddRef(This) ((This)->lpVtbl->AddRef(This)) #define IDsObjectPicker_Release(This) ((This)->lpVtbl->Release(This)) #define IDsObjectPicker_Initialize(This, pInitInfo) ((This)->lpVtbl->Initialize(This, pInitInfo)) #define IDsObjectPicker_InvokeDialog(This, hwndParent, ppdoSelections) ((This)->lpVtbl->InvokeDialog(This, hwndParent, ppdoSelections)) IDsObjectPicker *PhpCreateDsObjectPicker( VOID ) { static CLSID CLSID_DsObjectPicker_I = { 0x17d6ccd8, 0x3b7b, 0x11d2, { 0xb9, 0xe0, 0x00, 0xc0, 0x4f, 0xd8, 0xdb, 0xf7 } }; static IID IID_IDsObjectPicker_I = { 0x0c87e64e, 0x3b7a, 0x11d2, { 0xb9, 0xe0, 0x00, 0xc0, 0x4f, 0xd8, 0xdb, 0xf7 } }; IDsObjectPicker *picker; if (SUCCEEDED(CoCreateInstance( &CLSID_DsObjectPicker_I, NULL, CLSCTX_INPROC_SERVER, &IID_IDsObjectPicker_I, &picker ))) { return picker; } else { return NULL; } } VOID PhFreeDsObjectPickerDialog( _In_ PVOID PickerDialog ) { IDsObjectPicker_Release((IDsObjectPicker *)PickerDialog); } PVOID PhCreateDsObjectPickerDialog( _In_ ULONG Flags ) { IDsObjectPicker *picker; DSOP_INIT_INFO initInfo; DSOP_SCOPE_INIT_INFO scopeInit[1]; picker = PhpCreateDsObjectPicker(); if (!picker) return NULL; memset(scopeInit, 0, sizeof(scopeInit)); scopeInit[0].cbSize = sizeof(DSOP_SCOPE_INIT_INFO); scopeInit[0].flType = DSOP_SCOPE_TYPE_TARGET_COMPUTER; scopeInit[0].flScope = DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT | DSOP_SCOPE_FLAG_WANT_SID_PATH | DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS | DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS; scopeInit[0].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS | DSOP_FILTER_BUILTIN_GROUPS | DSOP_FILTER_WELL_KNOWN_PRINCIPALS; scopeInit[0].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS | DSOP_DOWNLEVEL_FILTER_LOCAL_GROUPS | DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS | DSOP_DOWNLEVEL_FILTER_ALL_WELLKNOWN_SIDS; memset(&initInfo, 0, sizeof(DSOP_INIT_INFO)); initInfo.cbSize = sizeof(DSOP_INIT_INFO); initInfo.pwzTargetComputer = NULL; initInfo.cDsScopeInfos = 1; initInfo.aDsScopeInfos = scopeInit; initInfo.flOptions = DSOP_FLAG_SKIP_TARGET_COMPUTER_DC_CHECK; if (Flags & PH_DSPICK_MULTISELECT) initInfo.flOptions |= DSOP_FLAG_MULTISELECT; if (!SUCCEEDED(IDsObjectPicker_Initialize(picker, &initInfo))) { IDsObjectPicker_Release(picker); return NULL; } return picker; } PDS_SELECTION_LIST PhpGetDsSelectionList( _In_ IDataObject *Selections ) { FORMATETC format; STGMEDIUM medium; format.cfFormat = (CLIPFORMAT)RegisterClipboardFormat(L"CFSTR_DSOP_DS_SELECTION_LIST"); format.ptd = NULL; format.dwAspect = -1; format.lindex = -1; format.tymed = TYMED_HGLOBAL; if (SUCCEEDED(IDataObject_GetData(Selections, &format, &medium))) { if (medium.tymed != TYMED_HGLOBAL) return NULL; return (PDS_SELECTION_LIST)GlobalLock(medium.hGlobal); } else { return NULL; } } BOOLEAN PhShowDsObjectPickerDialog( _In_ HWND hWnd, _In_ PVOID PickerDialog, _Out_ PPH_DSPICK_OBJECTS *Objects ) { IDsObjectPicker *picker; IDataObject *dataObject; PDS_SELECTION_LIST selections; PPH_DSPICK_OBJECTS objects; ULONG i; picker = (IDsObjectPicker *)PickerDialog; if (!SUCCEEDED(IDsObjectPicker_InvokeDialog(picker, hWnd, &dataObject))) return FALSE; if (!dataObject) return FALSE; selections = PhpGetDsSelectionList(dataObject); IDataObject_Release(dataObject); if (!selections) return FALSE; objects = PhAllocate( FIELD_OFFSET(PH_DSPICK_OBJECTS, Objects) + selections->cItems * sizeof(PH_DSPICK_OBJECT) ); objects->NumberOfObjects = selections->cItems; for (i = 0; i < selections->cItems; i++) { PDS_SELECTION selection; PSID sid; PH_STRINGREF path; PH_STRINGREF prefix; selection = &selections->aDsSelection[i]; objects->Objects[i].Name = PhCreateString(selection->pwzName); objects->Objects[i].Sid = NULL; if (selection->pwzADsPath && selection->pwzADsPath[0] != 0) { PhInitializeStringRef(&path, selection->pwzADsPath); PhInitializeStringRef(&prefix, L"LDAP://" at end sid = PhAllocate(path.Length / sizeof(WCHAR) / 2); if (PhHexStringToBuffer(&path, (PUCHAR)sid)) { if (RtlValidSid(sid)) objects->Objects[i].Sid = sid; else PhFree(sid); } else { PhFree(sid); } } } else { // Try to get the SID. PhLookupName(&objects->Objects[i].Name->sr, &objects->Objects[i].Sid, NULL, NULL); } } *Objects = objects; return TRUE; } VOID PhFreeDsObjectPickerObjects( _In_ PPH_DSPICK_OBJECTS Objects ) { ULONG i; for (i = 0; i < Objects->NumberOfObjects; i++) { PhDereferenceObject(Objects->Objects[i].Name); if (Objects->Objects[i].Sid) PhFree(Objects->Objects[i].Sid); } PhFree(Objects); }