Sync with trunk r63383 .
[reactos.git] / base / applications / regedit / security.c
1 /*
2 * Regedit ACL Editor for Registry Keys
3 *
4 * Copyright (C) 2004 - 2006 Thomas Weidenmueller <w3seek@reactos.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "regedit.h"
22
23 #define INITGUID
24 #include <guiddef.h>
25
26 /* FIXME - shouldn't be defined here... */
27 DEFINE_GUID(IID_IRegKeySecurity, 0x965fc360, 0x16ff, 0x11d0, 0x0091, 0xcb,0x00,0xaa,0x00,0xbb,0xb7,0x23);
28 #if REGEDIT_IMPLEMENT_ISECURITYINFORMATION2
29 DEFINE_GUID(IID_IRegKeySecurity2, 0xc3ccfdb4, 0x6f88, 0x11d2, 0x00a3, 0xce,0x00,0xc0,0x4f,0xb1,0x78,0x2a);
30 #endif
31
32 /* FIXME: already defined in aclui.h - causing problems when compiling with MSVC/PSDK*/
33 #ifdef _MSC_VER
34 #pragma message ("INVESTIGATE ME")
35 #endif
36
37 #if 1 //#ifndef _MSC_VER
38 DEFINE_GUID(IID_IEffectivePermission, 0x3853dc76, 0x9f35, 0x407c, 0x0088, 0xa1,0xd1,0x93,0x44,0x36,0x5f,0xbc);
39 DEFINE_GUID(IID_ISecurityObjectTypeInfo, 0xfc3066eb, 0x79ef, 0x444b, 0x0091, 0x11,0xd1,0x8a,0x75,0xeb,0xf2,0xfa);
40 #endif
41
42 /******************************************************************************
43 Implementation of the IUnknown methods of CRegKeySecurity
44 ******************************************************************************/
45
46 static __inline PCRegKeySecurity
47 impl_from_ISecurityInformation(struct ISecurityInformation *iface)
48 {
49 return (PCRegKeySecurity)((ULONG_PTR)iface - FIELD_OFFSET(CRegKeySecurity,
50 lpISecurityInformationVtbl));
51 }
52
53 #if REGEDIT_IMPLEMENT_ISECURITYINFORMATION2
54 static __inline PCRegKeySecurity
55 impl_from_ISecurityInformation2(struct ISecurityInformation2 *iface)
56 {
57 return (PCRegKeySecurity)((ULONG_PTR)iface - FIELD_OFFSET(CRegKeySecurity,
58 lpISecurityInformation2Vtbl));
59 }
60 #endif
61
62 static __inline PCRegKeySecurity
63 impl_from_ISecurityObjectTypeInfo(struct ISecurityObjectTypeInfo *iface)
64 {
65 return (PCRegKeySecurity)((ULONG_PTR)iface - FIELD_OFFSET(CRegKeySecurity,
66 lpISecurityObjectTypeInfoVtbl));
67 }
68
69 static __inline PCRegKeySecurity
70 impl_from_IEffectivePermission(struct IEffectivePermission *iface)
71 {
72 return (PCRegKeySecurity)((ULONG_PTR)iface - FIELD_OFFSET(CRegKeySecurity,
73 lpIEffectivePermissionVtbl));
74 }
75
76 #define impl_to_interface(impl,iface) (struct iface *)(&(impl)->lp##iface##Vtbl)
77
78 static __inline ULONG
79 CRegKeySecurity_fnAddRef(PCRegKeySecurity obj)
80 {
81 return (ULONG)InterlockedIncrement((LONG*)&obj->ref);
82 }
83
84 static __inline ULONG
85 CRegKeySecurity_fnRelease(PCRegKeySecurity obj)
86 {
87 ULONG Ret;
88
89 Ret = (ULONG)InterlockedDecrement((LONG*)&obj->ref);
90 if (Ret == 0)
91 {
92 HeapFree(GetProcessHeap(),
93 0,
94 obj);
95 }
96
97 return Ret;
98 }
99
100 static __inline HRESULT
101 CRegKeySecurity_fnQueryInterface(PCRegKeySecurity obj,
102 REFIID iid,
103 PVOID *pvObject)
104 {
105 PVOID pvObj = NULL;
106
107 if (IsEqualGUID(iid,
108 &IID_IRegKeySecurity))
109 {
110 pvObj = (PVOID)impl_to_interface(obj,
111 ISecurityInformation);
112 }
113 #if REGEDIT_IMPLEMENT_ISECURITYINFORMATION2
114 else if (IsEqualGUID(iid,
115 &IID_IRegKeySecurity2))
116 {
117 pvObj = (PVOID)impl_to_interface(obj,
118 ISecurityInformation2);
119 }
120 #endif
121 else if (IsEqualGUID(iid,
122 &IID_IEffectivePermission))
123 {
124 pvObj = (PVOID)impl_to_interface(obj,
125 IEffectivePermission);
126 }
127 else if (IsEqualGUID(iid,
128 &IID_ISecurityObjectTypeInfo))
129 {
130 pvObj = (PVOID)impl_to_interface(obj,
131 ISecurityObjectTypeInfo);
132 }
133
134 if (pvObj == NULL)
135 {
136 return E_NOINTERFACE;
137 }
138
139 *pvObject = pvObj;
140 CRegKeySecurity_fnAddRef(obj);
141
142 return S_OK;
143 }
144
145
146 /******************************************************************************
147 Definition of the ISecurityInformation interface
148 ******************************************************************************/
149
150 /* IUnknown */
151 static HRESULT STDMETHODCALLTYPE
152 ISecurityInformation_fnQueryInterface(struct ISecurityInformation *this,
153 REFIID iid,
154 PVOID *pvObject);
155
156 static ULONG STDMETHODCALLTYPE
157 ISecurityInformation_fnAddRef(struct ISecurityInformation *this);
158
159 static ULONG STDMETHODCALLTYPE
160 ISecurityInformation_fnRelease(struct ISecurityInformation *this);
161
162 /* ISecurityInformation */
163 static HRESULT STDMETHODCALLTYPE
164 ISecurityInformation_fnGetObjectInformation(struct ISecurityInformation *this,
165 PSI_OBJECT_INFO pObjectInfo);
166
167 static HRESULT STDMETHODCALLTYPE
168 ISecurityInformation_fnGetSecurity(struct ISecurityInformation *this,
169 SECURITY_INFORMATION RequestedInformation,
170 PSECURITY_DESCRIPTOR* ppSecurityDescriptor,
171 BOOL fDefault);
172
173 static HRESULT STDMETHODCALLTYPE
174 ISecurityInformation_fnSetSecurity(struct ISecurityInformation *this,
175 SECURITY_INFORMATION RequestedInformation,
176 PSECURITY_DESCRIPTOR pSecurityDescriptor);
177
178 static HRESULT STDMETHODCALLTYPE
179 ISecurityInformation_fnGetAccessRights(struct ISecurityInformation *this,
180 const GUID* pguidObjectType,
181 DWORD dwFlags,
182 PSI_ACCESS* ppAccess,
183 ULONG* pcAccesses,
184 ULONG* piDefaultAccess);
185
186 static HRESULT STDMETHODCALLTYPE
187 ISecurityInformation_fnMapGeneric(struct ISecurityInformation *this,
188 const GUID* pguidObjectType,
189 UCHAR* pAceFlags,
190 ACCESS_MASK* pMask);
191
192 static HRESULT STDMETHODCALLTYPE
193 ISecurityInformation_fnGetInheritTypes(struct ISecurityInformation *this,
194 PSI_INHERIT_TYPE* ppInheritTypes,
195 ULONG* pcInheritTypes);
196 static HRESULT STDMETHODCALLTYPE
197 ISecurityInformation_fnPropertySheetPageCallback(struct ISecurityInformation *this,
198 HWND hwnd,
199 UINT uMsg,
200 SI_PAGE_TYPE uPage);
201
202 static const struct ifaceISecurityInformationVbtl vtblISecurityInformation =
203 {
204 /* IUnknown methods */
205 ISecurityInformation_fnQueryInterface,
206 ISecurityInformation_fnAddRef,
207 ISecurityInformation_fnRelease,
208
209 /* ISecurityInformation methods */
210 ISecurityInformation_fnGetObjectInformation,
211 ISecurityInformation_fnGetSecurity,
212 ISecurityInformation_fnSetSecurity,
213 ISecurityInformation_fnGetAccessRights,
214 ISecurityInformation_fnMapGeneric,
215 ISecurityInformation_fnGetInheritTypes,
216 ISecurityInformation_fnPropertySheetPageCallback,
217 };
218
219 #if REGEDIT_IMPLEMENT_ISECURITYINFORMATION2
220 /******************************************************************************
221 Definition of the ISecurityInformation2 interface
222 ******************************************************************************/
223
224 /* IUnknown */
225 static HRESULT STDMETHODCALLTYPE
226 ISecurityInformation2_fnQueryInterface(struct ISecurityInformation2 *this,
227 REFIID iid,
228 PVOID *pvObject);
229
230 static ULONG STDMETHODCALLTYPE
231 ISecurityInformation2_fnAddRef(struct ISecurityInformation2 *this);
232
233 static ULONG STDMETHODCALLTYPE
234 ISecurityInformation2_fnRelease(struct ISecurityInformation2 *this);
235
236 /* ISecurityInformation2 */
237 static BOOL STDMETHODCALLTYPE
238 ISecurityInformation2_fnIsDaclCanonical(struct ISecurityInformation2 *this,
239 PACL pDacl);
240
241 static HRESULT STDMETHODCALLTYPE
242 ISecurityInformation2_fnLookupSids(struct ISecurityInformation2 *this,
243 ULONG cSids,
244 PSID* rgpSids,
245 LPDATAOBJECT* ppdo);
246
247 static const struct ifaceISecurityInformation2Vbtl vtblISecurityInformation2 =
248 {
249 /* IUnknown methods */
250 ISecurityInformation2_fnQueryInterface,
251 ISecurityInformation2_fnAddRef,
252 ISecurityInformation2_fnRelease,
253
254 /* ISecurityInformation2 methods */
255 ISecurityInformation2_fnIsDaclCanonical,
256 ISecurityInformation2_fnLookupSids
257 };
258 #endif
259
260 /******************************************************************************
261 Definition of the IEffectivePermission interface
262 ******************************************************************************/
263
264 /* IUnknown */
265 static HRESULT STDMETHODCALLTYPE
266 IEffectivePermission_fnQueryInterface(struct IEffectivePermission *this,
267 REFIID iid,
268 PVOID *pvObject);
269
270 static ULONG STDMETHODCALLTYPE
271 IEffectivePermission_fnAddRef(struct IEffectivePermission *this);
272
273 static ULONG STDMETHODCALLTYPE
274 IEffectivePermission_fnRelease(struct IEffectivePermission *this);
275
276 /* IEffectivePermission */
277 static HRESULT STDMETHODCALLTYPE
278 IEffectivePermission_fnGetEffectivePermission(struct IEffectivePermission *this,
279 const GUID* pguidObjectType,
280 PSID pUserSid,
281 LPCWSTR pszServerName,
282 PSECURITY_DESCRIPTOR pSD,
283 POBJECT_TYPE_LIST* ppObjectTypeList,
284 ULONG* pcObjectTypeListLength,
285 PACCESS_MASK* ppGrantedAccessList,
286 ULONG* pcGrantedAccessListLength);
287
288 static const struct ifaceIEffectivePermissionVbtl vtblIEffectivePermission =
289 {
290 /* IUnknown methods */
291 IEffectivePermission_fnQueryInterface,
292 IEffectivePermission_fnAddRef,
293 IEffectivePermission_fnRelease,
294
295 /* IEffectivePermissions methods */
296 IEffectivePermission_fnGetEffectivePermission
297 };
298
299 /******************************************************************************
300 Definition of the ISecurityObjectTypeInfo interface
301 ******************************************************************************/
302
303 /* IUnknown */
304 static HRESULT STDMETHODCALLTYPE
305 ISecurityObjectTypeInfo_fnQueryInterface(struct ISecurityObjectTypeInfo *this,
306 REFIID iid,
307 PVOID *pvObject);
308
309 static ULONG STDMETHODCALLTYPE
310 ISecurityObjectTypeInfo_fnAddRef(struct ISecurityObjectTypeInfo *this);
311
312 static ULONG STDMETHODCALLTYPE
313 ISecurityObjectTypeInfo_fnRelease(struct ISecurityObjectTypeInfo *this);
314
315 /* ISecurityObjectTypeInfo */
316 static HRESULT STDMETHODCALLTYPE
317 ISecurityObjectTypeInfo_fnGetInheritSource(struct ISecurityObjectTypeInfo *this,
318 SECURITY_INFORMATION si,
319 PACL pACL,
320 PINHERITED_FROM* ppInheritArray);
321
322 static const struct ifaceISecurityObjectTypeInfoVbtl vtblISecurityObjectTypeInfo =
323 {
324 /* IUnknown methods */
325 ISecurityObjectTypeInfo_fnQueryInterface,
326 ISecurityObjectTypeInfo_fnAddRef,
327 ISecurityObjectTypeInfo_fnRelease,
328
329 /* ISecurityObjectTypeInfo methods */
330 ISecurityObjectTypeInfo_fnGetInheritSource
331 };
332
333
334 /******************************************************************************
335 Implementation of the ISecurityInformation interface
336 ******************************************************************************/
337
338 static SI_ACCESS RegAccess[] = {
339 {&GUID_NULL, KEY_ALL_ACCESS, MAKEINTRESOURCEW(IDS_ACCESS_FULLCONTROL), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC},
340 {&GUID_NULL, KEY_READ, MAKEINTRESOURCEW(IDS_ACCESS_READ), SI_ACCESS_GENERAL},
341 {&GUID_NULL, KEY_QUERY_VALUE, MAKEINTRESOURCEW(IDS_ACCESS_QUERYVALUE), SI_ACCESS_SPECIFIC},
342 {&GUID_NULL, KEY_SET_VALUE, MAKEINTRESOURCEW(IDS_ACCESS_SETVALUE), SI_ACCESS_SPECIFIC},
343 {&GUID_NULL, KEY_CREATE_SUB_KEY, MAKEINTRESOURCEW(IDS_ACCESS_CREATESUBKEY), SI_ACCESS_SPECIFIC},
344 {&GUID_NULL, KEY_ENUMERATE_SUB_KEYS, MAKEINTRESOURCEW(IDS_ACCESS_ENUMERATESUBKEYS), SI_ACCESS_SPECIFIC},
345 {&GUID_NULL, KEY_NOTIFY, MAKEINTRESOURCEW(IDS_ACCESS_NOTIFY), SI_ACCESS_SPECIFIC},
346 {&GUID_NULL, KEY_CREATE_LINK, MAKEINTRESOURCEW(IDS_ACCESS_CREATELINK), SI_ACCESS_SPECIFIC},
347 {&GUID_NULL, DELETE, MAKEINTRESOURCEW(IDS_ACCESS_DELETE), SI_ACCESS_SPECIFIC},
348 {&GUID_NULL, WRITE_DAC, MAKEINTRESOURCEW(IDS_ACCESS_WRITEDAC), SI_ACCESS_SPECIFIC},
349 {&GUID_NULL, WRITE_OWNER, MAKEINTRESOURCEW(IDS_ACCESS_WRITEOWNER), SI_ACCESS_SPECIFIC},
350 {&GUID_NULL, READ_CONTROL, MAKEINTRESOURCEW(IDS_ACCESS_READCONTROL), SI_ACCESS_SPECIFIC},
351 };
352
353 static const DWORD RegDefaultAccess = 1; /* KEY_READ */
354
355 static GENERIC_MAPPING RegAccessMasks = {
356 KEY_READ,
357 KEY_WRITE,
358 KEY_EXECUTE,
359 KEY_ALL_ACCESS
360 };
361
362 static SI_INHERIT_TYPE RegInheritTypes[] = {
363 {&GUID_NULL, 0, (LPWSTR)MAKEINTRESOURCEW(IDS_INHERIT_THISKEYONLY)},
364 {&GUID_NULL, CONTAINER_INHERIT_ACE, (LPWSTR)MAKEINTRESOURCEW(IDS_INHERIT_THISKEYANDSUBKEYS)},
365 {&GUID_NULL, INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE, (LPWSTR)MAKEINTRESOURCEW(IDS_INHERIT_SUBKEYSONLY)},
366 };
367
368 static HRESULT STDMETHODCALLTYPE
369 ISecurityInformation_fnQueryInterface(struct ISecurityInformation *this,
370 REFIID iid,
371 PVOID *pvObject)
372 {
373 if (IsEqualGUID(iid,
374 &IID_IUnknown))
375 {
376 *pvObject = (PVOID)this;
377 ISecurityInformation_fnAddRef(this);
378 return S_OK;
379 }
380
381 return CRegKeySecurity_fnQueryInterface(impl_from_ISecurityInformation(this),
382 iid,
383 pvObject);
384 }
385
386 static ULONG STDMETHODCALLTYPE
387 ISecurityInformation_fnAddRef(struct ISecurityInformation *this)
388 {
389 return CRegKeySecurity_fnAddRef(impl_from_ISecurityInformation(this));
390 }
391
392 static ULONG STDMETHODCALLTYPE
393 ISecurityInformation_fnRelease(struct ISecurityInformation *this)
394 {
395 return CRegKeySecurity_fnRelease(impl_from_ISecurityInformation(this));
396 }
397
398 static HRESULT STDMETHODCALLTYPE
399 ISecurityInformation_fnGetObjectInformation(struct ISecurityInformation *this,
400 PSI_OBJECT_INFO pObjectInfo)
401 {
402 PCRegKeySecurity obj = impl_from_ISecurityInformation(this);
403
404 *pObjectInfo = obj->ObjectInfo;
405 return S_OK;
406 }
407
408 static HRESULT STDMETHODCALLTYPE
409 ISecurityInformation_fnGetSecurity(struct ISecurityInformation *this,
410 SECURITY_INFORMATION RequestedInformation,
411 PSECURITY_DESCRIPTOR* ppSecurityDescriptor,
412 BOOL fDefault)
413 {
414 PCRegKeySecurity obj = impl_from_ISecurityInformation(this);
415 LONG ErrorCode;
416
417 ErrorCode = GetNamedSecurityInfoW(obj->szRegKey,
418 SE_REGISTRY_KEY,
419 RequestedInformation,
420 NULL,
421 NULL,
422 NULL,
423 NULL,
424 ppSecurityDescriptor);
425
426 return HRESULT_FROM_WIN32(ErrorCode);
427 }
428
429 static HRESULT STDMETHODCALLTYPE
430 ISecurityInformation_fnSetSecurity(struct ISecurityInformation *this,
431 SECURITY_INFORMATION RequestedInformation,
432 PSECURITY_DESCRIPTOR pSecurityDescriptor)
433 {
434 PCRegKeySecurity obj = impl_from_ISecurityInformation(this);
435
436 /* FIXME */
437 *obj->Btn = TRUE;
438 return S_OK;
439 }
440
441 static HRESULT STDMETHODCALLTYPE
442 ISecurityInformation_fnGetAccessRights(struct ISecurityInformation *this,
443 const GUID* pguidObjectType,
444 DWORD dwFlags,
445 PSI_ACCESS* ppAccess,
446 ULONG* pcAccesses,
447 ULONG* piDefaultAccess)
448 {
449 *ppAccess = RegAccess;
450 *pcAccesses = COUNT_OF(RegAccess);
451 *piDefaultAccess = RegDefaultAccess;
452 return S_OK;
453 }
454
455 static HRESULT STDMETHODCALLTYPE
456 ISecurityInformation_fnMapGeneric(struct ISecurityInformation *this,
457 const GUID* pguidObjectType,
458 UCHAR* pAceFlags,
459 ACCESS_MASK* pMask)
460 {
461 MapGenericMask(pMask,
462 &RegAccessMasks);
463 *pMask &= ~SYNCHRONIZE;
464 return S_OK;
465 }
466
467 static HRESULT STDMETHODCALLTYPE
468 ISecurityInformation_fnGetInheritTypes(struct ISecurityInformation *this,
469 PSI_INHERIT_TYPE* ppInheritTypes,
470 ULONG* pcInheritTypes)
471 {
472 PCRegKeySecurity obj = impl_from_ISecurityInformation(this);
473
474 /* FIXME */
475 if (obj->ObjectInfo.dwFlags & SI_CONTAINER)
476 {
477 *ppInheritTypes = RegInheritTypes;
478 *pcInheritTypes = COUNT_OF(RegInheritTypes);
479 return S_OK;
480 }
481
482 return E_NOTIMPL;
483 }
484
485 static HRESULT STDMETHODCALLTYPE
486 ISecurityInformation_fnPropertySheetPageCallback(struct ISecurityInformation *this,
487 HWND hwnd,
488 UINT uMsg,
489 SI_PAGE_TYPE uPage)
490 {
491 return S_OK;
492 }
493
494 #if REGEDIT_IMPLEMENT_ISECURITYINFORMATION2
495 /******************************************************************************
496 Implementation of the ISecurityInformation2 interface
497 ******************************************************************************/
498
499 static HRESULT STDMETHODCALLTYPE
500 ISecurityInformation2_fnQueryInterface(struct ISecurityInformation2 *this,
501 REFIID iid,
502 PVOID *pvObject)
503 {
504 if (IsEqualGUID(iid,
505 &IID_IUnknown))
506 {
507 *pvObject = (PVOID)this;
508 ISecurityInformation2_fnAddRef(this);
509 return S_OK;
510 }
511
512 return CRegKeySecurity_fnQueryInterface(impl_from_ISecurityInformation2(this),
513 iid,
514 pvObject);
515 }
516
517 static ULONG STDMETHODCALLTYPE
518 ISecurityInformation2_fnAddRef(struct ISecurityInformation2 *this)
519 {
520 return CRegKeySecurity_fnAddRef(impl_from_ISecurityInformation2(this));
521 }
522
523 static ULONG STDMETHODCALLTYPE
524 ISecurityInformation2_fnRelease(struct ISecurityInformation2 *this)
525 {
526 return CRegKeySecurity_fnRelease(impl_from_ISecurityInformation2(this));
527 }
528
529 static BOOL STDMETHODCALLTYPE
530 ISecurityInformation2_fnIsDaclCanonical(struct ISecurityInformation2 *this,
531 PACL pDacl)
532 {
533 /* FIXME */
534 return TRUE;
535 }
536
537 static HRESULT STDMETHODCALLTYPE
538 ISecurityInformation2_fnLookupSids(struct ISecurityInformation2 *this,
539 ULONG cSids,
540 PSID* rgpSids,
541 LPDATAOBJECT* ppdo)
542 {
543 /* FIXME */
544 return E_NOTIMPL;
545 }
546 #endif
547
548 /******************************************************************************
549 Implementation of the IEffectivePermission interface
550 ******************************************************************************/
551
552 static HRESULT STDMETHODCALLTYPE
553 IEffectivePermission_fnQueryInterface(struct IEffectivePermission *this,
554 REFIID iid,
555 PVOID *pvObject)
556 {
557 if (IsEqualGUID(iid,
558 &IID_IUnknown))
559 {
560 *pvObject = (PVOID)this;
561 IEffectivePermission_fnAddRef(this);
562 return S_OK;
563 }
564
565 return CRegKeySecurity_fnQueryInterface(impl_from_IEffectivePermission(this),
566 iid,
567 pvObject);
568 }
569
570 static ULONG STDMETHODCALLTYPE
571 IEffectivePermission_fnAddRef(struct IEffectivePermission *this)
572 {
573 return CRegKeySecurity_fnAddRef(impl_from_IEffectivePermission(this));
574 }
575
576 static ULONG STDMETHODCALLTYPE
577 IEffectivePermission_fnRelease(struct IEffectivePermission *this)
578 {
579 return CRegKeySecurity_fnRelease(impl_from_IEffectivePermission(this));
580 }
581
582 static HRESULT STDMETHODCALLTYPE
583 IEffectivePermission_fnGetEffectivePermission(struct IEffectivePermission *this,
584 const GUID* pguidObjectType,
585 PSID pUserSid,
586 LPCWSTR pszServerName,
587 PSECURITY_DESCRIPTOR pSD,
588 POBJECT_TYPE_LIST* ppObjectTypeList,
589 ULONG* pcObjectTypeListLength,
590 PACCESS_MASK* ppGrantedAccessList,
591 ULONG* pcGrantedAccessListLength)
592 {
593 PACL Dacl = NULL;
594 BOOL DaclPresent, DaclDefaulted;
595 PACCESS_MASK GrantedAccessList;
596 DWORD ErrorCode = ERROR_SUCCESS;
597 TRUSTEE Trustee = {0};
598 static OBJECT_TYPE_LIST DefObjTypeList = {0};
599
600 *ppObjectTypeList = &DefObjTypeList;
601 *pcObjectTypeListLength = 1;
602
603 BuildTrusteeWithSid(&Trustee,
604 pUserSid);
605
606 if (GetSecurityDescriptorDacl(pSD,
607 &DaclPresent,
608 &Dacl,
609 &DaclDefaulted) && DaclPresent)
610 {
611 GrantedAccessList = (PACCESS_MASK)LocalAlloc(LMEM_FIXED,
612 sizeof(ACCESS_MASK));
613 if (GrantedAccessList == NULL)
614 {
615 goto Fail;
616 }
617
618 ErrorCode = GetEffectiveRightsFromAcl(Dacl,
619 &Trustee,
620 GrantedAccessList);
621 if (ErrorCode == ERROR_SUCCESS)
622 {
623 *ppGrantedAccessList = GrantedAccessList;
624 *pcGrantedAccessListLength = 1;
625 }
626 else
627 LocalFree((HLOCAL)GrantedAccessList);
628 }
629 else
630 Fail:
631 ErrorCode = GetLastError();
632
633 return HRESULT_FROM_WIN32(ErrorCode);
634 }
635
636 /******************************************************************************
637 Implementation of the ISecurityObjectTypeInfo interface
638 ******************************************************************************/
639
640 static HRESULT STDMETHODCALLTYPE
641 ISecurityObjectTypeInfo_fnQueryInterface(struct ISecurityObjectTypeInfo *this,
642 REFIID iid,
643 PVOID *pvObject)
644 {
645 if (IsEqualGUID(iid,
646 &IID_IUnknown))
647 {
648 *pvObject = (PVOID)this;
649 ISecurityObjectTypeInfo_fnAddRef(this);
650 return S_OK;
651 }
652
653 return CRegKeySecurity_fnQueryInterface(impl_from_ISecurityObjectTypeInfo(this),
654 iid,
655 pvObject);
656 }
657
658 static ULONG STDMETHODCALLTYPE
659 ISecurityObjectTypeInfo_fnAddRef(struct ISecurityObjectTypeInfo *this)
660 {
661 return CRegKeySecurity_fnAddRef(impl_from_ISecurityObjectTypeInfo(this));
662 }
663
664 static ULONG STDMETHODCALLTYPE
665 ISecurityObjectTypeInfo_fnRelease(struct ISecurityObjectTypeInfo *this)
666 {
667 return CRegKeySecurity_fnRelease(impl_from_ISecurityObjectTypeInfo(this));
668 }
669
670 static HRESULT STDMETHODCALLTYPE
671 ISecurityObjectTypeInfo_fnGetInheritSource(struct ISecurityObjectTypeInfo *this,
672 SECURITY_INFORMATION si,
673 PACL pACL,
674 PINHERITED_FROM* ppInheritArray)
675 {
676 PCRegKeySecurity obj = impl_from_ISecurityObjectTypeInfo(this);
677 PINHERITED_FROM pif, pif2;
678 SIZE_T pifSize;
679 DWORD ErrorCode, i;
680 LPWSTR lpBuf;
681
682 pifSize = pACL->AceCount * sizeof(INHERITED_FROM);
683 pif = (PINHERITED_FROM)HeapAlloc(GetProcessHeap(),
684 0,
685 pifSize);
686 if (pif == NULL)
687 {
688 return E_OUTOFMEMORY;
689 }
690
691 ErrorCode = GetInheritanceSourceW(obj->szRegKey,
692 SE_REGISTRY_KEY,
693 si,
694 (obj->ObjectInfo.dwFlags & SI_CONTAINER) != 0,
695 NULL,
696 0,
697 pACL,
698 NULL,
699 &RegAccessMasks,
700 pif);
701
702 if (ErrorCode == ERROR_SUCCESS)
703 {
704 /* Calculate the size of the buffer to return */
705 for (i = 0;
706 i < pACL->AceCount;
707 i++)
708 {
709 if (pif[i].AncestorName != NULL)
710 {
711 pifSize += (wcslen(pif[i].AncestorName) + 1) * sizeof(WCHAR);
712 }
713 }
714
715 /* Allocate enough space for the array and the strings */
716 pif2 = (PINHERITED_FROM)LocalAlloc(LMEM_FIXED,
717 pifSize);
718 if (pif2 == NULL)
719 {
720 ErrorCode = GetLastError();
721 goto Cleanup;
722 }
723
724 /* copy the array and strings to the buffer */
725 lpBuf = (LPWSTR)((ULONG_PTR)pif2 + (pACL->AceCount * sizeof(INHERITED_FROM)));
726 for (i = 0;
727 i < pACL->AceCount;
728 i++)
729 {
730 pif2[i].GenerationGap = pif[i].GenerationGap;
731 if (pif[i].AncestorName != NULL)
732 {
733 pif2[i].AncestorName = lpBuf;
734 wcscpy(lpBuf,
735 pif[i].AncestorName);
736 lpBuf += wcslen(pif[i].AncestorName) + 1;
737 }
738 else
739 pif2[i].AncestorName = NULL;
740 }
741
742 /* return the newly allocated array */
743 *ppInheritArray = pif2;
744 }
745
746 Cleanup:
747 FreeInheritedFromArray(pif,
748 pACL->AceCount,
749 NULL);
750 HeapFree(GetProcessHeap(),
751 0,
752 pif);
753
754 return HRESULT_FROM_WIN32(ErrorCode);
755 }
756
757 /******************************************************************************
758 Implementation of the CRegKeySecurity constructor
759 ******************************************************************************/
760
761 static PCRegKeySecurity
762 CRegKeySecurity_fnConstructor(LPWSTR lpRegKey,
763 HKEY hRootKey,
764 SI_OBJECT_INFO *ObjectInfo,
765 BOOL *Btn)
766 {
767 PCRegKeySecurity obj;
768
769 obj = (PCRegKeySecurity)HeapAlloc(GetProcessHeap(),
770 HEAP_ZERO_MEMORY,
771 FIELD_OFFSET(CRegKeySecurity,
772 szRegKey[wcslen(lpRegKey) + 1]));
773 if (obj != NULL)
774 {
775 obj->ref = 1;
776 obj->lpISecurityInformationVtbl = &vtblISecurityInformation;
777 #if REGEDIT_IMPLEMENT_ISECURITYINFORMATION2
778 obj->lpISecurityInformation2Vtbl = &vtblISecurityInformation2;
779 #endif
780 obj->lpIEffectivePermissionVtbl = &vtblIEffectivePermission;
781 obj->lpISecurityObjectTypeInfoVtbl = &vtblISecurityObjectTypeInfo;
782 obj->ObjectInfo = *ObjectInfo;
783 obj->Btn = Btn;
784 obj->hRootKey = hRootKey;
785 wcscpy(obj->szRegKey,
786 lpRegKey);
787 }
788 else
789 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
790
791 return obj;
792 }
793
794 /******************************************************************************/
795 /******************************************************************************/
796 /******************************************************************************/
797
798 typedef struct _CHANGE_CONTEXT
799 {
800 HKEY hKey;
801 LPWSTR KeyString;
802 } CHANGE_CONTEXT, *PCHANGE_CONTEXT;
803
804 typedef BOOL (WINAPI *PEDITSECURITY)(HWND hwndOwner,
805 struct ISecurityInformation *psi);
806
807 static PEDITSECURITY pfnEditSecurity;
808 static HMODULE hAclUiDll;
809
810 BOOL
811 InitializeAclUiDll(VOID)
812 {
813 if (!(hAclUiDll = LoadLibraryW(L"aclui.dll")))
814 {
815 return FALSE;
816 }
817
818 if (!(pfnEditSecurity = (PEDITSECURITY)GetProcAddress(hAclUiDll,
819 "EditSecurity")))
820 {
821 FreeLibrary(hAclUiDll);
822 hAclUiDll = NULL;
823 return FALSE;
824 }
825
826 return TRUE;
827 }
828
829 VOID
830 UnloadAclUiDll(VOID)
831 {
832 if (hAclUiDll != NULL)
833 {
834 FreeLibrary(hAclUiDll);
835 }
836 }
837
838 BOOL
839 RegKeyEditPermissions(HWND hWndOwner,
840 HKEY hKey,
841 LPCWSTR lpMachine,
842 LPCWSTR lpKeyName)
843 {
844 BOOL Result = FALSE;
845 LPCWSTR lphKey = NULL;
846 LPWSTR lpKeyPath = NULL;
847 PCRegKeySecurity RegKeySecurity;
848 SI_OBJECT_INFO ObjectInfo;
849 size_t lnMachine = 0, lnKeyName = 0;
850
851 if (pfnEditSecurity == NULL)
852 {
853 return FALSE;
854 }
855
856 if (lpMachine != NULL)
857 lnMachine = wcslen(lpMachine);
858 if (lpKeyName != NULL)
859 lnKeyName = wcslen(lpKeyName);
860
861 /* build registry path */
862 if (lpMachine != NULL &&
863 (lpMachine[0] == L'\0' ||
864 (lpMachine[0] == L'.' && lpMachine[1] == L'.')))
865 {
866 lnMachine = 0;
867 }
868
869 if (hKey == HKEY_CLASSES_ROOT)
870 lphKey = L"CLASSES_ROOT";
871 else if (hKey == HKEY_CURRENT_USER)
872 lphKey = L"CURRENT_USER";
873 else if (hKey == HKEY_LOCAL_MACHINE)
874 lphKey = L"MACHINE";
875 else if (hKey == HKEY_USERS)
876 lphKey = L"USERS";
877 else if (hKey == HKEY_CURRENT_CONFIG)
878 lphKey = L"CONFIG";
879 else
880 goto Cleanup;
881
882 lpKeyPath = HeapAlloc(GetProcessHeap(),
883 0,
884 (2 + lnMachine + 1 + wcslen(lphKey) + 1 + lnKeyName) * sizeof(WCHAR));
885 if (lpKeyPath == NULL)
886 {
887 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
888 goto Cleanup;
889 }
890 lpKeyPath[0] = L'\0';
891
892 if (lnMachine != 0)
893 {
894 wcscat(lpKeyPath,
895 L"\\\\");
896 wcscat(lpKeyPath,
897 lpMachine);
898 wcscat(lpKeyPath,
899 L"\\");
900 }
901
902 wcscat(lpKeyPath,
903 lphKey);
904 if (lpKeyName != NULL && lpKeyName[0] != L'\0')
905 {
906 if (lpKeyName[0] != L'\\')
907 {
908 wcscat(lpKeyPath,
909 L"\\");
910 }
911
912 wcscat(lpKeyPath,
913 lpKeyName);
914 }
915
916 ObjectInfo.dwFlags = SI_EDIT_ALL | SI_ADVANCED | SI_CONTAINER | SI_EDIT_EFFECTIVE | SI_EDIT_PERMS |
917 SI_OWNER_RECURSE | SI_RESET_DACL_TREE | SI_RESET_SACL_TREE;
918 ObjectInfo.hInstance = hInst;
919 ObjectInfo.pszServerName = (LPWSTR)lpMachine;
920 ObjectInfo.pszObjectName = (LPWSTR)lpKeyName; /* FIXME */
921 ObjectInfo.pszPageTitle = (LPWSTR)lpKeyName; /* FIXME */
922
923 if (!(RegKeySecurity = CRegKeySecurity_fnConstructor(lpKeyPath,
924 hKey,
925 &ObjectInfo,
926 &Result)))
927 {
928 goto Cleanup;
929 }
930
931 /* display the security editor dialog */
932 pfnEditSecurity(hWndOwner,
933 impl_to_interface(RegKeySecurity,
934 ISecurityInformation));
935
936 /* dereference the interface, it should be destroyed here */
937 CRegKeySecurity_fnRelease(RegKeySecurity);
938
939 Cleanup:
940 if (lpKeyPath != NULL)
941 {
942 HeapFree(GetProcessHeap(),
943 0,
944 lpKeyPath);
945 }
946
947 return Result;
948 }
949
950 /* EOF */