[CMAKE]
[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, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_FULLCONTROL), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC},
340 {&GUID_NULL, KEY_READ, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_READ), SI_ACCESS_GENERAL},
341 {&GUID_NULL, KEY_QUERY_VALUE, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_QUERYVALUE), SI_ACCESS_SPECIFIC},
342 {&GUID_NULL, KEY_SET_VALUE, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_SETVALUE), SI_ACCESS_SPECIFIC},
343 {&GUID_NULL, KEY_CREATE_SUB_KEY, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_CREATESUBKEY), SI_ACCESS_SPECIFIC},
344 {&GUID_NULL, KEY_ENUMERATE_SUB_KEYS, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_ENUMERATESUBKEYS), SI_ACCESS_SPECIFIC},
345 {&GUID_NULL, KEY_NOTIFY, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_NOTIFY), SI_ACCESS_SPECIFIC},
346 {&GUID_NULL, KEY_CREATE_LINK, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_CREATELINK), SI_ACCESS_SPECIFIC},
347 {&GUID_NULL, DELETE, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_DELETE), SI_ACCESS_SPECIFIC},
348 {&GUID_NULL, WRITE_DAC, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_WRITEDAC), SI_ACCESS_SPECIFIC},
349 {&GUID_NULL, WRITE_OWNER, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_WRITEOWNER), SI_ACCESS_SPECIFIC},
350 {&GUID_NULL, READ_CONTROL, (LPWSTR)MAKEINTRESOURCE(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)MAKEINTRESOURCE(IDS_INHERIT_THISKEYONLY)},
364 {&GUID_NULL, CONTAINER_INHERIT_ACE, (LPWSTR)MAKEINTRESOURCE(IDS_INHERIT_THISKEYANDSUBKEYS)},
365 {&GUID_NULL, INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE, (LPWSTR)MAKEINTRESOURCE(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 = GetNamedSecurityInfo(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 = sizeof(RegAccess) / sizeof(RegAccess[0]);
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 = sizeof(RegInheritTypes) / sizeof(RegInheritTypes[0]);
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 LPTSTR 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 = GetInheritanceSource(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 += (_tcslen(pif[i].AncestorName) + 1) * sizeof(TCHAR);
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 = (LPTSTR)((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 _tcscpy(lpBuf,
735 pif[i].AncestorName);
736 lpBuf += _tcslen(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(LPTSTR 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[_tcslen(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 _tcscpy(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 LPTSTR 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 = LoadLibrary(_T("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 LPCTSTR lpMachine,
842 LPCTSTR lpKeyName)
843 {
844 BOOL Result = FALSE;
845 LPWSTR Machine = NULL, KeyName = NULL;
846 LPCTSTR lphKey = NULL;
847 LPTSTR lpKeyPath = NULL;
848 PCRegKeySecurity RegKeySecurity;
849 SI_OBJECT_INFO ObjectInfo;
850 size_t lnMachine = 0, lnKeyName = 0;
851
852 if (pfnEditSecurity == NULL)
853 {
854 return FALSE;
855 }
856
857 #ifndef UNICODE
858 /* aclui.dll only accepts unicode strings, convert them */
859 if (lpMachine != NULL)
860 {
861 lnMachine = lstrlen(lpMachine);
862 if (!(Machine = HeapAlloc(GetProcessHeap(),
863 0,
864 (lnMachine + 1) * sizeof(WCHAR))))
865 {
866 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
867 goto Cleanup;
868 }
869
870 if (lnMachine > 0)
871 {
872 MultiByteToWideChar(CP_ACP,
873 0,
874 lpMachine,
875 -1,
876 Machine,
877 lnMachine + 1);
878 }
879 else
880 *Machine = L'\0';
881 }
882 else
883 Machine = NULL;
884
885 if (lpKeyName != NULL)
886 {
887 lnKeyName = lstrlen(lpKeyName);
888 if (!(KeyName = HeapAlloc(GetProcessHeap(),
889 0,
890 (lnKeyName + 1) * sizeof(WCHAR))))
891 {
892 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
893 goto Cleanup;
894 }
895
896 if (lnKeyName > 0)
897 {
898 MultiByteToWideChar(CP_ACP,
899 0,
900 lpKeyName,
901 -1,
902 KeyName,
903 lnKeyName + 1);
904 }
905 else
906 *KeyName = L'\0';
907 }
908 else
909 KeyName = NULL;
910 #else
911 Machine = (LPWSTR)lpMachine;
912 KeyName = (LPWSTR)lpKeyName;
913
914 if (Machine != NULL)
915 lnMachine = wcslen(lpMachine);
916 if (KeyName != NULL)
917 lnKeyName = wcslen(KeyName);
918 #endif
919
920 /* build registry path */
921 if (lpMachine != NULL &&
922 (lpMachine[0] == _T('\0') ||
923 (lpMachine[0] == _T('.') && lpMachine[1] == _T('.'))))
924 {
925 lnMachine = 0;
926 }
927
928 if (hKey == HKEY_CLASSES_ROOT)
929 lphKey = TEXT("CLASSES_ROOT");
930 else if (hKey == HKEY_CURRENT_USER)
931 lphKey = TEXT("CURRENT_USER");
932 else if (hKey == HKEY_LOCAL_MACHINE)
933 lphKey = TEXT("MACHINE");
934 else if (hKey == HKEY_USERS)
935 lphKey = TEXT("USERS");
936 else if (hKey == HKEY_CURRENT_CONFIG)
937 lphKey = TEXT("CONFIG");
938 else
939 goto Cleanup;
940
941 lpKeyPath = HeapAlloc(GetProcessHeap(),
942 0,
943 (2 + lnMachine + 1 + _tcslen(lphKey) + 1 + lnKeyName) * sizeof(TCHAR));
944 if (lpKeyPath == NULL)
945 {
946 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
947 goto Cleanup;
948 }
949 lpKeyPath[0] = _T('\0');
950
951 if (lnMachine != 0)
952 {
953 _tcscat(lpKeyPath,
954 _T("\\\\"));
955 _tcscat(lpKeyPath,
956 lpMachine);
957 _tcscat(lpKeyPath,
958 _T("\\"));
959 }
960
961 _tcscat(lpKeyPath,
962 lphKey);
963 if (lpKeyName != NULL && lpKeyName[0] != _T('\0'))
964 {
965 if (lpKeyName[0] != _T('\\'))
966 {
967 _tcscat(lpKeyPath,
968 _T("\\"));
969 }
970
971 _tcscat(lpKeyPath,
972 lpKeyName);
973 }
974
975 ObjectInfo.dwFlags = SI_EDIT_ALL | SI_ADVANCED | SI_CONTAINER | SI_EDIT_EFFECTIVE | SI_EDIT_PERMS |
976 SI_OWNER_RECURSE | SI_RESET_DACL_TREE | SI_RESET_SACL_TREE;
977 ObjectInfo.hInstance = hInst;
978 ObjectInfo.pszServerName = Machine;
979 ObjectInfo.pszObjectName = KeyName; /* FIXME */
980 ObjectInfo.pszPageTitle = KeyName; /* FIXME */
981
982 if (!(RegKeySecurity = CRegKeySecurity_fnConstructor(lpKeyPath,
983 hKey,
984 &ObjectInfo,
985 &Result)))
986 {
987 goto Cleanup;
988 }
989
990 /* display the security editor dialog */
991 pfnEditSecurity(hWndOwner,
992 impl_to_interface(RegKeySecurity,
993 ISecurityInformation));
994
995 /* dereference the interface, it should be destroyed here */
996 CRegKeySecurity_fnRelease(RegKeySecurity);
997
998 Cleanup:
999 #ifndef UNICODE
1000 if (Machine != NULL)
1001 {
1002 HeapFree(GetProcessHeap(),
1003 0,
1004 Machine);
1005 }
1006
1007 if (KeyName != NULL)
1008 {
1009 HeapFree(GetProcessHeap(),
1010 0,
1011 KeyName);
1012 }
1013 #endif
1014
1015 if (lpKeyPath != NULL)
1016 {
1017 HeapFree(GetProcessHeap(),
1018 0,
1019 lpKeyPath);
1020 }
1021
1022 return Result;
1023 }
1024
1025 /* EOF */