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