Process Hacker
dspick.c
Go to the documentation of this file.
1 /*
2  * Process Hacker -
3  * DS object picker wrapper
4  *
5  * Copyright (C) 2010 wj32
6  *
7  * This file is part of Process Hacker.
8  *
9  * Process Hacker is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Process Hacker is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <phgui.h>
24 #include <dspick.h>
25 #define CINTERFACE
26 #define COBJMACROS
27 #include <objsel.h>
28 
29 #define IDataObject_AddRef(This) ((This)->lpVtbl->AddRef(This))
30 #define IDataObject_Release(This) ((This)->lpVtbl->Release(This))
31 #define IDataObject_GetData(This, pformatetcIn, pmedium) ((This)->lpVtbl->GetData(This, pformatetcIn, pmedium))
32 
33 #define IDsObjectPicker_QueryInterface(This, riid, ppvObject) ((This)->lpVtbl->QueryInterface(This, riid, ppvObject))
34 #define IDsObjectPicker_AddRef(This) ((This)->lpVtbl->AddRef(This))
35 #define IDsObjectPicker_Release(This) ((This)->lpVtbl->Release(This))
36 #define IDsObjectPicker_Initialize(This, pInitInfo) ((This)->lpVtbl->Initialize(This, pInitInfo))
37 #define IDsObjectPicker_InvokeDialog(This, hwndParent, ppdoSelections) ((This)->lpVtbl->InvokeDialog(This, hwndParent, ppdoSelections))
38 
39 IDsObjectPicker *PhpCreateDsObjectPicker(
40  VOID
41  )
42 {
43  static CLSID CLSID_DsObjectPicker_I = { 0x17d6ccd8, 0x3b7b, 0x11d2, { 0xb9, 0xe0, 0x00, 0xc0, 0x4f, 0xd8, 0xdb, 0xf7 } };
44  static IID IID_IDsObjectPicker_I = { 0x0c87e64e, 0x3b7a, 0x11d2, { 0xb9, 0xe0, 0x00, 0xc0, 0x4f, 0xd8, 0xdb, 0xf7 } };
45 
46  IDsObjectPicker *picker;
47 
48  if (SUCCEEDED(CoCreateInstance(
49  &CLSID_DsObjectPicker_I,
50  NULL,
51  CLSCTX_INPROC_SERVER,
52  &IID_IDsObjectPicker_I,
53  &picker
54  )))
55  {
56  return picker;
57  }
58  else
59  {
60  return NULL;
61  }
62 }
63 
65  _In_ PVOID PickerDialog
66  )
67 {
68  IDsObjectPicker_Release((IDsObjectPicker *)PickerDialog);
69 }
70 
72  _In_ ULONG Flags
73  )
74 {
75  IDsObjectPicker *picker;
76  DSOP_INIT_INFO initInfo;
77  DSOP_SCOPE_INIT_INFO scopeInit[1];
78 
79  picker = PhpCreateDsObjectPicker();
80 
81  if (!picker)
82  return NULL;
83 
84  memset(scopeInit, 0, sizeof(scopeInit));
85 
86  scopeInit[0].cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
87  scopeInit[0].flType = DSOP_SCOPE_TYPE_TARGET_COMPUTER;
88  scopeInit[0].flScope =
89  DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT |
90  DSOP_SCOPE_FLAG_WANT_SID_PATH |
91  DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS |
92  DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS;
93  scopeInit[0].FilterFlags.Uplevel.flBothModes =
94  DSOP_FILTER_INCLUDE_ADVANCED_VIEW |
95  DSOP_FILTER_USERS |
96  DSOP_FILTER_BUILTIN_GROUPS |
97  DSOP_FILTER_WELL_KNOWN_PRINCIPALS;
98  scopeInit[0].FilterFlags.flDownlevel =
99  DSOP_DOWNLEVEL_FILTER_USERS |
100  DSOP_DOWNLEVEL_FILTER_LOCAL_GROUPS |
101  DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS |
102  DSOP_DOWNLEVEL_FILTER_ALL_WELLKNOWN_SIDS;
103 
104  memset(&initInfo, 0, sizeof(DSOP_INIT_INFO));
105  initInfo.cbSize = sizeof(DSOP_INIT_INFO);
106  initInfo.pwzTargetComputer = NULL;
107  initInfo.cDsScopeInfos = 1;
108  initInfo.aDsScopeInfos = scopeInit;
109  initInfo.flOptions = DSOP_FLAG_SKIP_TARGET_COMPUTER_DC_CHECK;
110 
111  if (Flags & PH_DSPICK_MULTISELECT)
112  initInfo.flOptions |= DSOP_FLAG_MULTISELECT;
113 
114  if (!SUCCEEDED(IDsObjectPicker_Initialize(picker, &initInfo)))
115  {
116  IDsObjectPicker_Release(picker);
117  return NULL;
118  }
119 
120  return picker;
121 }
122 
123 PDS_SELECTION_LIST PhpGetDsSelectionList(
124  _In_ IDataObject *Selections
125  )
126 {
127  FORMATETC format;
128  STGMEDIUM medium;
129 
130  format.cfFormat = (CLIPFORMAT)RegisterClipboardFormat(L"CFSTR_DSOP_DS_SELECTION_LIST");
131  format.ptd = NULL;
132  format.dwAspect = -1;
133  format.lindex = -1;
134  format.tymed = TYMED_HGLOBAL;
135 
136  if (SUCCEEDED(IDataObject_GetData(Selections, &format, &medium)))
137  {
138  if (medium.tymed != TYMED_HGLOBAL)
139  return NULL;
140 
141  return (PDS_SELECTION_LIST)GlobalLock(medium.hGlobal);
142  }
143  else
144  {
145  return NULL;
146  }
147 }
148 
150  _In_ HWND hWnd,
151  _In_ PVOID PickerDialog,
152  _Out_ PPH_DSPICK_OBJECTS *Objects
153  )
154 {
155  IDsObjectPicker *picker;
156  IDataObject *dataObject;
157  PDS_SELECTION_LIST selections;
158  PPH_DSPICK_OBJECTS objects;
159  ULONG i;
160 
161  picker = (IDsObjectPicker *)PickerDialog;
162 
163  if (!SUCCEEDED(IDsObjectPicker_InvokeDialog(picker, hWnd, &dataObject)))
164  return FALSE;
165 
166  if (!dataObject)
167  return FALSE;
168 
169  selections = PhpGetDsSelectionList(dataObject);
170  IDataObject_Release(dataObject);
171 
172  if (!selections)
173  return FALSE;
174 
175  objects = PhAllocate(
176  FIELD_OFFSET(PH_DSPICK_OBJECTS, Objects) +
177  selections->cItems * sizeof(PH_DSPICK_OBJECT)
178  );
179 
180  objects->NumberOfObjects = selections->cItems;
181 
182  for (i = 0; i < selections->cItems; i++)
183  {
184  PDS_SELECTION selection;
185  PSID sid;
186  PH_STRINGREF path;
187  PH_STRINGREF prefix;
188 
189  selection = &selections->aDsSelection[i];
190 
191  objects->Objects[i].Name = PhCreateString(selection->pwzName);
192  objects->Objects[i].Sid = NULL;
193 
194  if (selection->pwzADsPath && selection->pwzADsPath[0] != 0)
195  {
196  PhInitializeStringRef(&path, selection->pwzADsPath);
197  PhInitializeStringRef(&prefix, L"LDAP://<SID=");
198 
199  if (PhStartsWithStringRef(&path, &prefix, TRUE))
200  {
201  PhSkipStringRef(&path, prefix.Length);
202  path.Length -= sizeof(WCHAR); // Ignore ">" at end
203 
204  sid = PhAllocate(path.Length / sizeof(WCHAR) / 2);
205 
206  if (PhHexStringToBuffer(&path, (PUCHAR)sid))
207  {
208  if (RtlValidSid(sid))
209  objects->Objects[i].Sid = sid;
210  else
211  PhFree(sid);
212  }
213  else
214  {
215  PhFree(sid);
216  }
217  }
218  }
219  else
220  {
221  // Try to get the SID.
222  PhLookupName(&objects->Objects[i].Name->sr, &objects->Objects[i].Sid, NULL, NULL);
223  }
224  }
225 
226  *Objects = objects;
227 
228  return TRUE;
229 }
230 
232  _In_ PPH_DSPICK_OBJECTS Objects
233  )
234 {
235  ULONG i;
236 
237  for (i = 0; i < Objects->NumberOfObjects; i++)
238  {
239  PhDereferenceObject(Objects->Objects[i].Name);
240 
241  if (Objects->Objects[i].Sid)
242  PhFree(Objects->Objects[i].Sid);
243  }
244 
245  PhFree(Objects);
246 }