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