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