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