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