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