xref: /reactos/dll/win32/ntmarta/ntmarta.c (revision 5100859e)
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 AccpLookupCurrentUser(OUT PSID *ppSid)
448 {
449     DWORD Ret;
450     CHAR Buffer[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
451     DWORD Length;
452     HANDLE Token;
453     PSID pSid;
454 
455     *ppSid = NULL;
456     if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &Token))
457     {
458         Ret = GetLastError();
459         if (Ret != ERROR_NO_TOKEN)
460         {
461             return Ret;
462         }
463 
464         if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &Token))
465         {
466             return GetLastError();
467         }
468     }
469 
470     Length = sizeof(Buffer);
471     if (!GetTokenInformation(Token, TokenUser, Buffer, Length, &Length))
472     {
473         Ret = GetLastError();
474         CloseHandle(Token);
475         return Ret;
476     }
477     CloseHandle(Token);
478 
479     pSid = ((PTOKEN_USER)Buffer)->User.Sid;
480     Length = GetLengthSid(pSid);
481     *ppSid = LocalAlloc(LMEM_FIXED, Length);
482     if (!*ppSid)
483     {
484         return ERROR_NOT_ENOUGH_MEMORY;
485     }
486     CopyMemory(*ppSid, pSid, Length);
487 
488     return ERROR_SUCCESS;
489 }
490 
491 static DWORD
492 AccpLookupSidByName(IN LSA_HANDLE PolicyHandle,
493                     IN LPWSTR Name,
494                     OUT PSID *pSid)
495 {
496     NTSTATUS Status;
497     LSA_UNICODE_STRING LsaNames[1];
498     PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains = NULL;
499     PLSA_TRANSLATED_SID2 TranslatedSid = NULL;
500     DWORD SidLen;
501     DWORD Ret = ERROR_SUCCESS;
502 
503     LsaNames[0].Buffer = Name;
504     LsaNames[0].Length = wcslen(Name) * sizeof(WCHAR);
505     LsaNames[0].MaximumLength = LsaNames[0].Length + sizeof(WCHAR);
506 
507     Status = LsaLookupNames2(PolicyHandle,
508                              0,
509                              sizeof(LsaNames) / sizeof(LsaNames[0]),
510                              LsaNames,
511                              &ReferencedDomains,
512                              &TranslatedSid);
513 
514     if (!NT_SUCCESS(Status))
515         return LsaNtStatusToWinError(Status);
516 
517     if (TranslatedSid->Use == SidTypeUnknown || TranslatedSid->Use == SidTypeInvalid)
518     {
519         Ret = LsaNtStatusToWinError(STATUS_NONE_MAPPED); /* FIXME- what error code? */
520         goto Cleanup;
521     }
522 
523     SidLen = GetLengthSid(TranslatedSid->Sid);
524     ASSERT(SidLen != 0);
525 
526     *pSid = LocalAlloc(LMEM_FIXED, (SIZE_T)SidLen);
527     if (*pSid != NULL)
528     {
529         if (!CopySid(SidLen,
530                      *pSid,
531                      TranslatedSid->Sid))
532         {
533             Ret = GetLastError();
534 
535             LocalFree((HLOCAL)*pSid);
536             *pSid = NULL;
537         }
538     }
539     else
540         Ret = ERROR_NOT_ENOUGH_MEMORY;
541 
542 Cleanup:
543     LsaFreeMemory(ReferencedDomains);
544     LsaFreeMemory(TranslatedSid);
545 
546     return Ret;
547 }
548 
549 
550 static DWORD
551 AccpGetTrusteeSid(IN PTRUSTEE_W Trustee,
552                   IN OUT PLSA_HANDLE pPolicyHandle,
553                   OUT PSID *ppSid,
554                   OUT BOOL *Allocated)
555 {
556     DWORD Ret = ERROR_SUCCESS;
557     LPWSTR TrusteeName;
558 
559     *ppSid = NULL;
560     *Allocated = FALSE;
561 
562     /* Windows ignores this */
563 #if 0
564     if (Trustee->pMultipleTrustee || Trustee->MultipleTrusteeOperation != NO_MULTIPLE_TRUSTEE)
565     {
566         /* This is currently not supported */
567         return ERROR_INVALID_PARAMETER;
568     }
569 #endif
570 
571     switch (Trustee->TrusteeForm)
572     {
573         case TRUSTEE_IS_OBJECTS_AND_NAME:
574             if (((POBJECTS_AND_NAME_W)Trustee->ptstrName)->ObjectsPresent != 0)
575             {
576                 /* This is not supported as there is no way to interpret the
577                    strings provided, and we need GUIDs for the ACEs... */
578                 Ret = ERROR_INVALID_PARAMETER;
579                 break;
580             }
581             /* fall through */
582 
583         case TRUSTEE_IS_NAME:
584             TrusteeName = AccpGetTrusteeName(Trustee);
585             if (!wcscmp(TrusteeName, L"CURRENT_USER"))
586             {
587                 Ret = AccpLookupCurrentUser(ppSid);
588                 if (Ret == ERROR_SUCCESS)
589                 {
590                     ASSERT(*ppSid != NULL);
591                     *Allocated = TRUE;
592                 }
593                 break;
594             }
595 
596             if (*pPolicyHandle == NULL)
597             {
598                 Ret = AccpOpenLSAPolicyHandle(NULL, /* FIXME - always local? */
599                                               POLICY_LOOKUP_NAMES,
600                                               pPolicyHandle);
601                 if (Ret != ERROR_SUCCESS)
602                     return Ret;
603 
604                 ASSERT(*pPolicyHandle != NULL);
605             }
606 
607             Ret = AccpLookupSidByName(*pPolicyHandle,
608                                       TrusteeName,
609                                       ppSid);
610             if (Ret == ERROR_SUCCESS)
611             {
612                 ASSERT(*ppSid != NULL);
613                 *Allocated = TRUE;
614             }
615             break;
616 
617         case TRUSTEE_IS_OBJECTS_AND_SID:
618             *ppSid = ((POBJECTS_AND_SID)Trustee->ptstrName)->pSid;
619             break;
620 
621         case TRUSTEE_IS_SID:
622             *ppSid = (PSID)Trustee->ptstrName;
623             break;
624 
625         default:
626             Ret = ERROR_INVALID_PARAMETER;
627             break;
628     }
629 
630     return Ret;
631 }
632 
633 
634 /**********************************************************************
635  * AccRewriteGetHandleRights				EXPORTED
636  *
637  * @unimplemented
638  */
639 DWORD WINAPI
640 AccRewriteGetHandleRights(HANDLE handle,
641                           SE_OBJECT_TYPE ObjectType,
642                           SECURITY_INFORMATION SecurityInfo,
643                           PSID* ppsidOwner,
644                           PSID* ppsidGroup,
645                           PACL* ppDacl,
646                           PACL* ppSacl,
647                           PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
648 {
649     PSECURITY_DESCRIPTOR pSD = NULL;
650     ULONG SDSize = 0;
651     NTSTATUS Status;
652     DWORD LastErr;
653     DWORD Ret;
654 
655     /* save the last error code */
656     LastErr = GetLastError();
657 
658     do
659     {
660         Ret = ERROR_SUCCESS;
661 
662         /* allocate a buffer large enough to hold the
663            security descriptor we need to return */
664         SDSize += 0x100;
665         if (pSD == NULL)
666         {
667             pSD = LocalAlloc(LMEM_FIXED,
668                              (SIZE_T)SDSize);
669         }
670         else
671         {
672             PSECURITY_DESCRIPTOR newSD;
673 
674             newSD = LocalReAlloc((HLOCAL)pSD,
675                                  (SIZE_T)SDSize,
676                                  LMEM_MOVEABLE);
677             if (newSD != NULL)
678                 pSD = newSD;
679         }
680 
681         if (pSD == NULL)
682         {
683             Ret = GetLastError();
684             break;
685         }
686 
687         /* perform the actual query depending on the object type */
688         switch (ObjectType)
689         {
690             case SE_REGISTRY_KEY:
691             {
692                 Ret = (DWORD)RegGetKeySecurity((HKEY)handle,
693                                                SecurityInfo,
694                                                pSD,
695                                                &SDSize);
696                 break;
697             }
698 
699             case SE_FILE_OBJECT:
700                 /* FIXME - handle console handles? */
701             case SE_KERNEL_OBJECT:
702             {
703                 Status = NtQuerySecurityObject(handle,
704                                                SecurityInfo,
705                                                pSD,
706                                                SDSize,
707                                                &SDSize);
708                 if (!NT_SUCCESS(Status))
709                 {
710                     Ret = RtlNtStatusToDosError(Status);
711                 }
712                 break;
713             }
714 
715             case SE_SERVICE:
716             {
717                 if (!QueryServiceObjectSecurity((SC_HANDLE)handle,
718                                                 SecurityInfo,
719                                                 pSD,
720                                                 SDSize,
721                                                 &SDSize))
722                 {
723                     Ret = GetLastError();
724                 }
725                 break;
726             }
727 
728             case SE_WINDOW_OBJECT:
729             {
730                 if (!GetUserObjectSecurity(handle,
731                                            &SecurityInfo,
732                                            pSD,
733                                            SDSize,
734                                            &SDSize))
735                 {
736                     Ret = GetLastError();
737                 }
738                 break;
739             }
740 
741             default:
742             {
743                 UNIMPLEMENTED;
744                 Ret = ERROR_CALL_NOT_IMPLEMENTED;
745                 break;
746             }
747         }
748 
749     } while (Ret == ERROR_INSUFFICIENT_BUFFER);
750 
751     if (Ret == ERROR_SUCCESS)
752     {
753         BOOL Present, Defaulted;
754 
755         if (SecurityInfo & OWNER_SECURITY_INFORMATION && ppsidOwner != NULL)
756         {
757             *ppsidOwner = NULL;
758             if (!GetSecurityDescriptorOwner(pSD,
759                                             ppsidOwner,
760                                             &Defaulted))
761             {
762                 Ret = GetLastError();
763                 goto Cleanup;
764             }
765         }
766 
767         if (SecurityInfo & GROUP_SECURITY_INFORMATION && ppsidGroup != NULL)
768         {
769             *ppsidGroup = NULL;
770             if (!GetSecurityDescriptorGroup(pSD,
771                                             ppsidGroup,
772                                             &Defaulted))
773             {
774                 Ret = GetLastError();
775                 goto Cleanup;
776             }
777         }
778 
779         if (SecurityInfo & DACL_SECURITY_INFORMATION && ppDacl != NULL)
780         {
781             *ppDacl = NULL;
782             if (!GetSecurityDescriptorDacl(pSD,
783                                            &Present,
784                                            ppDacl,
785                                            &Defaulted))
786             {
787                 Ret = GetLastError();
788                 goto Cleanup;
789             }
790         }
791 
792         if (SecurityInfo & SACL_SECURITY_INFORMATION && ppSacl != NULL)
793         {
794             *ppSacl = NULL;
795             if (!GetSecurityDescriptorSacl(pSD,
796                                            &Present,
797                                            ppSacl,
798                                            &Defaulted))
799             {
800                 Ret = GetLastError();
801                 goto Cleanup;
802             }
803         }
804 
805         *ppSecurityDescriptor = pSD;
806     }
807     else
808     {
809 Cleanup:
810         if (pSD != NULL)
811         {
812             LocalFree((HLOCAL)pSD);
813         }
814     }
815 
816     /* restore the last error code */
817     SetLastError(LastErr);
818 
819     return Ret;
820 }
821 
822 
823 /**********************************************************************
824  * AccRewriteSetHandleRights				EXPORTED
825  *
826  * @unimplemented
827  */
828 DWORD WINAPI
829 AccRewriteSetHandleRights(HANDLE handle,
830                           SE_OBJECT_TYPE ObjectType,
831                           SECURITY_INFORMATION SecurityInfo,
832                           PSECURITY_DESCRIPTOR pSecurityDescriptor)
833 {
834     NTSTATUS Status;
835     DWORD LastErr;
836     DWORD Ret = ERROR_SUCCESS;
837 
838     /* save the last error code */
839     LastErr = GetLastError();
840 
841     /* set the security according to the object type */
842     switch (ObjectType)
843     {
844         case SE_REGISTRY_KEY:
845         {
846             Ret = (DWORD)RegSetKeySecurity((HKEY)handle,
847                                            SecurityInfo,
848                                            pSecurityDescriptor);
849             break;
850         }
851 
852         case SE_FILE_OBJECT:
853             /* FIXME - handle console handles? */
854         case SE_KERNEL_OBJECT:
855         {
856             Status = NtSetSecurityObject(handle,
857                                          SecurityInfo,
858                                          pSecurityDescriptor);
859             if (!NT_SUCCESS(Status))
860             {
861                 Ret = RtlNtStatusToDosError(Status);
862             }
863             break;
864         }
865 
866         case SE_SERVICE:
867         {
868             if (!SetServiceObjectSecurity((SC_HANDLE)handle,
869                                           SecurityInfo,
870                                           pSecurityDescriptor))
871             {
872                 Ret = GetLastError();
873             }
874             break;
875         }
876 
877         case SE_WINDOW_OBJECT:
878         {
879             if (!SetUserObjectSecurity(handle,
880                                        &SecurityInfo,
881                                        pSecurityDescriptor))
882             {
883                 Ret = GetLastError();
884             }
885             break;
886         }
887 
888         default:
889         {
890             UNIMPLEMENTED;
891             Ret = ERROR_CALL_NOT_IMPLEMENTED;
892             break;
893         }
894     }
895 
896 
897     /* restore the last error code */
898     SetLastError(LastErr);
899 
900     return Ret;
901 }
902 
903 
904 static DWORD
905 AccpOpenNamedObject(LPWSTR pObjectName,
906                     SE_OBJECT_TYPE ObjectType,
907                     SECURITY_INFORMATION SecurityInfo,
908                     PHANDLE Handle,
909                     PHANDLE Handle2,
910                     BOOL Write)
911 {
912     LPWSTR lpPath;
913     NTSTATUS Status;
914     ACCESS_MASK DesiredAccess = (ACCESS_MASK)0;
915     DWORD Ret = ERROR_SUCCESS;
916 
917     /* determine the required access rights */
918     switch (ObjectType)
919     {
920         case SE_REGISTRY_KEY:
921         case SE_FILE_OBJECT:
922         case SE_KERNEL_OBJECT:
923         case SE_SERVICE:
924         case SE_WINDOW_OBJECT:
925             if (Write)
926             {
927                 SetSecurityAccessMask(SecurityInfo,
928                                       (PDWORD)&DesiredAccess);
929             }
930             else
931             {
932                 QuerySecurityAccessMask(SecurityInfo,
933                                         (PDWORD)&DesiredAccess);
934             }
935             break;
936 
937         default:
938             break;
939     }
940 
941     /* make a copy of the path if we're modifying the string */
942     switch (ObjectType)
943     {
944         case SE_REGISTRY_KEY:
945         case SE_SERVICE:
946             lpPath = (LPWSTR)LocalAlloc(LMEM_FIXED,
947                                         (wcslen(pObjectName) + 1) * sizeof(WCHAR));
948             if (lpPath == NULL)
949             {
950                 Ret = GetLastError();
951                 goto Cleanup;
952             }
953 
954             wcscpy(lpPath,
955                    pObjectName);
956             break;
957 
958         default:
959             lpPath = pObjectName;
960             break;
961     }
962 
963     /* open a handle to the path depending on the object type */
964     switch (ObjectType)
965     {
966         case SE_FILE_OBJECT:
967         {
968             IO_STATUS_BLOCK IoStatusBlock;
969             OBJECT_ATTRIBUTES ObjectAttributes;
970             UNICODE_STRING FileName;
971 
972             if (!RtlDosPathNameToNtPathName_U(pObjectName,
973                                               &FileName,
974                                               NULL,
975                                               NULL))
976             {
977                 Ret = ERROR_INVALID_NAME;
978                 goto Cleanup;
979             }
980 
981             InitializeObjectAttributes(&ObjectAttributes,
982                                        &FileName,
983                                        OBJ_CASE_INSENSITIVE,
984                                        NULL,
985                                        NULL);
986 
987             Status = NtOpenFile(Handle,
988                                 DesiredAccess | SYNCHRONIZE,
989                                 &ObjectAttributes,
990                                 &IoStatusBlock,
991                                 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
992                                 FILE_SYNCHRONOUS_IO_NONALERT);
993 
994             RtlFreeHeap(RtlGetProcessHeap(),
995                         0,
996                         FileName.Buffer);
997 
998             if (!NT_SUCCESS(Status))
999             {
1000                 Ret = RtlNtStatusToDosError(Status);
1001             }
1002             break;
1003         }
1004 
1005         case SE_REGISTRY_KEY:
1006         {
1007             static const struct
1008             {
1009                 HKEY hRootKey;
1010                 LPCWSTR szRootKey;
1011             } AccRegRootKeys[] =
1012             {
1013                 {HKEY_CLASSES_ROOT, L"CLASSES_ROOT"},
1014                 {HKEY_CURRENT_USER, L"CURRENT_USER"},
1015                 {HKEY_LOCAL_MACHINE, L"MACHINE"},
1016                 {HKEY_USERS, L"USERS"},
1017                 {HKEY_CURRENT_CONFIG, L"CONFIG"},
1018             };
1019             LPWSTR lpMachineName, lpRootKeyName, lpKeyName;
1020             HKEY hRootKey = NULL;
1021             UINT i;
1022 
1023             /* parse the registry path */
1024             if (lpPath[0] == L'\\' && lpPath[1] == L'\\')
1025             {
1026                 lpMachineName = lpPath;
1027 
1028                 lpRootKeyName = wcschr(lpPath + 2,
1029                                        L'\\');
1030                 if (lpRootKeyName == NULL)
1031                     goto ParseRegErr;
1032                 else
1033                     *(lpRootKeyName++) = L'\0';
1034             }
1035             else
1036             {
1037                 lpMachineName = NULL;
1038                 lpRootKeyName = lpPath;
1039             }
1040 
1041             lpKeyName = wcschr(lpRootKeyName,
1042                                L'\\');
1043             if (lpKeyName != NULL)
1044             {
1045                 *(lpKeyName++) = L'\0';
1046             }
1047 
1048             for (i = 0;
1049                  i != sizeof(AccRegRootKeys) / sizeof(AccRegRootKeys[0]);
1050                  i++)
1051             {
1052                 if (!wcsicmp(lpRootKeyName,
1053                              AccRegRootKeys[i].szRootKey))
1054                 {
1055                     hRootKey = AccRegRootKeys[i].hRootKey;
1056                     break;
1057                 }
1058             }
1059 
1060             if (hRootKey == NULL)
1061             {
1062 ParseRegErr:
1063                 /* FIXME - right error code? */
1064                 Ret = ERROR_INVALID_PARAMETER;
1065                 goto Cleanup;
1066             }
1067 
1068             /* open the registry key */
1069             if (lpMachineName != NULL)
1070             {
1071                 Ret = RegConnectRegistry(lpMachineName,
1072                                          hRootKey,
1073                                          (PHKEY)Handle2);
1074 
1075                 if (Ret != ERROR_SUCCESS)
1076                     goto Cleanup;
1077 
1078                 hRootKey = (HKEY)(*Handle2);
1079             }
1080 
1081             Ret = RegOpenKeyEx(hRootKey,
1082                                lpKeyName,
1083                                0,
1084                                (REGSAM)DesiredAccess,
1085                                (PHKEY)Handle);
1086             if (Ret != ERROR_SUCCESS)
1087             {
1088                 if (*Handle2 != NULL)
1089                 {
1090                     RegCloseKey((HKEY)(*Handle2));
1091                 }
1092 
1093                 goto Cleanup;
1094             }
1095             break;
1096         }
1097 
1098         case SE_SERVICE:
1099         {
1100             LPWSTR lpServiceName, lpMachineName;
1101 
1102             /* parse the service path */
1103             if (lpPath[0] == L'\\' && lpPath[1] == L'\\')
1104             {
1105                 DesiredAccess |= SC_MANAGER_CONNECT;
1106 
1107                 lpMachineName = lpPath;
1108 
1109                 lpServiceName = wcschr(lpPath + 2,
1110                                        L'\\');
1111                 if (lpServiceName == NULL)
1112                 {
1113                     /* FIXME - right error code? */
1114                     Ret = ERROR_INVALID_PARAMETER;
1115                     goto Cleanup;
1116                 }
1117                 else
1118                     *(lpServiceName++) = L'\0';
1119             }
1120             else
1121             {
1122                 lpMachineName = NULL;
1123                 lpServiceName = lpPath;
1124             }
1125 
1126             /* open the service */
1127             *Handle2 = (HANDLE)OpenSCManager(lpMachineName,
1128                                              NULL,
1129                                              (DWORD)DesiredAccess);
1130             if (*Handle2 == NULL)
1131             {
1132                 Ret = GetLastError();
1133                 ASSERT(Ret != ERROR_SUCCESS);
1134                 goto Cleanup;
1135             }
1136 
1137             DesiredAccess &= ~SC_MANAGER_CONNECT;
1138             *Handle = (HANDLE)OpenService((SC_HANDLE)(*Handle2),
1139                                           lpServiceName,
1140                                           (DWORD)DesiredAccess);
1141             if (*Handle == NULL)
1142             {
1143                 Ret = GetLastError();
1144                 ASSERT(Ret != ERROR_SUCCESS);
1145                 ASSERT(*Handle2 != NULL);
1146                 CloseServiceHandle((SC_HANDLE)(*Handle2));
1147 
1148                 goto Cleanup;
1149             }
1150             break;
1151         }
1152 
1153         default:
1154         {
1155             UNIMPLEMENTED;
1156             Ret = ERROR_CALL_NOT_IMPLEMENTED;
1157             break;
1158         }
1159     }
1160 
1161 Cleanup:
1162     if (lpPath != NULL && lpPath != pObjectName)
1163     {
1164         LocalFree((HLOCAL)lpPath);
1165     }
1166 
1167     return Ret;
1168 }
1169 
1170 
1171 static VOID
1172 AccpCloseObjectHandle(SE_OBJECT_TYPE ObjectType,
1173                       HANDLE Handle,
1174                       HANDLE Handle2)
1175 {
1176     ASSERT(Handle != NULL);
1177 
1178     /* close allocated handles depending on the object type */
1179     switch (ObjectType)
1180     {
1181         case SE_REGISTRY_KEY:
1182             RegCloseKey((HKEY)Handle);
1183             if (Handle2 != NULL)
1184                 RegCloseKey((HKEY)Handle2);
1185             break;
1186 
1187         case SE_FILE_OBJECT:
1188             NtClose(Handle);
1189             break;
1190 
1191         case SE_KERNEL_OBJECT:
1192         case SE_WINDOW_OBJECT:
1193             CloseHandle(Handle);
1194             break;
1195 
1196         case SE_SERVICE:
1197             CloseServiceHandle((SC_HANDLE)Handle);
1198             ASSERT(Handle2 != NULL);
1199             CloseServiceHandle((SC_HANDLE)Handle2);
1200             break;
1201 
1202         default:
1203             break;
1204     }
1205 }
1206 
1207 
1208 /**********************************************************************
1209  * AccRewriteGetNamedRights				EXPORTED
1210  *
1211  * @unimplemented
1212  */
1213 DWORD WINAPI
1214 AccRewriteGetNamedRights(LPWSTR pObjectName,
1215                          SE_OBJECT_TYPE ObjectType,
1216                          SECURITY_INFORMATION SecurityInfo,
1217                          PSID* ppsidOwner,
1218                          PSID* ppsidGroup,
1219                          PACL* ppDacl,
1220                          PACL* ppSacl,
1221                          PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
1222 {
1223     HANDLE Handle = NULL;
1224     HANDLE Handle2 = NULL;
1225     DWORD LastErr;
1226     DWORD Ret;
1227 
1228     /* save the last error code */
1229     LastErr = GetLastError();
1230 
1231     /* create the handle */
1232     Ret = AccpOpenNamedObject(pObjectName,
1233                               ObjectType,
1234                               SecurityInfo,
1235                               &Handle,
1236                               &Handle2,
1237                               FALSE);
1238 
1239     if (Ret == ERROR_SUCCESS)
1240     {
1241         ASSERT(Handle != NULL);
1242 
1243         /* perform the operation */
1244         Ret = AccRewriteGetHandleRights(Handle,
1245                                         ObjectType,
1246                                         SecurityInfo,
1247                                         ppsidOwner,
1248                                         ppsidGroup,
1249                                         ppDacl,
1250                                         ppSacl,
1251                                         ppSecurityDescriptor);
1252 
1253         /* close opened handles */
1254         AccpCloseObjectHandle(ObjectType,
1255                               Handle,
1256                               Handle2);
1257     }
1258 
1259     /* restore the last error code */
1260     SetLastError(LastErr);
1261 
1262     return Ret;
1263 }
1264 
1265 
1266 /**********************************************************************
1267  * AccRewriteSetNamedRights				EXPORTED
1268  *
1269  * @unimplemented
1270  */
1271 DWORD WINAPI
1272 AccRewriteSetNamedRights(LPWSTR pObjectName,
1273                          SE_OBJECT_TYPE ObjectType,
1274                          SECURITY_INFORMATION SecurityInfo,
1275                          PSECURITY_DESCRIPTOR pSecurityDescriptor)
1276 {
1277     HANDLE Handle = NULL;
1278     HANDLE Handle2 = NULL;
1279     DWORD LastErr;
1280     DWORD Ret;
1281 
1282     /* save the last error code */
1283     LastErr = GetLastError();
1284 
1285     /* create the handle */
1286     Ret = AccpOpenNamedObject(pObjectName,
1287                               ObjectType,
1288                               SecurityInfo,
1289                               &Handle,
1290                               &Handle2,
1291                               TRUE);
1292 
1293     if (Ret == ERROR_SUCCESS)
1294     {
1295         ASSERT(Handle != NULL);
1296 
1297         /* perform the operation */
1298         Ret = AccRewriteSetHandleRights(Handle,
1299                                         ObjectType,
1300                                         SecurityInfo,
1301                                         pSecurityDescriptor);
1302 
1303         /* close opened handles */
1304         AccpCloseObjectHandle(ObjectType,
1305                               Handle,
1306                               Handle2);
1307     }
1308 
1309     /* restore the last error code */
1310     SetLastError(LastErr);
1311 
1312     return Ret;
1313 }
1314 
1315 
1316 /**********************************************************************
1317  * AccRewriteSetEntriesInAcl				EXPORTED
1318  *
1319  * @implemented
1320  */
1321 DWORD WINAPI
1322 AccRewriteSetEntriesInAcl(ULONG cCountOfExplicitEntries,
1323                           PEXPLICIT_ACCESS_W pListOfExplicitEntries,
1324                           PACL OldAcl,
1325                           PACL* NewAcl)
1326 {
1327     PACL pNew = NULL;
1328     ACL_SIZE_INFORMATION SizeInformation;
1329     PACE_HEADER pAce;
1330     BOOLEAN KeepAceBuf[8];
1331     BOOLEAN *pKeepAce = NULL;
1332     GUID ObjectTypeGuid, InheritedObjectTypeGuid;
1333     DWORD ObjectsPresent;
1334     BOOL needToClean;
1335     PSID pSid1, pSid2;
1336     ULONG i, j;
1337     LSA_HANDLE PolicyHandle = NULL;
1338     BOOL bRet;
1339     DWORD LastErr;
1340     DWORD Ret = ERROR_SUCCESS;
1341 
1342     /* save the last error code */
1343     LastErr = GetLastError();
1344 
1345     *NewAcl = NULL;
1346 
1347     /* Get information about previous ACL */
1348     if (OldAcl)
1349     {
1350         if (!GetAclInformation(OldAcl, &SizeInformation, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
1351         {
1352             Ret = GetLastError();
1353             goto Cleanup;
1354         }
1355 
1356         if (SizeInformation.AceCount > sizeof(KeepAceBuf) / sizeof(KeepAceBuf[0]))
1357         {
1358             pKeepAce = (BOOLEAN *)LocalAlloc(LMEM_FIXED, SizeInformation.AceCount * sizeof(*pKeepAce));
1359             if (!pKeepAce)
1360             {
1361                 Ret = ERROR_NOT_ENOUGH_MEMORY;
1362                 goto Cleanup;
1363             }
1364         }
1365         else
1366             pKeepAce = KeepAceBuf;
1367 
1368         memset(pKeepAce, TRUE, SizeInformation.AceCount * sizeof(*pKeepAce));
1369     }
1370     else
1371     {
1372         ZeroMemory(&SizeInformation, sizeof(ACL_SIZE_INFORMATION));
1373         SizeInformation.AclBytesInUse = sizeof(ACL);
1374     }
1375 
1376     /* Get size required for new entries */
1377     for (i = 0; i < cCountOfExplicitEntries; i++)
1378     {
1379         Ret = AccpGetTrusteeSid(&pListOfExplicitEntries[i].Trustee,
1380                                 &PolicyHandle,
1381                                 &pSid1,
1382                                 &needToClean);
1383         if (Ret != ERROR_SUCCESS)
1384             goto Cleanup;
1385 
1386         ObjectsPresent = AccpGetTrusteeObjects(&pListOfExplicitEntries[i].Trustee,
1387                                                NULL,
1388                                                NULL);
1389 
1390         switch (pListOfExplicitEntries[i].grfAccessMode)
1391         {
1392             case REVOKE_ACCESS:
1393             case SET_ACCESS:
1394                 /* Discard all accesses for the trustee... */
1395                 for (j = 0; j < SizeInformation.AceCount; j++)
1396                 {
1397                     if (!pKeepAce[j])
1398                         continue;
1399                     if (!GetAce(OldAcl, j, (PVOID*)&pAce))
1400                     {
1401                         Ret = GetLastError();
1402                         goto Cleanup;
1403                     }
1404 
1405                     pSid2 = AccpGetAceSid(pAce);
1406                     if (RtlEqualSid(pSid1, pSid2))
1407                     {
1408                         pKeepAce[j] = FALSE;
1409                         SizeInformation.AclBytesInUse -= pAce->AceSize;
1410                     }
1411                 }
1412                 if (pListOfExplicitEntries[i].grfAccessMode == REVOKE_ACCESS)
1413                     break;
1414                 /* ...and replace by the current access */
1415             case GRANT_ACCESS:
1416             case DENY_ACCESS:
1417                 /* Add to ACL */
1418                 SizeInformation.AclBytesInUse += AccpCalcNeededAceSize(pSid1, ObjectsPresent);
1419                 break;
1420             case SET_AUDIT_SUCCESS:
1421             case SET_AUDIT_FAILURE:
1422                 /* FIXME */
1423                 DPRINT1("Case not implemented!\n");
1424                 break;
1425             default:
1426                 DPRINT1("Unknown access mode 0x%x. Ignoring it\n", pListOfExplicitEntries[i].grfAccessMode);
1427                 break;
1428         }
1429 
1430         if (needToClean)
1431             LocalFree((HLOCAL)pSid1);
1432     }
1433 
1434     /* Succeed, if no ACL needs to be allocated */
1435     if (SizeInformation.AclBytesInUse == 0)
1436         goto Cleanup;
1437 
1438     /* OK, now create the new ACL */
1439     DPRINT("Allocating %u bytes for the new ACL\n", SizeInformation.AclBytesInUse);
1440     pNew = (PACL)LocalAlloc(LMEM_FIXED, SizeInformation.AclBytesInUse);
1441     if (!pNew)
1442     {
1443         Ret = ERROR_NOT_ENOUGH_MEMORY;
1444         goto Cleanup;
1445     }
1446     if (!InitializeAcl(pNew, SizeInformation.AclBytesInUse, ACL_REVISION))
1447     {
1448         Ret = GetLastError();
1449         goto Cleanup;
1450     }
1451 
1452     /* Fill it */
1453     /* 1a) New audit entries (SET_AUDIT_SUCCESS, SET_AUDIT_FAILURE) */
1454     /* FIXME */
1455 
1456     /* 1b) Existing audit entries */
1457     /* FIXME */
1458 
1459     /* 2a) New denied entries (DENY_ACCESS) */
1460     for (i = 0; i < cCountOfExplicitEntries; i++)
1461     {
1462         if (pListOfExplicitEntries[i].grfAccessMode == DENY_ACCESS)
1463         {
1464             /* FIXME: take care of pListOfExplicitEntries[i].grfInheritance */
1465             Ret = AccpGetTrusteeSid(&pListOfExplicitEntries[i].Trustee,
1466                                     &PolicyHandle,
1467                                     &pSid1,
1468                                     &needToClean);
1469             if (Ret != ERROR_SUCCESS)
1470                 goto Cleanup;
1471 
1472             ObjectsPresent = AccpGetTrusteeObjects(&pListOfExplicitEntries[i].Trustee,
1473                                                    &ObjectTypeGuid,
1474                                                    &InheritedObjectTypeGuid);
1475 
1476             if (ObjectsPresent == 0)
1477             {
1478                 /* FIXME: Call AddAccessDeniedAceEx instead! */
1479                 bRet = AddAccessDeniedAce(pNew, ACL_REVISION, pListOfExplicitEntries[i].grfAccessPermissions, pSid1);
1480             }
1481             else
1482             {
1483                 /* FIXME: Call AddAccessDeniedObjectAce */
1484                 DPRINT1("Object ACEs not yet supported!\n");
1485                 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1486                 bRet = FALSE;
1487             }
1488 
1489             if (needToClean) LocalFree((HLOCAL)pSid1);
1490             if (!bRet)
1491             {
1492                 Ret = GetLastError();
1493                 goto Cleanup;
1494             }
1495         }
1496     }
1497 
1498     /* 2b) Existing denied entries */
1499     /* FIXME */
1500 
1501     /* 3a) New allow entries (GRANT_ACCESS, SET_ACCESS) */
1502     for (i = 0; i < cCountOfExplicitEntries; i++)
1503     {
1504         if (pListOfExplicitEntries[i].grfAccessMode == SET_ACCESS ||
1505             pListOfExplicitEntries[i].grfAccessMode == GRANT_ACCESS)
1506         {
1507             /* FIXME: take care of pListOfExplicitEntries[i].grfInheritance */
1508             Ret = AccpGetTrusteeSid(&pListOfExplicitEntries[i].Trustee,
1509                                     &PolicyHandle,
1510                                     &pSid1,
1511                                     &needToClean);
1512             if (Ret != ERROR_SUCCESS)
1513                 goto Cleanup;
1514 
1515             ObjectsPresent = AccpGetTrusteeObjects(&pListOfExplicitEntries[i].Trustee,
1516                                                    &ObjectTypeGuid,
1517                                                    &InheritedObjectTypeGuid);
1518 
1519             if (ObjectsPresent == 0)
1520             {
1521                 /* FIXME: Call AddAccessAllowedAceEx instead! */
1522                 bRet = AddAccessAllowedAce(pNew, ACL_REVISION, pListOfExplicitEntries[i].grfAccessPermissions, pSid1);
1523             }
1524             else
1525             {
1526                 /* FIXME: Call AddAccessAllowedObjectAce */
1527                 DPRINT1("Object ACEs not yet supported!\n");
1528                 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1529                 bRet = FALSE;
1530             }
1531 
1532             if (needToClean) LocalFree((HLOCAL)pSid1);
1533             if (!bRet)
1534             {
1535                 Ret = GetLastError();
1536                 goto Cleanup;
1537             }
1538         }
1539     }
1540 
1541     /* 3b) Existing allow entries */
1542     /* FIXME */
1543 
1544     *NewAcl = pNew;
1545 
1546 Cleanup:
1547     if (pKeepAce && pKeepAce != KeepAceBuf)
1548         LocalFree((HLOCAL)pKeepAce);
1549 
1550     if (pNew && Ret != ERROR_SUCCESS)
1551         LocalFree((HLOCAL)pNew);
1552 
1553     if (PolicyHandle)
1554         LsaClose(PolicyHandle);
1555 
1556     /* restore the last error code */
1557     SetLastError(LastErr);
1558 
1559     return Ret;
1560 }
1561 
1562 
1563 /**********************************************************************
1564  * AccGetInheritanceSource				EXPORTED
1565  *
1566  * @unimplemented
1567  */
1568 DWORD WINAPI
1569 AccGetInheritanceSource(LPWSTR pObjectName,
1570                         SE_OBJECT_TYPE ObjectType,
1571                         SECURITY_INFORMATION SecurityInfo,
1572                         BOOL Container,
1573                         GUID** pObjectClassGuids,
1574                         DWORD GuidCount,
1575                         PACL pAcl,
1576                         PFN_OBJECT_MGR_FUNCTS pfnArray,
1577                         PGENERIC_MAPPING pGenericMapping,
1578                         PINHERITED_FROMW pInheritArray)
1579 {
1580     UNIMPLEMENTED;
1581     return ERROR_CALL_NOT_IMPLEMENTED;
1582 }
1583 
1584 
1585 /**********************************************************************
1586  * AccFreeIndexArray					EXPORTED
1587  *
1588  * @implemented
1589  */
1590 DWORD WINAPI
1591 AccFreeIndexArray(PINHERITED_FROMW pInheritArray,
1592                   USHORT AceCnt,
1593                   PFN_OBJECT_MGR_FUNCTS pfnArray  OPTIONAL)
1594 {
1595     PINHERITED_FROMW pLast;
1596 
1597     UNREFERENCED_PARAMETER(pfnArray);
1598 
1599     pLast = pInheritArray + AceCnt;
1600     while (pInheritArray != pLast)
1601     {
1602         if (pInheritArray->AncestorName != NULL)
1603         {
1604             LocalFree((HLOCAL)pInheritArray->AncestorName);
1605             pInheritArray->AncestorName = NULL;
1606         }
1607 
1608         pInheritArray++;
1609     }
1610 
1611     return ERROR_SUCCESS;
1612 }
1613 
1614 
1615 /**********************************************************************
1616  * AccRewriteGetExplicitEntriesFromAcl			EXPORTED
1617  *
1618  * @implemented
1619  */
1620 DWORD WINAPI
1621 AccRewriteGetExplicitEntriesFromAcl(PACL pacl,
1622                                     PULONG pcCountOfExplicitEntries,
1623                                     PEXPLICIT_ACCESS_W* pListOfExplicitEntries)
1624 {
1625     PACE_HEADER AceHeader;
1626     PSID Sid, SidTarget;
1627     ULONG ObjectAceCount = 0;
1628     POBJECTS_AND_SID ObjSid;
1629     SIZE_T Size;
1630     PEXPLICIT_ACCESS_W peaw;
1631     DWORD LastErr, SidLen;
1632     DWORD AceIndex = 0;
1633     DWORD ErrorCode = ERROR_SUCCESS;
1634 
1635     /* save the last error code */
1636     LastErr = GetLastError();
1637 
1638     if (pacl != NULL)
1639     {
1640         if (pacl->AceCount != 0)
1641         {
1642             Size = (SIZE_T)pacl->AceCount * sizeof(EXPLICIT_ACCESS_W);
1643 
1644             /* calculate the space needed */
1645             while (GetAce(pacl,
1646                           AceIndex,
1647                           (LPVOID*)&AceHeader))
1648             {
1649                 Sid = AccpGetAceSid(AceHeader);
1650                 Size += GetLengthSid(Sid);
1651 
1652                 if (AccpIsObjectAce(AceHeader))
1653                     ObjectAceCount++;
1654 
1655                 AceIndex++;
1656             }
1657 
1658             Size += ObjectAceCount * sizeof(OBJECTS_AND_SID);
1659 
1660             ASSERT(pacl->AceCount == AceIndex);
1661 
1662             /* allocate the array */
1663             peaw = (PEXPLICIT_ACCESS_W)LocalAlloc(LMEM_FIXED,
1664                                                   Size);
1665             if (peaw != NULL)
1666             {
1667                 AceIndex = 0;
1668                 ObjSid = (POBJECTS_AND_SID)(peaw + pacl->AceCount);
1669                 SidTarget = (PSID)(ObjSid + ObjectAceCount);
1670 
1671                 /* initialize the array */
1672                 while (GetAce(pacl,
1673                               AceIndex,
1674                               (LPVOID*)&AceHeader))
1675                 {
1676                     Sid = AccpGetAceSid(AceHeader);
1677                     SidLen = GetLengthSid(Sid);
1678 
1679                     peaw[AceIndex].grfAccessPermissions = AccpGetAceAccessMask(AceHeader);
1680                     peaw[AceIndex].grfAccessMode = AccpGetAceAccessMode(AceHeader);
1681                     peaw[AceIndex].grfInheritance = AceHeader->AceFlags & VALID_INHERIT_FLAGS;
1682 
1683                     if (CopySid(SidLen,
1684                                 SidTarget,
1685                                 Sid))
1686                     {
1687                         if (AccpIsObjectAce(AceHeader))
1688                         {
1689                             BuildTrusteeWithObjectsAndSid(&peaw[AceIndex].Trustee,
1690                                                           ObjSid++,
1691                                                           AccpGetObjectAceObjectType(AceHeader),
1692                                                           AccpGetObjectAceInheritedObjectType(AceHeader),
1693                                                           SidTarget);
1694                         }
1695                         else
1696                         {
1697                             BuildTrusteeWithSid(&peaw[AceIndex].Trustee,
1698                                                 SidTarget);
1699                         }
1700 
1701                         SidTarget = (PSID)((ULONG_PTR)SidTarget + SidLen);
1702                     }
1703                     else
1704                     {
1705                         /* copying the SID failed, treat it as an fatal error... */
1706                         ErrorCode = GetLastError();
1707 
1708                         /* free allocated resources */
1709                         LocalFree(peaw);
1710                         peaw = NULL;
1711                         AceIndex = 0;
1712                         break;
1713                     }
1714 
1715                     AceIndex++;
1716                 }
1717 
1718                 *pcCountOfExplicitEntries = AceIndex;
1719                 *pListOfExplicitEntries = peaw;
1720             }
1721             else
1722                 ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1723         }
1724         else
1725         {
1726             goto EmptyACL;
1727         }
1728     }
1729     else
1730     {
1731 EmptyACL:
1732         *pcCountOfExplicitEntries = 0;
1733         *pListOfExplicitEntries = NULL;
1734     }
1735 
1736     /* restore the last error code */
1737     SetLastError(LastErr);
1738 
1739     return ErrorCode;
1740 }
1741 
1742 
1743 /**********************************************************************
1744  * AccTreeResetNamedSecurityInfo			EXPORTED
1745  *
1746  * @unimplemented
1747  */
1748 DWORD WINAPI
1749 AccTreeResetNamedSecurityInfo(LPWSTR pObjectName,
1750                               SE_OBJECT_TYPE ObjectType,
1751                               SECURITY_INFORMATION SecurityInfo,
1752                               PSID pOwner,
1753                               PSID pGroup,
1754                               PACL pDacl,
1755                               PACL pSacl,
1756                               BOOL KeepExplicit,
1757                               FN_PROGRESSW fnProgress,
1758                               PROG_INVOKE_SETTING ProgressInvokeSetting,
1759                               PVOID Args)
1760 {
1761     UNIMPLEMENTED;
1762     return ERROR_CALL_NOT_IMPLEMENTED;
1763 }
1764 
1765 
1766 BOOL WINAPI
1767 DllMain(IN HINSTANCE hinstDLL,
1768         IN DWORD dwReason,
1769         IN LPVOID lpvReserved)
1770 {
1771     switch (dwReason)
1772     {
1773         case DLL_PROCESS_ATTACH:
1774             hDllInstance = hinstDLL;
1775             DisableThreadLibraryCalls(hinstDLL);
1776             break;
1777 
1778         case DLL_PROCESS_DETACH:
1779             break;
1780     }
1781     return TRUE;
1782 }
1783 
1784