062fe7674da15d25e5f0dd91f9d4d0c79e9ea13a
[reactos.git] / reactos / dll / win32 / ntmarta / ntmarta.c
1 /*
2 * ReactOS MARTA provider
3 * Copyright (C) 2005 - 2006 ReactOS Team
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 /*
20 * PROJECT: ReactOS MARTA provider
21 * FILE: lib/ntmarta/ntmarta.c
22 * PURPOSE: ReactOS MARTA provider
23 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
24 *
25 * UPDATE HISTORY:
26 * 07/26/2005 Created
27 */
28
29 #include "ntmarta.h"
30
31 #define NDEBUG
32 #include <debug.h>
33
34 HINSTANCE hDllInstance;
35
36 /* FIXME: Vista+ API */
37 VOID
38 WINAPI
39 SetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
40 OUT LPDWORD DesiredAccess)
41 {
42 *DesiredAccess = 0;
43
44 if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
45 *DesiredAccess |= WRITE_OWNER;
46
47 if (SecurityInformation & DACL_SECURITY_INFORMATION)
48 *DesiredAccess |= WRITE_DAC;
49
50 if (SecurityInformation & SACL_SECURITY_INFORMATION)
51 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
52 }
53
54 /* FIXME: Vista+ API */
55 VOID
56 WINAPI
57 QuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
58 OUT LPDWORD DesiredAccess)
59 {
60 *DesiredAccess = 0;
61
62 if (SecurityInformation & (OWNER_SECURITY_INFORMATION |
63 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION))
64 {
65 *DesiredAccess |= READ_CONTROL;
66 }
67
68 if (SecurityInformation & SACL_SECURITY_INFORMATION)
69 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
70 }
71
72 static ACCESS_MODE
73 AccpGetAceAccessMode(IN PACE_HEADER AceHeader)
74 {
75 ACCESS_MODE Mode = NOT_USED_ACCESS;
76
77 switch (AceHeader->AceType)
78 {
79 case ACCESS_ALLOWED_ACE_TYPE:
80 case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
81 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
82 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
83 Mode = GRANT_ACCESS;
84 break;
85
86 case ACCESS_DENIED_ACE_TYPE:
87 case ACCESS_DENIED_CALLBACK_ACE_TYPE:
88 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
89 case ACCESS_DENIED_OBJECT_ACE_TYPE:
90 Mode = DENY_ACCESS;
91 break;
92
93 case SYSTEM_AUDIT_ACE_TYPE:
94 case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
95 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
96 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
97 if (AceHeader->AceFlags & FAILED_ACCESS_ACE_FLAG)
98 Mode = SET_AUDIT_FAILURE;
99 else if (AceHeader->AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
100 Mode = SET_AUDIT_SUCCESS;
101 break;
102 }
103
104 return Mode;
105 }
106
107 static UINT
108 AccpGetAceStructureSize(IN PACE_HEADER AceHeader)
109 {
110 UINT Size = 0;
111
112 switch (AceHeader->AceType)
113 {
114 case ACCESS_ALLOWED_ACE_TYPE:
115 case ACCESS_DENIED_ACE_TYPE:
116 Size = FIELD_OFFSET(ACCESS_ALLOWED_ACE,
117 SidStart);
118 break;
119 case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
120 case ACCESS_DENIED_CALLBACK_ACE_TYPE:
121 Size = FIELD_OFFSET(ACCESS_ALLOWED_CALLBACK_ACE,
122 SidStart);
123 break;
124 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
125 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
126 {
127 PACCESS_ALLOWED_CALLBACK_OBJECT_ACE Ace = (PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader;
128 Size = FIELD_OFFSET(ACCESS_ALLOWED_CALLBACK_OBJECT_ACE,
129 ObjectType);
130 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
131 Size += sizeof(Ace->ObjectType);
132 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
133 Size += sizeof(Ace->InheritedObjectType);
134 break;
135 }
136 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
137 case ACCESS_DENIED_OBJECT_ACE_TYPE:
138 {
139 PACCESS_ALLOWED_OBJECT_ACE Ace = (PACCESS_ALLOWED_OBJECT_ACE)AceHeader;
140 Size = FIELD_OFFSET(ACCESS_ALLOWED_OBJECT_ACE,
141 ObjectType);
142 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
143 Size += sizeof(Ace->ObjectType);
144 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
145 Size += sizeof(Ace->InheritedObjectType);
146 break;
147 }
148
149 case SYSTEM_AUDIT_ACE_TYPE:
150 Size = FIELD_OFFSET(SYSTEM_AUDIT_ACE,
151 SidStart);
152 break;
153 case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
154 Size = FIELD_OFFSET(SYSTEM_AUDIT_CALLBACK_ACE,
155 SidStart);
156 break;
157 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
158 {
159 PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE Ace = (PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE)AceHeader;
160 Size = FIELD_OFFSET(SYSTEM_AUDIT_CALLBACK_OBJECT_ACE,
161 ObjectType);
162 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
163 Size += sizeof(Ace->ObjectType);
164 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
165 Size += sizeof(Ace->InheritedObjectType);
166 break;
167 }
168 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
169 {
170 PSYSTEM_AUDIT_OBJECT_ACE Ace = (PSYSTEM_AUDIT_OBJECT_ACE)AceHeader;
171 Size = FIELD_OFFSET(SYSTEM_AUDIT_OBJECT_ACE,
172 ObjectType);
173 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
174 Size += sizeof(Ace->ObjectType);
175 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
176 Size += sizeof(Ace->InheritedObjectType);
177 break;
178 }
179
180 case SYSTEM_MANDATORY_LABEL_ACE_TYPE:
181 Size = FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE,
182 SidStart);
183 break;
184 }
185
186 return Size;
187 }
188
189 static PSID
190 AccpGetAceSid(IN PACE_HEADER AceHeader)
191 {
192 return (PSID)((ULONG_PTR)AceHeader + AccpGetAceStructureSize(AceHeader));
193 }
194
195 static ACCESS_MASK
196 AccpGetAceAccessMask(IN PACE_HEADER AceHeader)
197 {
198 return *((PACCESS_MASK)(AceHeader + 1));
199 }
200
201 static BOOL
202 AccpIsObjectAce(IN PACE_HEADER AceHeader)
203 {
204 BOOL Ret;
205
206 switch (AceHeader->AceType)
207 {
208 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
209 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
210 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
211 case ACCESS_DENIED_OBJECT_ACE_TYPE:
212 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
213 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
214 Ret = TRUE;
215 break;
216
217 default:
218 Ret = FALSE;
219 break;
220 }
221
222 return Ret;
223 }
224
225 static DWORD
226 AccpGetTrusteeObjects(IN PTRUSTEE_W Trustee,
227 OUT GUID *pObjectTypeGuid OPTIONAL,
228 OUT GUID *pInheritedObjectTypeGuid OPTIONAL)
229 {
230 DWORD Ret;
231
232 switch (Trustee->TrusteeForm)
233 {
234 case TRUSTEE_IS_OBJECTS_AND_NAME:
235 {
236 POBJECTS_AND_NAME_W pOan = (POBJECTS_AND_NAME_W)Trustee->ptstrName;
237
238 /* pOan->ObjectsPresent should always be 0 here because a previous
239 call to AccpGetTrusteeSid should have rejected these trustees
240 already. */
241 ASSERT(pOan->ObjectsPresent == 0);
242
243 Ret = pOan->ObjectsPresent;
244 break;
245 }
246
247 case TRUSTEE_IS_OBJECTS_AND_SID:
248 {
249 POBJECTS_AND_SID pOas = (POBJECTS_AND_SID)Trustee->ptstrName;
250
251 if (pObjectTypeGuid != NULL && pOas->ObjectsPresent & ACE_OBJECT_TYPE_PRESENT)
252 *pObjectTypeGuid = pOas->ObjectTypeGuid;
253
254 if (pInheritedObjectTypeGuid != NULL && pOas->ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT)
255 *pInheritedObjectTypeGuid = pOas->InheritedObjectTypeGuid;
256
257 Ret = pOas->ObjectsPresent;
258 break;
259 }
260
261 default:
262 /* Any other trustee forms have no objects attached... */
263 Ret = 0;
264 break;
265 }
266
267 return Ret;
268 }
269
270 static DWORD
271 AccpCalcNeededAceSize(IN PSID Sid,
272 IN DWORD ObjectsPresent)
273 {
274 DWORD Ret;
275
276 Ret = sizeof(ACE) + GetLengthSid(Sid);
277
278 /* This routine calculates the generic size of the ACE needed.
279 If no objects are present it is assumed that only a standard
280 ACE is to be created. */
281
282 if (ObjectsPresent & ACE_OBJECT_TYPE_PRESENT)
283 Ret += sizeof(GUID);
284 if (ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT)
285 Ret += sizeof(GUID);
286
287 if (ObjectsPresent != 0)
288 Ret += sizeof(DWORD); /* Include the Flags member to make it an object ACE */
289
290 return Ret;
291 }
292
293 static GUID*
294 AccpGetObjectAceObjectType(IN PACE_HEADER AceHeader)
295 {
296 GUID *ObjectType = NULL;
297
298 switch (AceHeader->AceType)
299 {
300 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
301 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
302 {
303 PACCESS_ALLOWED_CALLBACK_OBJECT_ACE Ace = (PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader;
304 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
305 ObjectType = &Ace->ObjectType;
306 break;
307 }
308 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
309 case ACCESS_DENIED_OBJECT_ACE_TYPE:
310 {
311 PACCESS_ALLOWED_OBJECT_ACE Ace = (PACCESS_ALLOWED_OBJECT_ACE)AceHeader;
312 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
313 ObjectType = &Ace->ObjectType;
314 break;
315 }
316
317 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
318 {
319 PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE Ace = (PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE)AceHeader;
320 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
321 ObjectType = &Ace->ObjectType;
322 break;
323 }
324 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
325 {
326 PSYSTEM_AUDIT_OBJECT_ACE Ace = (PSYSTEM_AUDIT_OBJECT_ACE)AceHeader;
327 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
328 ObjectType = &Ace->ObjectType;
329 break;
330 }
331 }
332
333 return ObjectType;
334 }
335
336 static GUID*
337 AccpGetObjectAceInheritedObjectType(IN PACE_HEADER AceHeader)
338 {
339 GUID *ObjectType = NULL;
340
341 switch (AceHeader->AceType)
342 {
343 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
344 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
345 {
346 PACCESS_ALLOWED_CALLBACK_OBJECT_ACE Ace = (PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader;
347 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
348 {
349 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
350 ObjectType = &Ace->InheritedObjectType;
351 else
352 ObjectType = &Ace->ObjectType;
353 }
354 break;
355 }
356 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
357 case ACCESS_DENIED_OBJECT_ACE_TYPE:
358 {
359 PACCESS_ALLOWED_OBJECT_ACE Ace = (PACCESS_ALLOWED_OBJECT_ACE)AceHeader;
360 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
361 {
362 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
363 ObjectType = &Ace->InheritedObjectType;
364 else
365 ObjectType = &Ace->ObjectType;
366 }
367 break;
368 }
369
370 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
371 {
372 PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE Ace = (PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE)AceHeader;
373 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
374 {
375 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
376 ObjectType = &Ace->InheritedObjectType;
377 else
378 ObjectType = &Ace->ObjectType;
379 }
380 break;
381 }
382 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
383 {
384 PSYSTEM_AUDIT_OBJECT_ACE Ace = (PSYSTEM_AUDIT_OBJECT_ACE)AceHeader;
385 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
386 {
387 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
388 ObjectType = &Ace->InheritedObjectType;
389 else
390 ObjectType = &Ace->ObjectType;
391 }
392 break;
393 }
394 }
395
396 return ObjectType;
397 }
398
399 static DWORD
400 AccpOpenLSAPolicyHandle(IN LPWSTR SystemName,
401 IN ACCESS_MASK DesiredAccess,
402 OUT PLSA_HANDLE pPolicyHandle)
403 {
404 LSA_OBJECT_ATTRIBUTES LsaObjectAttributes = {0};
405 LSA_UNICODE_STRING LsaSystemName, *psn;
406 NTSTATUS Status;
407
408 if (SystemName != NULL && SystemName[0] != L'\0')
409 {
410 LsaSystemName.Buffer = SystemName;
411 LsaSystemName.Length = wcslen(SystemName) * sizeof(WCHAR);
412 LsaSystemName.MaximumLength = LsaSystemName.Length + sizeof(WCHAR);
413 psn = &LsaSystemName;
414 }
415 else
416 {
417 psn = NULL;
418 }
419
420 Status = LsaOpenPolicy(psn,
421 &LsaObjectAttributes,
422 DesiredAccess,
423 pPolicyHandle);
424 if (!NT_SUCCESS(Status))
425 return LsaNtStatusToWinError(Status);
426
427 return ERROR_SUCCESS;
428 }
429
430 static LPWSTR
431 AccpGetTrusteeName(IN PTRUSTEE_W Trustee)
432 {
433 switch (Trustee->TrusteeForm)
434 {
435 case TRUSTEE_IS_NAME:
436 return Trustee->ptstrName;
437
438 case TRUSTEE_IS_OBJECTS_AND_NAME:
439 return ((POBJECTS_AND_NAME_W)Trustee->ptstrName)->ptstrName;
440
441 default:
442 return NULL;
443 }
444 }
445
446 static DWORD
447 AccpLookupSidByName(IN LSA_HANDLE PolicyHandle,
448 IN LPWSTR Name,
449 OUT PSID *pSid)
450 {
451 NTSTATUS Status;
452 LSA_UNICODE_STRING LsaNames[1];
453 PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains = NULL;
454 PLSA_TRANSLATED_SID2 TranslatedSid = NULL;
455 DWORD SidLen;
456 DWORD Ret = ERROR_SUCCESS;
457
458 LsaNames[0].Buffer = Name;
459 LsaNames[0].Length = wcslen(Name) * sizeof(WCHAR);
460 LsaNames[0].MaximumLength = LsaNames[0].Length + sizeof(WCHAR);
461
462 Status = LsaLookupNames2(PolicyHandle,
463 0,
464 sizeof(LsaNames) / sizeof(LsaNames[0]),
465 LsaNames,
466 &ReferencedDomains,
467 &TranslatedSid);
468
469 if (!NT_SUCCESS(Status))
470 return LsaNtStatusToWinError(Status);
471
472 if (TranslatedSid->Use == SidTypeUnknown || TranslatedSid->Use == SidTypeInvalid)
473 {
474 Ret = LsaNtStatusToWinError(STATUS_NONE_MAPPED); /* FIXME- what error code? */
475 goto Cleanup;
476 }
477
478 SidLen = GetLengthSid(TranslatedSid->Sid);
479 ASSERT(SidLen != 0);
480
481 *pSid = LocalAlloc(LMEM_FIXED, (SIZE_T)SidLen);
482 if (*pSid != NULL)
483 {
484 if (!CopySid(SidLen,
485 *pSid,
486 TranslatedSid->Sid))
487 {
488 Ret = GetLastError();
489
490 LocalFree((HLOCAL)*pSid);
491 *pSid = NULL;
492 }
493 }
494 else
495 Ret = ERROR_NOT_ENOUGH_MEMORY;
496
497 Cleanup:
498 LsaFreeMemory(ReferencedDomains);
499 LsaFreeMemory(TranslatedSid);
500
501 return Ret;
502 }
503
504
505 static DWORD
506 AccpGetTrusteeSid(IN PTRUSTEE_W Trustee,
507 IN OUT PLSA_HANDLE pPolicyHandle,
508 OUT PSID *ppSid,
509 OUT BOOL *Allocated)
510 {
511 DWORD Ret = ERROR_SUCCESS;
512
513 *ppSid = NULL;
514 *Allocated = FALSE;
515
516 if (Trustee->pMultipleTrustee || Trustee->MultipleTrusteeOperation != NO_MULTIPLE_TRUSTEE)
517 {
518 /* This is currently not supported */
519 return ERROR_INVALID_PARAMETER;
520 }
521
522 switch (Trustee->TrusteeForm)
523 {
524 case TRUSTEE_IS_OBJECTS_AND_NAME:
525 if (((POBJECTS_AND_NAME_W)Trustee->ptstrName)->ObjectsPresent != 0)
526 {
527 /* This is not supported as there is no way to interpret the
528 strings provided, and we need GUIDs for the ACEs... */
529 Ret = ERROR_INVALID_PARAMETER;
530 break;
531 }
532 /* fall through */
533
534 case TRUSTEE_IS_NAME:
535 if (*pPolicyHandle == NULL)
536 {
537 Ret = AccpOpenLSAPolicyHandle(NULL, /* FIXME - always local? */
538 POLICY_LOOKUP_NAMES,
539 pPolicyHandle);
540 if (Ret != ERROR_SUCCESS)
541 return Ret;
542
543 ASSERT(*pPolicyHandle != NULL);
544 }
545
546 Ret = AccpLookupSidByName(*pPolicyHandle,
547 AccpGetTrusteeName(Trustee),
548 ppSid);
549 if (Ret == ERROR_SUCCESS)
550 {
551 ASSERT(*ppSid != NULL);
552 *Allocated = TRUE;
553 }
554 break;
555
556 case TRUSTEE_IS_OBJECTS_AND_SID:
557 *ppSid = ((POBJECTS_AND_SID)Trustee->ptstrName)->pSid;
558 break;
559
560 case TRUSTEE_IS_SID:
561 *ppSid = (PSID)Trustee->ptstrName;
562 break;
563
564 default:
565 Ret = ERROR_INVALID_PARAMETER;
566 break;
567 }
568
569 return Ret;
570 }
571
572
573 /**********************************************************************
574 * AccRewriteGetHandleRights EXPORTED
575 *
576 * @unimplemented
577 */
578 DWORD WINAPI
579 AccRewriteGetHandleRights(HANDLE handle,
580 SE_OBJECT_TYPE ObjectType,
581 SECURITY_INFORMATION SecurityInfo,
582 PSID* ppsidOwner,
583 PSID* ppsidGroup,
584 PACL* ppDacl,
585 PACL* ppSacl,
586 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
587 {
588 PSECURITY_DESCRIPTOR pSD = NULL;
589 ULONG SDSize = 0;
590 NTSTATUS Status;
591 DWORD LastErr;
592 DWORD Ret;
593
594 /* save the last error code */
595 LastErr = GetLastError();
596
597 do
598 {
599 Ret = ERROR_SUCCESS;
600
601 /* allocate a buffer large enough to hold the
602 security descriptor we need to return */
603 SDSize += 0x100;
604 if (pSD == NULL)
605 {
606 pSD = LocalAlloc(LMEM_FIXED,
607 (SIZE_T)SDSize);
608 }
609 else
610 {
611 PSECURITY_DESCRIPTOR newSD;
612
613 newSD = LocalReAlloc((HLOCAL)pSD,
614 (SIZE_T)SDSize,
615 LMEM_MOVEABLE);
616 if (newSD != NULL)
617 pSD = newSD;
618 }
619
620 if (pSD == NULL)
621 {
622 Ret = GetLastError();
623 break;
624 }
625
626 /* perform the actual query depending on the object type */
627 switch (ObjectType)
628 {
629 case SE_REGISTRY_KEY:
630 {
631 Ret = (DWORD)RegGetKeySecurity((HKEY)handle,
632 SecurityInfo,
633 pSD,
634 &SDSize);
635 break;
636 }
637
638 case SE_FILE_OBJECT:
639 /* FIXME - handle console handles? */
640 case SE_KERNEL_OBJECT:
641 {
642 Status = NtQuerySecurityObject(handle,
643 SecurityInfo,
644 pSD,
645 SDSize,
646 &SDSize);
647 if (!NT_SUCCESS(Status))
648 {
649 Ret = RtlNtStatusToDosError(Status);
650 }
651 break;
652 }
653
654 case SE_SERVICE:
655 {
656 if (!QueryServiceObjectSecurity((SC_HANDLE)handle,
657 SecurityInfo,
658 pSD,
659 SDSize,
660 &SDSize))
661 {
662 Ret = GetLastError();
663 }
664 break;
665 }
666
667 case SE_WINDOW_OBJECT:
668 {
669 if (!GetUserObjectSecurity(handle,
670 &SecurityInfo,
671 pSD,
672 SDSize,
673 &SDSize))
674 {
675 Ret = GetLastError();
676 }
677 break;
678 }
679
680 default:
681 {
682 UNIMPLEMENTED;
683 Ret = ERROR_CALL_NOT_IMPLEMENTED;
684 break;
685 }
686 }
687
688 } while (Ret == ERROR_INSUFFICIENT_BUFFER);
689
690 if (Ret == ERROR_SUCCESS)
691 {
692 BOOL Present, Defaulted;
693
694 if (SecurityInfo & OWNER_SECURITY_INFORMATION && ppsidOwner != NULL)
695 {
696 *ppsidOwner = NULL;
697 if (!GetSecurityDescriptorOwner(pSD,
698 ppsidOwner,
699 &Defaulted))
700 {
701 Ret = GetLastError();
702 goto Cleanup;
703 }
704 }
705
706 if (SecurityInfo & GROUP_SECURITY_INFORMATION && ppsidGroup != NULL)
707 {
708 *ppsidGroup = NULL;
709 if (!GetSecurityDescriptorGroup(pSD,
710 ppsidGroup,
711 &Defaulted))
712 {
713 Ret = GetLastError();
714 goto Cleanup;
715 }
716 }
717
718 if (SecurityInfo & DACL_SECURITY_INFORMATION && ppDacl != NULL)
719 {
720 *ppDacl = NULL;
721 if (!GetSecurityDescriptorDacl(pSD,
722 &Present,
723 ppDacl,
724 &Defaulted))
725 {
726 Ret = GetLastError();
727 goto Cleanup;
728 }
729 }
730
731 if (SecurityInfo & SACL_SECURITY_INFORMATION && ppSacl != NULL)
732 {
733 *ppSacl = NULL;
734 if (!GetSecurityDescriptorSacl(pSD,
735 &Present,
736 ppSacl,
737 &Defaulted))
738 {
739 Ret = GetLastError();
740 goto Cleanup;
741 }
742 }
743
744 *ppSecurityDescriptor = pSD;
745 }
746 else
747 {
748 Cleanup:
749 if (pSD != NULL)
750 {
751 LocalFree((HLOCAL)pSD);
752 }
753 }
754
755 /* restore the last error code */
756 SetLastError(LastErr);
757
758 return Ret;
759 }
760
761
762 /**********************************************************************
763 * AccRewriteSetHandleRights EXPORTED
764 *
765 * @unimplemented
766 */
767 DWORD WINAPI
768 AccRewriteSetHandleRights(HANDLE handle,
769 SE_OBJECT_TYPE ObjectType,
770 SECURITY_INFORMATION SecurityInfo,
771 PSECURITY_DESCRIPTOR pSecurityDescriptor)
772 {
773 NTSTATUS Status;
774 DWORD LastErr;
775 DWORD Ret = ERROR_SUCCESS;
776
777 /* save the last error code */
778 LastErr = GetLastError();
779
780 /* set the security according to the object type */
781 switch (ObjectType)
782 {
783 case SE_REGISTRY_KEY:
784 {
785 Ret = (DWORD)RegSetKeySecurity((HKEY)handle,
786 SecurityInfo,
787 pSecurityDescriptor);
788 break;
789 }
790
791 case SE_FILE_OBJECT:
792 /* FIXME - handle console handles? */
793 case SE_KERNEL_OBJECT:
794 {
795 Status = NtSetSecurityObject(handle,
796 SecurityInfo,
797 pSecurityDescriptor);
798 if (!NT_SUCCESS(Status))
799 {
800 Ret = RtlNtStatusToDosError(Status);
801 }
802 break;
803 }
804
805 case SE_SERVICE:
806 {
807 if (!SetServiceObjectSecurity((SC_HANDLE)handle,
808 SecurityInfo,
809 pSecurityDescriptor))
810 {
811 Ret = GetLastError();
812 }
813 break;
814 }
815
816 case SE_WINDOW_OBJECT:
817 {
818 if (!SetUserObjectSecurity(handle,
819 &SecurityInfo,
820 pSecurityDescriptor))
821 {
822 Ret = GetLastError();
823 }
824 break;
825 }
826
827 default:
828 {
829 UNIMPLEMENTED;
830 Ret = ERROR_CALL_NOT_IMPLEMENTED;
831 break;
832 }
833 }
834
835
836 /* restore the last error code */
837 SetLastError(LastErr);
838
839 return Ret;
840 }
841
842
843 static DWORD
844 AccpOpenNamedObject(LPWSTR pObjectName,
845 SE_OBJECT_TYPE ObjectType,
846 SECURITY_INFORMATION SecurityInfo,
847 PHANDLE Handle,
848 PHANDLE Handle2,
849 BOOL Write)
850 {
851 LPWSTR lpPath;
852 NTSTATUS Status;
853 ACCESS_MASK DesiredAccess = (ACCESS_MASK)0;
854 DWORD Ret = ERROR_SUCCESS;
855
856 /* determine the required access rights */
857 switch (ObjectType)
858 {
859 case SE_REGISTRY_KEY:
860 case SE_FILE_OBJECT:
861 case SE_KERNEL_OBJECT:
862 case SE_SERVICE:
863 case SE_WINDOW_OBJECT:
864 if (Write)
865 {
866 SetSecurityAccessMask(SecurityInfo,
867 (PDWORD)&DesiredAccess);
868 }
869 else
870 {
871 QuerySecurityAccessMask(SecurityInfo,
872 (PDWORD)&DesiredAccess);
873 }
874 break;
875
876 default:
877 break;
878 }
879
880 /* make a copy of the path if we're modifying the string */
881 switch (ObjectType)
882 {
883 case SE_REGISTRY_KEY:
884 case SE_SERVICE:
885 lpPath = (LPWSTR)LocalAlloc(LMEM_FIXED,
886 (wcslen(pObjectName) + 1) * sizeof(WCHAR));
887 if (lpPath == NULL)
888 {
889 Ret = GetLastError();
890 goto Cleanup;
891 }
892
893 wcscpy(lpPath,
894 pObjectName);
895 break;
896
897 default:
898 lpPath = pObjectName;
899 break;
900 }
901
902 /* open a handle to the path depending on the object type */
903 switch (ObjectType)
904 {
905 case SE_FILE_OBJECT:
906 {
907 IO_STATUS_BLOCK IoStatusBlock;
908 OBJECT_ATTRIBUTES ObjectAttributes;
909 UNICODE_STRING FileName;
910
911 if (!RtlDosPathNameToNtPathName_U(pObjectName,
912 &FileName,
913 NULL,
914 NULL))
915 {
916 Ret = ERROR_INVALID_NAME;
917 goto Cleanup;
918 }
919
920 InitializeObjectAttributes(&ObjectAttributes,
921 &FileName,
922 OBJ_CASE_INSENSITIVE,
923 NULL,
924 NULL);
925
926 Status = NtOpenFile(Handle,
927 DesiredAccess | SYNCHRONIZE,
928 &ObjectAttributes,
929 &IoStatusBlock,
930 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
931 FILE_SYNCHRONOUS_IO_NONALERT);
932
933 RtlFreeHeap(RtlGetProcessHeap(),
934 0,
935 FileName.Buffer);
936
937 if (!NT_SUCCESS(Status))
938 {
939 Ret = RtlNtStatusToDosError(Status);
940 }
941 break;
942 }
943
944 case SE_REGISTRY_KEY:
945 {
946 static const struct
947 {
948 HKEY hRootKey;
949 LPCWSTR szRootKey;
950 } AccRegRootKeys[] =
951 {
952 {HKEY_CLASSES_ROOT, L"CLASSES_ROOT"},
953 {HKEY_CURRENT_USER, L"CURRENT_USER"},
954 {HKEY_LOCAL_MACHINE, L"MACHINE"},
955 {HKEY_USERS, L"USERS"},
956 {HKEY_CURRENT_CONFIG, L"CONFIG"},
957 };
958 LPWSTR lpMachineName, lpRootKeyName, lpKeyName;
959 HKEY hRootKey = NULL;
960 UINT i;
961
962 /* parse the registry path */
963 if (lpPath[0] == L'\\' && lpPath[1] == L'\\')
964 {
965 lpMachineName = lpPath;
966
967 lpRootKeyName = wcschr(lpPath + 2,
968 L'\\');
969 if (lpRootKeyName == NULL)
970 goto ParseRegErr;
971 else
972 *(lpRootKeyName++) = L'\0';
973 }
974 else
975 {
976 lpMachineName = NULL;
977 lpRootKeyName = lpPath;
978 }
979
980 lpKeyName = wcschr(lpRootKeyName,
981 L'\\');
982 if (lpKeyName != NULL)
983 {
984 *(lpKeyName++) = L'\0';
985 }
986
987 for (i = 0;
988 i != sizeof(AccRegRootKeys) / sizeof(AccRegRootKeys[0]);
989 i++)
990 {
991 if (!wcsicmp(lpRootKeyName,
992 AccRegRootKeys[i].szRootKey))
993 {
994 hRootKey = AccRegRootKeys[i].hRootKey;
995 break;
996 }
997 }
998
999 if (hRootKey == NULL)
1000 {
1001 ParseRegErr:
1002 /* FIXME - right error code? */
1003 Ret = ERROR_INVALID_PARAMETER;
1004 goto Cleanup;
1005 }
1006
1007 /* open the registry key */
1008 if (lpMachineName != NULL)
1009 {
1010 Ret = RegConnectRegistry(lpMachineName,
1011 hRootKey,
1012 (PHKEY)Handle2);
1013
1014 if (Ret != ERROR_SUCCESS)
1015 goto Cleanup;
1016
1017 hRootKey = (HKEY)(*Handle2);
1018 }
1019
1020 Ret = RegOpenKeyEx(hRootKey,
1021 lpKeyName,
1022 0,
1023 (REGSAM)DesiredAccess,
1024 (PHKEY)Handle);
1025 if (Ret != ERROR_SUCCESS)
1026 {
1027 if (*Handle2 != NULL)
1028 {
1029 RegCloseKey((HKEY)(*Handle2));
1030 }
1031
1032 goto Cleanup;
1033 }
1034 break;
1035 }
1036
1037 case SE_SERVICE:
1038 {
1039 LPWSTR lpServiceName, lpMachineName;
1040
1041 /* parse the service path */
1042 if (lpPath[0] == L'\\' && lpPath[1] == L'\\')
1043 {
1044 DesiredAccess |= SC_MANAGER_CONNECT;
1045
1046 lpMachineName = lpPath;
1047
1048 lpServiceName = wcschr(lpPath + 2,
1049 L'\\');
1050 if (lpServiceName == NULL)
1051 {
1052 /* FIXME - right error code? */
1053 Ret = ERROR_INVALID_PARAMETER;
1054 goto Cleanup;
1055 }
1056 else
1057 *(lpServiceName++) = L'\0';
1058 }
1059 else
1060 {
1061 lpMachineName = NULL;
1062 lpServiceName = lpPath;
1063 }
1064
1065 /* open the service */
1066 *Handle2 = (HANDLE)OpenSCManager(lpMachineName,
1067 NULL,
1068 (DWORD)DesiredAccess);
1069 if (*Handle2 == NULL)
1070 {
1071 Ret = GetLastError();
1072 ASSERT(Ret != ERROR_SUCCESS);
1073 goto Cleanup;
1074 }
1075
1076 DesiredAccess &= ~SC_MANAGER_CONNECT;
1077 *Handle = (HANDLE)OpenService((SC_HANDLE)(*Handle2),
1078 lpServiceName,
1079 (DWORD)DesiredAccess);
1080 if (*Handle == NULL)
1081 {
1082 Ret = GetLastError();
1083 ASSERT(Ret != ERROR_SUCCESS);
1084 ASSERT(*Handle2 != NULL);
1085 CloseServiceHandle((SC_HANDLE)(*Handle2));
1086
1087 goto Cleanup;
1088 }
1089 break;
1090 }
1091
1092 default:
1093 {
1094 UNIMPLEMENTED;
1095 Ret = ERROR_CALL_NOT_IMPLEMENTED;
1096 break;
1097 }
1098 }
1099
1100 Cleanup:
1101 if (lpPath != NULL && lpPath != pObjectName)
1102 {
1103 LocalFree((HLOCAL)lpPath);
1104 }
1105
1106 return Ret;
1107 }
1108
1109
1110 static VOID
1111 AccpCloseObjectHandle(SE_OBJECT_TYPE ObjectType,
1112 HANDLE Handle,
1113 HANDLE Handle2)
1114 {
1115 ASSERT(Handle != NULL);
1116
1117 /* close allocated handlees depending on the object type */
1118 switch (ObjectType)
1119 {
1120 case SE_REGISTRY_KEY:
1121 RegCloseKey((HKEY)Handle);
1122 if (Handle2 != NULL)
1123 RegCloseKey((HKEY)Handle2);
1124 break;
1125
1126 case SE_FILE_OBJECT:
1127 NtClose(Handle);
1128 break;
1129
1130 case SE_KERNEL_OBJECT:
1131 case SE_WINDOW_OBJECT:
1132 CloseHandle(Handle);
1133 break;
1134
1135 case SE_SERVICE:
1136 CloseServiceHandle((SC_HANDLE)Handle);
1137 ASSERT(Handle2 != NULL);
1138 CloseServiceHandle((SC_HANDLE)Handle2);
1139 break;
1140
1141 default:
1142 break;
1143 }
1144 }
1145
1146
1147 /**********************************************************************
1148 * AccRewriteGetNamedRights EXPORTED
1149 *
1150 * @unimplemented
1151 */
1152 DWORD WINAPI
1153 AccRewriteGetNamedRights(LPWSTR pObjectName,
1154 SE_OBJECT_TYPE ObjectType,
1155 SECURITY_INFORMATION SecurityInfo,
1156 PSID* ppsidOwner,
1157 PSID* ppsidGroup,
1158 PACL* ppDacl,
1159 PACL* ppSacl,
1160 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
1161 {
1162 HANDLE Handle = NULL;
1163 HANDLE Handle2 = NULL;
1164 DWORD LastErr;
1165 DWORD Ret;
1166
1167 /* save the last error code */
1168 LastErr = GetLastError();
1169
1170 /* create the handle */
1171 Ret = AccpOpenNamedObject(pObjectName,
1172 ObjectType,
1173 SecurityInfo,
1174 &Handle,
1175 &Handle2,
1176 FALSE);
1177
1178 if (Ret == ERROR_SUCCESS)
1179 {
1180 ASSERT(Handle != NULL);
1181
1182 /* perform the operation */
1183 Ret = AccRewriteGetHandleRights(Handle,
1184 ObjectType,
1185 SecurityInfo,
1186 ppsidOwner,
1187 ppsidGroup,
1188 ppDacl,
1189 ppSacl,
1190 ppSecurityDescriptor);
1191
1192 /* close opened handles */
1193 AccpCloseObjectHandle(ObjectType,
1194 Handle,
1195 Handle2);
1196 }
1197
1198 /* restore the last error code */
1199 SetLastError(LastErr);
1200
1201 return Ret;
1202 }
1203
1204
1205 /**********************************************************************
1206 * AccRewriteSetNamedRights EXPORTED
1207 *
1208 * @unimplemented
1209 */
1210 DWORD WINAPI
1211 AccRewriteSetNamedRights(LPWSTR pObjectName,
1212 SE_OBJECT_TYPE ObjectType,
1213 SECURITY_INFORMATION SecurityInfo,
1214 PSECURITY_DESCRIPTOR pSecurityDescriptor)
1215 {
1216 HANDLE Handle = NULL;
1217 HANDLE Handle2 = NULL;
1218 DWORD LastErr;
1219 DWORD Ret;
1220
1221 /* save the last error code */
1222 LastErr = GetLastError();
1223
1224 /* create the handle */
1225 Ret = AccpOpenNamedObject(pObjectName,
1226 ObjectType,
1227 SecurityInfo,
1228 &Handle,
1229 &Handle2,
1230 TRUE);
1231
1232 if (Ret == ERROR_SUCCESS)
1233 {
1234 ASSERT(Handle != NULL);
1235
1236 /* perform the operation */
1237 Ret = AccRewriteSetHandleRights(Handle,
1238 ObjectType,
1239 SecurityInfo,
1240 pSecurityDescriptor);
1241
1242 /* close opened handles */
1243 AccpCloseObjectHandle(ObjectType,
1244 Handle,
1245 Handle2);
1246 }
1247
1248 /* restore the last error code */
1249 SetLastError(LastErr);
1250
1251 return Ret;
1252 }
1253
1254
1255 /**********************************************************************
1256 * AccRewriteSetEntriesInAcl EXPORTED
1257 *
1258 * @implemented
1259 */
1260 DWORD WINAPI
1261 AccRewriteSetEntriesInAcl(ULONG cCountOfExplicitEntries,
1262 PEXPLICIT_ACCESS_W pListOfExplicitEntries,
1263 PACL OldAcl,
1264 PACL* NewAcl)
1265 {
1266 PACL pNew = NULL;
1267 ACL_SIZE_INFORMATION SizeInformation;
1268 PACE_HEADER pAce;
1269 BOOLEAN KeepAceBuf[8];
1270 BOOLEAN *pKeepAce = NULL;
1271 GUID ObjectTypeGuid, InheritedObjectTypeGuid;
1272 DWORD ObjectsPresent;
1273 BOOL needToClean;
1274 PSID pSid1, pSid2;
1275 ULONG i, j;
1276 LSA_HANDLE PolicyHandle = NULL;
1277 BOOL bRet;
1278 DWORD LastErr;
1279 DWORD Ret = ERROR_SUCCESS;
1280
1281 /* save the last error code */
1282 LastErr = GetLastError();
1283
1284 *NewAcl = NULL;
1285
1286 /* Get information about previous ACL */
1287 if (OldAcl)
1288 {
1289 if (!GetAclInformation(OldAcl, &SizeInformation, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
1290 {
1291 Ret = GetLastError();
1292 goto Cleanup;
1293 }
1294
1295 if (SizeInformation.AceCount > sizeof(KeepAceBuf) / sizeof(KeepAceBuf[0]))
1296 {
1297 pKeepAce = (BOOLEAN *)LocalAlloc(LMEM_FIXED, SizeInformation.AceCount * sizeof(*pKeepAce));
1298 if (!pKeepAce)
1299 {
1300 Ret = ERROR_NOT_ENOUGH_MEMORY;
1301 goto Cleanup;
1302 }
1303 }
1304 else
1305 pKeepAce = KeepAceBuf;
1306
1307 memset(pKeepAce, TRUE, SizeInformation.AceCount * sizeof(*pKeepAce));
1308 }
1309 else
1310 {
1311 ZeroMemory(&SizeInformation, sizeof(ACL_SIZE_INFORMATION));
1312 SizeInformation.AclBytesInUse = sizeof(ACL);
1313 }
1314
1315 /* Get size required for new entries */
1316 for (i = 0; i < cCountOfExplicitEntries; i++)
1317 {
1318 Ret = AccpGetTrusteeSid(&pListOfExplicitEntries[i].Trustee,
1319 &PolicyHandle,
1320 &pSid1,
1321 &needToClean);
1322 if (Ret != ERROR_SUCCESS)
1323 goto Cleanup;
1324
1325 ObjectsPresent = AccpGetTrusteeObjects(&pListOfExplicitEntries[i].Trustee,
1326 NULL,
1327 NULL);
1328
1329 switch (pListOfExplicitEntries[i].grfAccessMode)
1330 {
1331 case REVOKE_ACCESS:
1332 case SET_ACCESS:
1333 /* Discard all accesses for the trustee... */
1334 for (j = 0; j < SizeInformation.AceCount; j++)
1335 {
1336 if (!pKeepAce[j])
1337 continue;
1338 if (!GetAce(OldAcl, j, (PVOID*)&pAce))
1339 {
1340 Ret = GetLastError();
1341 goto Cleanup;
1342 }
1343
1344 pSid2 = AccpGetAceSid(pAce);
1345 if (RtlEqualSid(pSid1, pSid2))
1346 {
1347 pKeepAce[j] = FALSE;
1348 SizeInformation.AclBytesInUse -= pAce->AceSize;
1349 }
1350 }
1351 if (pListOfExplicitEntries[i].grfAccessMode == REVOKE_ACCESS)
1352 break;
1353 /* ...and replace by the current access */
1354 case GRANT_ACCESS:
1355 case DENY_ACCESS:
1356 /* Add to ACL */
1357 SizeInformation.AclBytesInUse += AccpCalcNeededAceSize(pSid1, ObjectsPresent);
1358 break;
1359 case SET_AUDIT_SUCCESS:
1360 case SET_AUDIT_FAILURE:
1361 /* FIXME */
1362 DPRINT1("Case not implemented!\n");
1363 break;
1364 default:
1365 DPRINT1("Unknown access mode 0x%x. Ignoring it\n", pListOfExplicitEntries[i].grfAccessMode);
1366 break;
1367 }
1368
1369 if (needToClean)
1370 LocalFree((HLOCAL)pSid1);
1371 }
1372
1373 /* Succeed, if no ACL needs to be allocated */
1374 if (SizeInformation.AclBytesInUse == 0)
1375 goto Cleanup;
1376
1377 /* OK, now create the new ACL */
1378 DPRINT("Allocating %u bytes for the new ACL\n", SizeInformation.AclBytesInUse);
1379 pNew = (PACL)LocalAlloc(LMEM_FIXED, SizeInformation.AclBytesInUse);
1380 if (!pNew)
1381 {
1382 Ret = ERROR_NOT_ENOUGH_MEMORY;
1383 goto Cleanup;
1384 }
1385 if (!InitializeAcl(pNew, SizeInformation.AclBytesInUse, ACL_REVISION))
1386 {
1387 Ret = GetLastError();
1388 goto Cleanup;
1389 }
1390
1391 /* Fill it */
1392 /* 1a) New audit entries (SET_AUDIT_SUCCESS, SET_AUDIT_FAILURE) */
1393 /* FIXME */
1394
1395 /* 1b) Existing audit entries */
1396 /* FIXME */
1397
1398 /* 2a) New denied entries (DENY_ACCESS) */
1399 for (i = 0; i < cCountOfExplicitEntries; i++)
1400 {
1401 if (pListOfExplicitEntries[i].grfAccessMode == DENY_ACCESS)
1402 {
1403 /* FIXME: take care of pListOfExplicitEntries[i].grfInheritance */
1404 Ret = AccpGetTrusteeSid(&pListOfExplicitEntries[i].Trustee,
1405 &PolicyHandle,
1406 &pSid1,
1407 &needToClean);
1408 if (Ret != ERROR_SUCCESS)
1409 goto Cleanup;
1410
1411 ObjectsPresent = AccpGetTrusteeObjects(&pListOfExplicitEntries[i].Trustee,
1412 &ObjectTypeGuid,
1413 &InheritedObjectTypeGuid);
1414
1415 if (ObjectsPresent == 0)
1416 {
1417 /* FIXME: Call AddAccessDeniedAceEx instead! */
1418 bRet = AddAccessDeniedAce(pNew, ACL_REVISION, pListOfExplicitEntries[i].grfAccessPermissions, pSid1);
1419 }
1420 else
1421 {
1422 /* FIXME: Call AddAccessDeniedObjectAce */
1423 DPRINT1("Object ACEs not yet supported!\n");
1424 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1425 bRet = FALSE;
1426 }
1427
1428 if (needToClean) LocalFree((HLOCAL)pSid1);
1429 if (!bRet)
1430 {
1431 Ret = GetLastError();
1432 goto Cleanup;
1433 }
1434 }
1435 }
1436
1437 /* 2b) Existing denied entries */
1438 /* FIXME */
1439
1440 /* 3a) New allow entries (GRANT_ACCESS, SET_ACCESS) */
1441 for (i = 0; i < cCountOfExplicitEntries; i++)
1442 {
1443 if (pListOfExplicitEntries[i].grfAccessMode == SET_ACCESS ||
1444 pListOfExplicitEntries[i].grfAccessMode == GRANT_ACCESS)
1445 {
1446 /* FIXME: take care of pListOfExplicitEntries[i].grfInheritance */
1447 Ret = AccpGetTrusteeSid(&pListOfExplicitEntries[i].Trustee,
1448 &PolicyHandle,
1449 &pSid1,
1450 &needToClean);
1451 if (Ret != ERROR_SUCCESS)
1452 goto Cleanup;
1453
1454 ObjectsPresent = AccpGetTrusteeObjects(&pListOfExplicitEntries[i].Trustee,
1455 &ObjectTypeGuid,
1456 &InheritedObjectTypeGuid);
1457
1458 if (ObjectsPresent == 0)
1459 {
1460 /* FIXME: Call AddAccessAllowedAceEx instead! */
1461 bRet = AddAccessAllowedAce(pNew, ACL_REVISION, pListOfExplicitEntries[i].grfAccessPermissions, pSid1);
1462 }
1463 else
1464 {
1465 /* FIXME: Call AddAccessAllowedObjectAce */
1466 DPRINT1("Object ACEs not yet supported!\n");
1467 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1468 bRet = FALSE;
1469 }
1470
1471 if (needToClean) LocalFree((HLOCAL)pSid1);
1472 if (!bRet)
1473 {
1474 Ret = GetLastError();
1475 goto Cleanup;
1476 }
1477 }
1478 }
1479
1480 /* 3b) Existing allow entries */
1481 /* FIXME */
1482
1483 *NewAcl = pNew;
1484
1485 Cleanup:
1486 if (pKeepAce && pKeepAce != KeepAceBuf)
1487 LocalFree((HLOCAL)pKeepAce);
1488
1489 if (pNew && Ret != ERROR_SUCCESS)
1490 LocalFree((HLOCAL)pNew);
1491
1492 if (PolicyHandle)
1493 LsaClose(PolicyHandle);
1494
1495 /* restore the last error code */
1496 SetLastError(LastErr);
1497
1498 return Ret;
1499 }
1500
1501
1502 /**********************************************************************
1503 * AccGetInheritanceSource EXPORTED
1504 *
1505 * @unimplemented
1506 */
1507 DWORD WINAPI
1508 AccGetInheritanceSource(LPWSTR pObjectName,
1509 SE_OBJECT_TYPE ObjectType,
1510 SECURITY_INFORMATION SecurityInfo,
1511 BOOL Container,
1512 GUID** pObjectClassGuids,
1513 DWORD GuidCount,
1514 PACL pAcl,
1515 PFN_OBJECT_MGR_FUNCTS pfnArray,
1516 PGENERIC_MAPPING pGenericMapping,
1517 PINHERITED_FROMW pInheritArray)
1518 {
1519 UNIMPLEMENTED;
1520 return ERROR_CALL_NOT_IMPLEMENTED;
1521 }
1522
1523
1524 /**********************************************************************
1525 * AccFreeIndexArray EXPORTED
1526 *
1527 * @implemented
1528 */
1529 DWORD WINAPI
1530 AccFreeIndexArray(PINHERITED_FROMW pInheritArray,
1531 USHORT AceCnt,
1532 PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL)
1533 {
1534 PINHERITED_FROMW pLast;
1535
1536 UNREFERENCED_PARAMETER(pfnArray);
1537
1538 pLast = pInheritArray + AceCnt;
1539 while (pInheritArray != pLast)
1540 {
1541 if (pInheritArray->AncestorName != NULL)
1542 {
1543 LocalFree((HLOCAL)pInheritArray->AncestorName);
1544 pInheritArray->AncestorName = NULL;
1545 }
1546
1547 pInheritArray++;
1548 }
1549
1550 return ERROR_SUCCESS;
1551 }
1552
1553
1554 /**********************************************************************
1555 * AccRewriteGetExplicitEntriesFromAcl EXPORTED
1556 *
1557 * @implemented
1558 */
1559 DWORD WINAPI
1560 AccRewriteGetExplicitEntriesFromAcl(PACL pacl,
1561 PULONG pcCountOfExplicitEntries,
1562 PEXPLICIT_ACCESS_W* pListOfExplicitEntries)
1563 {
1564 PACE_HEADER AceHeader;
1565 PSID Sid, SidTarget;
1566 ULONG ObjectAceCount = 0;
1567 POBJECTS_AND_SID ObjSid;
1568 SIZE_T Size;
1569 PEXPLICIT_ACCESS_W peaw;
1570 DWORD LastErr, SidLen;
1571 DWORD AceIndex = 0;
1572 DWORD ErrorCode = ERROR_SUCCESS;
1573
1574 /* save the last error code */
1575 LastErr = GetLastError();
1576
1577 if (pacl != NULL)
1578 {
1579 if (pacl->AceCount != 0)
1580 {
1581 Size = (SIZE_T)pacl->AceCount * sizeof(EXPLICIT_ACCESS_W);
1582
1583 /* calculate the space needed */
1584 while (GetAce(pacl,
1585 AceIndex,
1586 (LPVOID*)&AceHeader))
1587 {
1588 Sid = AccpGetAceSid(AceHeader);
1589 Size += GetLengthSid(Sid);
1590
1591 if (AccpIsObjectAce(AceHeader))
1592 ObjectAceCount++;
1593
1594 AceIndex++;
1595 }
1596
1597 Size += ObjectAceCount * sizeof(OBJECTS_AND_SID);
1598
1599 ASSERT(pacl->AceCount == AceIndex);
1600
1601 /* allocate the array */
1602 peaw = (PEXPLICIT_ACCESS_W)LocalAlloc(LMEM_FIXED,
1603 Size);
1604 if (peaw != NULL)
1605 {
1606 AceIndex = 0;
1607 ObjSid = (POBJECTS_AND_SID)(peaw + pacl->AceCount);
1608 SidTarget = (PSID)(ObjSid + ObjectAceCount);
1609
1610 /* initialize the array */
1611 while (GetAce(pacl,
1612 AceIndex,
1613 (LPVOID*)&AceHeader))
1614 {
1615 Sid = AccpGetAceSid(AceHeader);
1616 SidLen = GetLengthSid(Sid);
1617
1618 peaw[AceIndex].grfAccessPermissions = AccpGetAceAccessMask(AceHeader);
1619 peaw[AceIndex].grfAccessMode = AccpGetAceAccessMode(AceHeader);
1620 peaw[AceIndex].grfInheritance = AceHeader->AceFlags & VALID_INHERIT_FLAGS;
1621
1622 if (CopySid(SidLen,
1623 SidTarget,
1624 Sid))
1625 {
1626 if (AccpIsObjectAce(AceHeader))
1627 {
1628 BuildTrusteeWithObjectsAndSid(&peaw[AceIndex].Trustee,
1629 ObjSid++,
1630 AccpGetObjectAceObjectType(AceHeader),
1631 AccpGetObjectAceInheritedObjectType(AceHeader),
1632 SidTarget);
1633 }
1634 else
1635 {
1636 BuildTrusteeWithSid(&peaw[AceIndex].Trustee,
1637 SidTarget);
1638 }
1639
1640 SidTarget = (PSID)((ULONG_PTR)SidTarget + SidLen);
1641 }
1642 else
1643 {
1644 /* copying the SID failed, treat it as an fatal error... */
1645 ErrorCode = GetLastError();
1646
1647 /* free allocated resources */
1648 LocalFree(peaw);
1649 peaw = NULL;
1650 AceIndex = 0;
1651 break;
1652 }
1653
1654 AceIndex++;
1655 }
1656
1657 *pcCountOfExplicitEntries = AceIndex;
1658 *pListOfExplicitEntries = peaw;
1659 }
1660 else
1661 ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1662 }
1663 else
1664 {
1665 goto EmptyACL;
1666 }
1667 }
1668 else
1669 {
1670 EmptyACL:
1671 *pcCountOfExplicitEntries = 0;
1672 *pListOfExplicitEntries = NULL;
1673 }
1674
1675 /* restore the last error code */
1676 SetLastError(LastErr);
1677
1678 return ErrorCode;
1679 }
1680
1681
1682 /**********************************************************************
1683 * AccTreeResetNamedSecurityInfo EXPORTED
1684 *
1685 * @unimplemented
1686 */
1687 DWORD WINAPI
1688 AccTreeResetNamedSecurityInfo(LPWSTR pObjectName,
1689 SE_OBJECT_TYPE ObjectType,
1690 SECURITY_INFORMATION SecurityInfo,
1691 PSID pOwner,
1692 PSID pGroup,
1693 PACL pDacl,
1694 PACL pSacl,
1695 BOOL KeepExplicit,
1696 FN_PROGRESSW fnProgress,
1697 PROG_INVOKE_SETTING ProgressInvokeSetting,
1698 PVOID Args)
1699 {
1700 UNIMPLEMENTED;
1701 return ERROR_CALL_NOT_IMPLEMENTED;
1702 }
1703
1704
1705 BOOL WINAPI
1706 DllMain(IN HINSTANCE hinstDLL,
1707 IN DWORD dwReason,
1708 IN LPVOID lpvReserved)
1709 {
1710 switch (dwReason)
1711 {
1712 case DLL_PROCESS_ATTACH:
1713 hDllInstance = hinstDLL;
1714 DisableThreadLibraryCalls(hinstDLL);
1715 break;
1716
1717 case DLL_PROCESS_DETACH:
1718 break;
1719 }
1720 return TRUE;
1721 }
1722