xref: /reactos/dll/win32/advapi32/sec/misc.c (revision 03422451)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * WINE COPYRIGHT:
4  * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net>
5  * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
6  * Copyright 2006 Robert Reif
7  *
8  * PROJECT:         ReactOS system libraries
9  * FILE:            dll/win32/advapi32/sec/misc.c
10  * PURPOSE:         Miscellaneous security functions (some ported from Wine)
11  */
12 
13 #include <advapi32.h>
14 
15 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
16 
17 /* Interface to ntmarta.dll ***************************************************/
18 
19 NTMARTA NtMartaStatic = { 0 };
20 static PNTMARTA NtMarta = NULL;
21 
22 #define FindNtMartaProc(Name)                                                  \
23     NtMartaStatic.Name = (PVOID)GetProcAddress(NtMartaStatic.hDllInstance,     \
24                                                "Acc" # Name );                 \
25     if (NtMartaStatic.Name == NULL)                                            \
26     {                                                                          \
27         return GetLastError();                                                 \
28     }
29 
30 
31 static DWORD
LoadAndInitializeNtMarta(VOID)32 LoadAndInitializeNtMarta(VOID)
33 {
34     /* this code may be executed simultaneously by multiple threads in case they're
35        trying to initialize the interface at the same time, but that's no problem
36        because the pointers returned by GetProcAddress will be the same. However,
37        only one of the threads will change the NtMarta pointer to the NtMartaStatic
38        structure, the others threads will detect that there were other threads
39        initializing the structure faster and will release the reference to the
40        DLL */
41 
42     NtMartaStatic.hDllInstance = LoadLibraryW(L"ntmarta.dll");
43     if (NtMartaStatic.hDllInstance == NULL)
44     {
45         return GetLastError();
46     }
47 
48 #if 0
49     FindNtMartaProc(LookupAccountTrustee);
50     FindNtMartaProc(LookupAccountName);
51     FindNtMartaProc(LookupAccountSid);
52     FindNtMartaProc(SetEntriesInAList);
53     FindNtMartaProc(ConvertAccessToSecurityDescriptor);
54     FindNtMartaProc(ConvertSDToAccess);
55     FindNtMartaProc(ConvertAclToAccess);
56     FindNtMartaProc(GetAccessForTrustee);
57     FindNtMartaProc(GetExplicitEntries);
58 #endif
59     FindNtMartaProc(RewriteGetNamedRights);
60     FindNtMartaProc(RewriteSetNamedRights);
61     FindNtMartaProc(RewriteGetHandleRights);
62     FindNtMartaProc(RewriteSetHandleRights);
63     FindNtMartaProc(RewriteSetEntriesInAcl);
64     FindNtMartaProc(RewriteGetExplicitEntriesFromAcl);
65     FindNtMartaProc(TreeResetNamedSecurityInfo);
66     FindNtMartaProc(GetInheritanceSource);
67     FindNtMartaProc(FreeIndexArray);
68 
69     return ERROR_SUCCESS;
70 }
71 
72 
73 DWORD
CheckNtMartaPresent(VOID)74 CheckNtMartaPresent(VOID)
75 {
76     DWORD ErrorCode;
77 
78     if (InterlockedCompareExchangePointer((PVOID)&NtMarta,
79                                           NULL,
80                                           NULL) == NULL)
81     {
82         /* we're the first one trying to use ntmarta, initialize it and change
83            the pointer after initialization */
84         ErrorCode = LoadAndInitializeNtMarta();
85 
86         if (ErrorCode == ERROR_SUCCESS)
87         {
88             /* try change the NtMarta pointer */
89             if (InterlockedCompareExchangePointer((PVOID)&NtMarta,
90                                                   &NtMartaStatic,
91                                                   NULL) != NULL)
92             {
93                 /* another thread initialized ntmarta in the meanwhile, release
94                    the reference of the dll loaded. */
95                 FreeLibrary(NtMartaStatic.hDllInstance);
96             }
97         }
98 #if DBG
99         else
100         {
101             ERR("Failed to initialize ntmarta.dll! Error: 0x%x\n", ErrorCode);
102         }
103 #endif
104     }
105     else
106     {
107         /* ntmarta was already initialized */
108         ErrorCode = ERROR_SUCCESS;
109     }
110 
111     return ErrorCode;
112 }
113 
114 
115 VOID
UnloadNtMarta(VOID)116 UnloadNtMarta(VOID)
117 {
118     if (InterlockedExchangePointer((PVOID)&NtMarta,
119                                    NULL) != NULL)
120     {
121         FreeLibrary(NtMartaStatic.hDllInstance);
122     }
123 }
124 
125 
126 /******************************************************************************/
127 
128 /*
129  * @implemented
130  */
131 BOOL
132 WINAPI
ImpersonateAnonymousToken(IN HANDLE ThreadHandle)133 ImpersonateAnonymousToken(IN HANDLE ThreadHandle)
134 {
135     NTSTATUS Status;
136 
137     Status = NtImpersonateAnonymousToken(ThreadHandle);
138     if (!NT_SUCCESS(Status))
139     {
140         SetLastError(RtlNtStatusToDosError(Status));
141         return FALSE;
142     }
143 
144     return TRUE;
145 }
146 
147 /*
148  * @implemented
149  */
150 BOOL
151 WINAPI
ImpersonateLoggedOnUser(HANDLE hToken)152 ImpersonateLoggedOnUser(HANDLE hToken)
153 {
154     SECURITY_QUALITY_OF_SERVICE Qos;
155     OBJECT_ATTRIBUTES ObjectAttributes;
156     HANDLE NewToken;
157     TOKEN_TYPE Type;
158     ULONG ReturnLength;
159     BOOL Duplicated;
160     NTSTATUS Status;
161 
162     /* Get the token type */
163     Status = NtQueryInformationToken(hToken,
164                                      TokenType,
165                                      &Type,
166                                      sizeof(TOKEN_TYPE),
167                                      &ReturnLength);
168     if (!NT_SUCCESS(Status))
169     {
170         SetLastError(RtlNtStatusToDosError(Status));
171         return FALSE;
172     }
173 
174     if (Type == TokenPrimary)
175     {
176         /* Create a duplicate impersonation token */
177         Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
178         Qos.ImpersonationLevel = SecurityImpersonation;
179         Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
180         Qos.EffectiveOnly = FALSE;
181 
182         ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
183         ObjectAttributes.RootDirectory = NULL;
184         ObjectAttributes.ObjectName = NULL;
185         ObjectAttributes.Attributes = 0;
186         ObjectAttributes.SecurityDescriptor = NULL;
187         ObjectAttributes.SecurityQualityOfService = &Qos;
188 
189         Status = NtDuplicateToken(hToken,
190                                   TOKEN_IMPERSONATE | TOKEN_QUERY,
191                                   &ObjectAttributes,
192                                   FALSE,
193                                   TokenImpersonation,
194                                   &NewToken);
195         if (!NT_SUCCESS(Status))
196         {
197             ERR("NtDuplicateToken failed: Status %08x\n", Status);
198             SetLastError(RtlNtStatusToDosError(Status));
199             return FALSE;
200         }
201 
202         Duplicated = TRUE;
203     }
204     else
205     {
206         /* User the original impersonation token */
207         NewToken = hToken;
208         Duplicated = FALSE;
209     }
210 
211     /* Impersonate the the current thread */
212     Status = NtSetInformationThread(NtCurrentThread(),
213                                     ThreadImpersonationToken,
214                                     &NewToken,
215                                     sizeof(HANDLE));
216 
217     if (Duplicated != FALSE)
218     {
219         NtClose(NewToken);
220     }
221 
222     if (!NT_SUCCESS(Status))
223     {
224         ERR("NtSetInformationThread failed: Status %08x\n", Status);
225         SetLastError(RtlNtStatusToDosError(Status));
226         return FALSE;
227     }
228 
229     return TRUE;
230 }
231 
232 /******************************************************************************
233  * GetUserNameA [ADVAPI32.@]
234  *
235  * Get the current user name.
236  *
237  * PARAMS
238  *  lpszName [O]   Destination for the user name.
239  *  lpSize   [I/O] Size of lpszName.
240  *
241  *
242  * @implemented
243  */
244 BOOL
245 WINAPI
GetUserNameA(LPSTR lpszName,LPDWORD lpSize)246 GetUserNameA(LPSTR lpszName,
247              LPDWORD lpSize)
248 {
249     UNICODE_STRING NameW;
250     ANSI_STRING NameA;
251     BOOL Ret;
252 
253     /* apparently Win doesn't check whether lpSize is valid at all! */
254 
255     NameW.MaximumLength = (*lpSize) * sizeof(WCHAR);
256     NameW.Buffer = LocalAlloc(LMEM_FIXED, NameW.MaximumLength);
257     if(NameW.Buffer == NULL)
258     {
259         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
260         return FALSE;
261     }
262 
263     NameA.Length = 0;
264     NameA.MaximumLength = ((*lpSize) < 0xFFFF ? (USHORT)(*lpSize) : 0xFFFF);
265     NameA.Buffer = lpszName;
266 
267     Ret = GetUserNameW(NameW.Buffer,
268                        lpSize);
269     if(Ret)
270     {
271         NameW.Length = (*lpSize - 1) * sizeof(WCHAR);
272         RtlUnicodeStringToAnsiString(&NameA, &NameW, FALSE);
273 
274         *lpSize = NameA.Length + 1;
275     }
276 
277     LocalFree(NameW.Buffer);
278 
279     return Ret;
280 }
281 
282 /******************************************************************************
283  * GetUserNameW [ADVAPI32.@]
284  *
285  * See GetUserNameA.
286  *
287  * @implemented
288  */
289 BOOL
290 WINAPI
GetUserNameW(LPWSTR lpszName,LPDWORD lpSize)291 GetUserNameW(LPWSTR lpszName,
292              LPDWORD lpSize)
293 {
294     HANDLE hToken = INVALID_HANDLE_VALUE;
295     DWORD tu_len = 0;
296     char* tu_buf = NULL;
297     TOKEN_USER* token_user = NULL;
298     DWORD an_len = 0;
299     SID_NAME_USE snu = SidTypeUser;
300     WCHAR* domain_name = NULL;
301     DWORD dn_len = 0;
302 
303     if (!OpenThreadToken (GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken))
304     {
305         DWORD dwLastError = GetLastError();
306         if (dwLastError != ERROR_NO_TOKEN
307             && dwLastError != ERROR_NO_IMPERSONATION_TOKEN)
308         {
309             /* don't call SetLastError(),
310                as OpenThreadToken() ought to have set one */
311             return FALSE;
312         }
313 
314         if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
315         {
316             /* don't call SetLastError(),
317                as OpenProcessToken() ought to have set one */
318             return FALSE;
319         }
320     }
321 
322     tu_buf = LocalAlloc(LMEM_FIXED, 36);
323     if (!tu_buf)
324     {
325         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
326         CloseHandle(hToken);
327         return FALSE;
328     }
329 
330     if (!GetTokenInformation(hToken, TokenUser, tu_buf, 36, &tu_len) || tu_len > 36)
331     {
332         LocalFree(tu_buf);
333         tu_buf = LocalAlloc(LMEM_FIXED, tu_len);
334         if (!tu_buf)
335         {
336             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
337             CloseHandle(hToken);
338             return FALSE;
339         }
340 
341         if (!GetTokenInformation(hToken, TokenUser, tu_buf, tu_len, &tu_len))
342         {
343             /* don't call SetLastError(),
344                as GetTokenInformation() ought to have set one */
345             LocalFree(tu_buf);
346             CloseHandle(hToken);
347             return FALSE;
348         }
349     }
350 
351     CloseHandle(hToken);
352     token_user = (TOKEN_USER*)tu_buf;
353 
354     an_len = *lpSize;
355     dn_len = 32;
356     domain_name = LocalAlloc(LMEM_FIXED, dn_len * sizeof(WCHAR));
357     if (!domain_name)
358     {
359         LocalFree(tu_buf);
360         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
361         return FALSE;
362     }
363 
364     if (!LookupAccountSidW(NULL, token_user->User.Sid, lpszName, &an_len, domain_name, &dn_len, &snu)
365         || dn_len > 32)
366     {
367         if (dn_len > 32)
368         {
369             LocalFree(domain_name);
370             domain_name = LocalAlloc(LMEM_FIXED, dn_len * sizeof(WCHAR));
371             if (!domain_name)
372             {
373                 LocalFree(tu_buf);
374                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
375                 return FALSE;
376             }
377         }
378 
379         an_len = *lpSize;
380         if (!LookupAccountSidW(NULL, token_user->User.Sid, lpszName, &an_len, domain_name, &dn_len, &snu))
381         {
382             /* don't call SetLastError(),
383                as LookupAccountSid() ought to have set one */
384             LocalFree(domain_name);
385             LocalFree(tu_buf);
386             *lpSize = an_len;
387             return FALSE;
388         }
389     }
390 
391     LocalFree(domain_name);
392     LocalFree(tu_buf);
393     *lpSize = an_len + 1;
394     return TRUE;
395 }
396 
397 
398 /******************************************************************************
399  * LookupAccountSidA [ADVAPI32.@]
400  *
401  * @implemented
402  */
403 BOOL
404 WINAPI
LookupAccountSidA(LPCSTR lpSystemName,PSID lpSid,LPSTR lpName,LPDWORD cchName,LPSTR lpReferencedDomainName,LPDWORD cchReferencedDomainName,PSID_NAME_USE peUse)405 LookupAccountSidA(LPCSTR lpSystemName,
406                   PSID lpSid,
407                   LPSTR lpName,
408                   LPDWORD cchName,
409                   LPSTR lpReferencedDomainName,
410                   LPDWORD cchReferencedDomainName,
411                   PSID_NAME_USE peUse)
412 {
413     UNICODE_STRING NameW, ReferencedDomainNameW, SystemNameW;
414     LPWSTR NameBuffer = NULL;
415     LPWSTR ReferencedDomainNameBuffer = NULL;
416     DWORD dwName, dwReferencedDomainName;
417     BOOL Ret;
418 
419     /*
420      * save the buffer sizes the caller passed to us, as they may get modified and
421      * we require the original values when converting back to ansi
422      */
423     dwName = *cchName;
424     dwReferencedDomainName = *cchReferencedDomainName;
425 
426     /* allocate buffers for the unicode strings to receive */
427     if (dwName > 0)
428     {
429         NameBuffer = LocalAlloc(LMEM_FIXED, dwName * sizeof(WCHAR));
430         if (NameBuffer == NULL)
431         {
432             SetLastError(ERROR_OUTOFMEMORY);
433             return FALSE;
434         }
435     }
436     else
437         NameBuffer = NULL;
438 
439     if (dwReferencedDomainName > 0)
440     {
441         ReferencedDomainNameBuffer = LocalAlloc(LMEM_FIXED, dwReferencedDomainName * sizeof(WCHAR));
442         if (ReferencedDomainNameBuffer == NULL)
443         {
444             if (dwName > 0)
445             {
446                 LocalFree(NameBuffer);
447             }
448 
449             SetLastError(ERROR_OUTOFMEMORY);
450             return FALSE;
451         }
452     }
453     else
454         ReferencedDomainNameBuffer = NULL;
455 
456 
457     /* convert the system name to unicode - if present */
458     if (lpSystemName != NULL)
459     {
460         ANSI_STRING SystemNameA;
461 
462         RtlInitAnsiString(&SystemNameA, lpSystemName);
463         RtlAnsiStringToUnicodeString(&SystemNameW, &SystemNameA, TRUE);
464     }
465     else
466         SystemNameW.Buffer = NULL;
467 
468     /* it's time to call the unicode version */
469     Ret = LookupAccountSidW(SystemNameW.Buffer,
470                             lpSid,
471                             NameBuffer,
472                             cchName,
473                             ReferencedDomainNameBuffer,
474                             cchReferencedDomainName,
475                             peUse);
476     if (Ret)
477     {
478         /*
479          * convert unicode strings back to ansi, don't forget that we can't convert
480          * more than 0xFFFF (USHORT) characters! Also don't forget to explicitly
481          * terminate the converted string, the Rtl functions don't do that!
482          */
483         if (lpName != NULL)
484         {
485             ANSI_STRING NameA;
486 
487             NameA.Length = 0;
488             NameA.MaximumLength = ((dwName <= 0xFFFF) ? (USHORT)dwName : 0xFFFF);
489             NameA.Buffer = lpName;
490 
491             RtlInitUnicodeString(&NameW, NameBuffer);
492             RtlUnicodeStringToAnsiString(&NameA, &NameW, FALSE);
493             NameA.Buffer[NameA.Length] = '\0';
494         }
495 
496         if (lpReferencedDomainName != NULL)
497         {
498             ANSI_STRING ReferencedDomainNameA;
499 
500             ReferencedDomainNameA.Length = 0;
501             ReferencedDomainNameA.MaximumLength = ((dwReferencedDomainName <= 0xFFFF) ?
502                                                    (USHORT)dwReferencedDomainName : 0xFFFF);
503             ReferencedDomainNameA.Buffer = lpReferencedDomainName;
504 
505             RtlInitUnicodeString(&ReferencedDomainNameW, ReferencedDomainNameBuffer);
506             RtlUnicodeStringToAnsiString(&ReferencedDomainNameA, &ReferencedDomainNameW, FALSE);
507             ReferencedDomainNameA.Buffer[ReferencedDomainNameA.Length] = '\0';
508         }
509     }
510 
511     /* free previously allocated buffers */
512     if (SystemNameW.Buffer != NULL)
513     {
514         RtlFreeUnicodeString(&SystemNameW);
515     }
516 
517     if (NameBuffer != NULL)
518     {
519         LocalFree(NameBuffer);
520     }
521 
522     if (ReferencedDomainNameBuffer != NULL)
523     {
524         LocalFree(ReferencedDomainNameBuffer);
525     }
526 
527     return Ret;
528 }
529 
530 
531 /******************************************************************************
532  * LookupAccountSidW [ADVAPI32.@]
533  *
534  * @implemented
535  */
536 BOOL WINAPI
LookupAccountSidW(LPCWSTR pSystemName,PSID pSid,LPWSTR pAccountName,LPDWORD pdwAccountName,LPWSTR pDomainName,LPDWORD pdwDomainName,PSID_NAME_USE peUse)537 LookupAccountSidW(LPCWSTR pSystemName,
538                   PSID pSid,
539                   LPWSTR pAccountName,
540                   LPDWORD pdwAccountName,
541                   LPWSTR pDomainName,
542                   LPDWORD pdwDomainName,
543                   PSID_NAME_USE peUse)
544 {
545     LSA_UNICODE_STRING SystemName;
546     LSA_OBJECT_ATTRIBUTES ObjectAttributes = {0};
547     LSA_HANDLE PolicyHandle = NULL;
548     NTSTATUS Status;
549     PLSA_REFERENCED_DOMAIN_LIST ReferencedDomain = NULL;
550     PLSA_TRANSLATED_NAME TranslatedName = NULL;
551     BOOL ret;
552     DWORD dwAccountName, dwDomainName;
553 
554     RtlInitUnicodeString(&SystemName, pSystemName);
555     Status = LsaOpenPolicy(&SystemName, &ObjectAttributes, POLICY_LOOKUP_NAMES, &PolicyHandle);
556     if (!NT_SUCCESS(Status))
557     {
558         SetLastError(LsaNtStatusToWinError(Status));
559         return FALSE;
560     }
561 
562     Status = LsaLookupSids(PolicyHandle, 1, &pSid, &ReferencedDomain, &TranslatedName);
563 
564     LsaClose(PolicyHandle);
565 
566     if (!NT_SUCCESS(Status) || Status == STATUS_SOME_NOT_MAPPED)
567     {
568         SetLastError(LsaNtStatusToWinError(Status));
569         ret = FALSE;
570     }
571     else
572     {
573         ret = TRUE;
574 
575         dwAccountName = TranslatedName->Name.Length / sizeof(WCHAR);
576         if (ReferencedDomain && ReferencedDomain->Entries > 0)
577             dwDomainName = ReferencedDomain->Domains[0].Name.Length / sizeof(WCHAR);
578         else
579             dwDomainName = 0;
580 
581         if (*pdwAccountName <= dwAccountName || *pdwDomainName <= dwDomainName)
582         {
583             /* One or two buffers are insufficient, add up a char for NULL termination */
584             *pdwAccountName = dwAccountName + 1;
585             *pdwDomainName = dwDomainName + 1;
586             ret = FALSE;
587         }
588         else
589         {
590             /* Lengths are sufficient, copy the data */
591             if (dwAccountName)
592                 RtlCopyMemory(pAccountName, TranslatedName->Name.Buffer, dwAccountName * sizeof(WCHAR));
593             pAccountName[dwAccountName] = L'\0';
594 
595             if (dwDomainName)
596                 RtlCopyMemory(pDomainName, ReferencedDomain->Domains[0].Name.Buffer, dwDomainName * sizeof(WCHAR));
597             pDomainName[dwDomainName] = L'\0';
598 
599             *pdwAccountName = dwAccountName;
600             *pdwDomainName = dwDomainName;
601 
602             if (peUse)
603                 *peUse = TranslatedName->Use;
604         }
605 
606         if (!ret)
607             SetLastError(ERROR_INSUFFICIENT_BUFFER);
608     }
609 
610     if (ReferencedDomain)
611         LsaFreeMemory(ReferencedDomain);
612 
613     if (TranslatedName)
614         LsaFreeMemory(TranslatedName);
615 
616     return ret;
617 }
618 
619 /******************************************************************************
620  * LookupAccountNameW [ADVAPI32.@]
621  *
622  * @implemented
623  */
624 BOOL
625 WINAPI
LookupAccountNameW(LPCWSTR lpSystemName,LPCWSTR lpAccountName,PSID Sid,LPDWORD cbSid,LPWSTR ReferencedDomainName,LPDWORD cchReferencedDomainName,PSID_NAME_USE peUse)626 LookupAccountNameW(LPCWSTR lpSystemName,
627                    LPCWSTR lpAccountName,
628                    PSID Sid,
629                    LPDWORD cbSid,
630                    LPWSTR ReferencedDomainName,
631                    LPDWORD cchReferencedDomainName,
632                    PSID_NAME_USE peUse)
633 {
634     OBJECT_ATTRIBUTES ObjectAttributes = {0};
635     UNICODE_STRING SystemName;
636     UNICODE_STRING AccountName;
637     LSA_HANDLE PolicyHandle = NULL;
638     PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains = NULL;
639     PLSA_TRANSLATED_SID TranslatedSid = NULL;
640     PSID pDomainSid;
641     DWORD dwDomainNameLength;
642     DWORD dwSidLength;
643     UCHAR nSubAuthorities;
644     BOOL bResult;
645     NTSTATUS Status;
646 
647     TRACE("%s %s %p %p %p %p %p\n", lpSystemName, lpAccountName,
648           Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse);
649 
650     RtlInitUnicodeString(&SystemName,
651                          lpSystemName);
652 
653     Status = LsaOpenPolicy(lpSystemName ? &SystemName : NULL,
654                            &ObjectAttributes,
655                            POLICY_LOOKUP_NAMES,
656                            &PolicyHandle);
657     if (!NT_SUCCESS(Status))
658     {
659         SetLastError(LsaNtStatusToWinError(Status));
660         return FALSE;
661     }
662 
663     RtlInitUnicodeString(&AccountName,
664                          lpAccountName);
665 
666     Status = LsaLookupNames(PolicyHandle,
667                             1,
668                             &AccountName,
669                             &ReferencedDomains,
670                             &TranslatedSid);
671 
672     LsaClose(PolicyHandle);
673 
674     if (!NT_SUCCESS(Status) || Status == STATUS_SOME_NOT_MAPPED)
675     {
676         SetLastError(LsaNtStatusToWinError(Status));
677         bResult = FALSE;
678     }
679     else
680     {
681         pDomainSid = ReferencedDomains->Domains[TranslatedSid->DomainIndex].Sid;
682         nSubAuthorities = *GetSidSubAuthorityCount(pDomainSid);
683         dwSidLength = GetSidLengthRequired(nSubAuthorities + 1);
684 
685         dwDomainNameLength = ReferencedDomains->Domains->Name.Length / sizeof(WCHAR);
686 
687         if (*cbSid < dwSidLength ||
688             *cchReferencedDomainName < dwDomainNameLength + 1)
689         {
690             *cbSid = dwSidLength;
691             *cchReferencedDomainName = dwDomainNameLength + 1;
692 
693             bResult = FALSE;
694         }
695         else
696         {
697             CopySid(*cbSid, Sid, pDomainSid);
698             *GetSidSubAuthorityCount(Sid) = nSubAuthorities + 1;
699             *GetSidSubAuthority(Sid, (DWORD)nSubAuthorities) = TranslatedSid->RelativeId;
700 
701             RtlCopyMemory(ReferencedDomainName, ReferencedDomains->Domains->Name.Buffer, dwDomainNameLength * sizeof(WCHAR));
702             ReferencedDomainName[dwDomainNameLength] = L'\0';
703 
704             *cchReferencedDomainName = dwDomainNameLength;
705 
706             *peUse = TranslatedSid->Use;
707 
708             bResult = TRUE;
709         }
710 
711         if (bResult == FALSE)
712             SetLastError(ERROR_INSUFFICIENT_BUFFER);
713     }
714 
715     if (ReferencedDomains != NULL)
716         LsaFreeMemory(ReferencedDomains);
717 
718     if (TranslatedSid != NULL)
719         LsaFreeMemory(TranslatedSid);
720 
721     return bResult;
722 }
723 
724 
725 /**********************************************************************
726  * LookupPrivilegeValueA				EXPORTED
727  *
728  * @implemented
729  */
730 BOOL
731 WINAPI
LookupPrivilegeValueA(LPCSTR lpSystemName,LPCSTR lpName,PLUID lpLuid)732 LookupPrivilegeValueA(LPCSTR lpSystemName,
733                       LPCSTR lpName,
734                       PLUID lpLuid)
735 {
736     UNICODE_STRING SystemName;
737     UNICODE_STRING Name;
738     BOOL Result;
739 
740     /* Remote system? */
741     if (lpSystemName != NULL)
742     {
743         RtlCreateUnicodeStringFromAsciiz(&SystemName,
744                                          (LPSTR)lpSystemName);
745     }
746     else
747         SystemName.Buffer = NULL;
748 
749     /* Check the privilege name is not NULL */
750     if (lpName == NULL)
751     {
752         SetLastError(ERROR_NO_SUCH_PRIVILEGE);
753         return FALSE;
754     }
755 
756     RtlCreateUnicodeStringFromAsciiz(&Name,
757                                      (LPSTR)lpName);
758 
759     Result = LookupPrivilegeValueW(SystemName.Buffer,
760                                    Name.Buffer,
761                                    lpLuid);
762 
763     RtlFreeUnicodeString(&Name);
764 
765     /* Remote system? */
766     if (SystemName.Buffer != NULL)
767     {
768         RtlFreeUnicodeString(&SystemName);
769     }
770 
771     return Result;
772 }
773 
774 
775 /**********************************************************************
776  * LookupPrivilegeValueW
777  *
778  * @implemented
779  */
780 BOOL
781 WINAPI
LookupPrivilegeValueW(LPCWSTR lpSystemName,LPCWSTR lpPrivilegeName,PLUID lpLuid)782 LookupPrivilegeValueW(LPCWSTR lpSystemName,
783                       LPCWSTR lpPrivilegeName,
784                       PLUID lpLuid)
785 {
786     OBJECT_ATTRIBUTES ObjectAttributes = {0};
787     UNICODE_STRING SystemName;
788     UNICODE_STRING PrivilegeName;
789     LSA_HANDLE PolicyHandle = NULL;
790     NTSTATUS Status;
791 
792     TRACE("%S,%S,%p\n", lpSystemName, lpPrivilegeName, lpLuid);
793 
794     RtlInitUnicodeString(&SystemName,
795                          lpSystemName);
796 
797     Status = LsaOpenPolicy(lpSystemName ? &SystemName : NULL,
798                            &ObjectAttributes,
799                            POLICY_LOOKUP_NAMES,
800                            &PolicyHandle);
801     if (!NT_SUCCESS(Status))
802     {
803         SetLastError(LsaNtStatusToWinError(Status));
804         return FALSE;
805     }
806 
807     RtlInitUnicodeString(&PrivilegeName,
808                          lpPrivilegeName);
809 
810     Status = LsaLookupPrivilegeValue(PolicyHandle,
811                                      &PrivilegeName,
812                                      lpLuid);
813 
814     LsaClose(PolicyHandle);
815 
816     if (!NT_SUCCESS(Status))
817     {
818         SetLastError(LsaNtStatusToWinError(Status));
819         return FALSE;
820     }
821 
822     return TRUE;
823 }
824 
825 /**********************************************************************
826  * LookupPrivilegeNameW				EXPORTED
827  *
828  * @implemented
829  */
830 BOOL
831 WINAPI
LookupPrivilegeNameW(LPCWSTR lpSystemName,PLUID lpLuid,LPWSTR lpName,LPDWORD cchName)832 LookupPrivilegeNameW(LPCWSTR lpSystemName,
833                      PLUID lpLuid,
834                      LPWSTR lpName,
835                      LPDWORD cchName)
836 {
837     OBJECT_ATTRIBUTES ObjectAttributes = {0};
838     UNICODE_STRING SystemName;
839     PUNICODE_STRING PrivilegeName = NULL;
840     LSA_HANDLE PolicyHandle = NULL;
841     NTSTATUS Status;
842 
843     TRACE("%S,%p,%p,%p\n", lpSystemName, lpLuid, lpName, cchName);
844 
845     RtlInitUnicodeString(&SystemName,
846                          lpSystemName);
847 
848     Status = LsaOpenPolicy(lpSystemName ? &SystemName : NULL,
849                            &ObjectAttributes,
850                            POLICY_LOOKUP_NAMES,
851                            &PolicyHandle);
852     if (!NT_SUCCESS(Status))
853     {
854         SetLastError(LsaNtStatusToWinError(Status));
855         return FALSE;
856     }
857 
858     Status = LsaLookupPrivilegeName(PolicyHandle,
859                                     lpLuid,
860                                     &PrivilegeName);
861     if (NT_SUCCESS(Status))
862     {
863         if (PrivilegeName->Length + sizeof(WCHAR) > *cchName * sizeof(WCHAR))
864         {
865             Status = STATUS_BUFFER_TOO_SMALL;
866 
867             *cchName = (PrivilegeName->Length + sizeof(WCHAR)) / sizeof(WCHAR);
868         }
869         else
870         {
871             RtlMoveMemory(lpName,
872                           PrivilegeName->Buffer,
873                           PrivilegeName->Length);
874             lpName[PrivilegeName->Length / sizeof(WCHAR)] = 0;
875 
876             *cchName = PrivilegeName->Length / sizeof(WCHAR);
877         }
878 
879         LsaFreeMemory(PrivilegeName->Buffer);
880         LsaFreeMemory(PrivilegeName);
881     }
882 
883     LsaClose(PolicyHandle);
884 
885     if (!NT_SUCCESS(Status))
886     {
887         SetLastError(LsaNtStatusToWinError(Status));
888         return FALSE;
889     }
890 
891     return TRUE;
892 }
893 
894 /**********************************************************************
895  * LookupPrivilegeDisplayNameW			EXPORTED
896  *
897  * @unimplemented
898  */
899 BOOL
900 WINAPI
LookupPrivilegeDisplayNameW(LPCWSTR lpSystemName,LPCWSTR lpName,LPWSTR lpDisplayName,LPDWORD cchDisplayName,LPDWORD lpLanguageId)901 LookupPrivilegeDisplayNameW(LPCWSTR lpSystemName,
902                             LPCWSTR lpName,
903                             LPWSTR lpDisplayName,
904                             LPDWORD cchDisplayName,
905                             LPDWORD lpLanguageId)
906 {
907     OBJECT_ATTRIBUTES ObjectAttributes = {0};
908     UNICODE_STRING SystemName, Name;
909     PUNICODE_STRING DisplayName;
910     LSA_HANDLE PolicyHandle = NULL;
911     USHORT LanguageId;
912     NTSTATUS Status;
913 
914     TRACE("%S,%S,%p,%p,%p\n", lpSystemName, lpName, lpDisplayName, cchDisplayName, lpLanguageId);
915 
916     RtlInitUnicodeString(&SystemName, lpSystemName);
917     RtlInitUnicodeString(&Name, lpName);
918 
919     Status = LsaOpenPolicy(lpSystemName ? &SystemName : NULL,
920                            &ObjectAttributes,
921                            POLICY_LOOKUP_NAMES,
922                            &PolicyHandle);
923     if (!NT_SUCCESS(Status))
924     {
925         SetLastError(LsaNtStatusToWinError(Status));
926         return FALSE;
927     }
928 
929     Status = LsaLookupPrivilegeDisplayName(PolicyHandle, &Name, &DisplayName, &LanguageId);
930     if (NT_SUCCESS(Status))
931     {
932         *lpLanguageId = LanguageId;
933         if (DisplayName->Length + sizeof(WCHAR) > *cchDisplayName * sizeof(WCHAR))
934         {
935             Status = STATUS_BUFFER_TOO_SMALL;
936 
937             *cchDisplayName = (DisplayName->Length + sizeof(WCHAR)) / sizeof(WCHAR);
938         }
939         else
940         {
941             RtlMoveMemory(lpDisplayName,
942                           DisplayName->Buffer,
943                           DisplayName->Length);
944             lpDisplayName[DisplayName->Length / sizeof(WCHAR)] = 0;
945 
946             *cchDisplayName = DisplayName->Length / sizeof(WCHAR);
947         }
948 
949         LsaFreeMemory(DisplayName->Buffer);
950         LsaFreeMemory(DisplayName);
951     }
952 
953     LsaClose(PolicyHandle);
954 
955     if (!NT_SUCCESS(Status))
956     {
957         SetLastError(LsaNtStatusToWinError(Status));
958         return FALSE;
959     }
960 
961     return TRUE;
962 }
963 
964 static DWORD
pGetSecurityInfoCheck(SECURITY_INFORMATION SecurityInfo,PSID * ppsidOwner,PSID * ppsidGroup,PACL * ppDacl,PACL * ppSacl,PSECURITY_DESCRIPTOR * ppSecurityDescriptor)965 pGetSecurityInfoCheck(SECURITY_INFORMATION SecurityInfo,
966                       PSID *ppsidOwner,
967                       PSID *ppsidGroup,
968                       PACL *ppDacl,
969                       PACL *ppSacl,
970                       PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
971 {
972     if ((SecurityInfo & (OWNER_SECURITY_INFORMATION |
973                          GROUP_SECURITY_INFORMATION |
974                          DACL_SECURITY_INFORMATION |
975                          SACL_SECURITY_INFORMATION)) &&
976         ppSecurityDescriptor == NULL)
977     {
978         /* if one of the SIDs or ACLs are present, the security descriptor
979            most not be NULL */
980         return ERROR_INVALID_PARAMETER;
981     }
982     else
983     {
984         /* reset the pointers unless they're ignored */
985         if ((SecurityInfo & OWNER_SECURITY_INFORMATION) &&
986             ppsidOwner != NULL)
987         {
988             *ppsidOwner = NULL;
989         }
990         if ((SecurityInfo & GROUP_SECURITY_INFORMATION) &&
991             ppsidGroup != NULL)
992         {
993             *ppsidGroup = NULL;
994         }
995         if ((SecurityInfo & DACL_SECURITY_INFORMATION) &&
996             ppDacl != NULL)
997         {
998             *ppDacl = NULL;
999         }
1000         if ((SecurityInfo & SACL_SECURITY_INFORMATION) &&
1001             ppSacl != NULL)
1002         {
1003             *ppSacl = NULL;
1004         }
1005 
1006         if (SecurityInfo & (OWNER_SECURITY_INFORMATION |
1007                             GROUP_SECURITY_INFORMATION |
1008                             DACL_SECURITY_INFORMATION |
1009                             SACL_SECURITY_INFORMATION))
1010         {
1011             *ppSecurityDescriptor = NULL;
1012         }
1013 
1014         return ERROR_SUCCESS;
1015     }
1016 }
1017 
1018 
1019 static DWORD
pSetSecurityInfoCheck(PSECURITY_DESCRIPTOR pSecurityDescriptor,SECURITY_INFORMATION SecurityInfo,PSID psidOwner,PSID psidGroup,PACL pDacl,PACL pSacl)1020 pSetSecurityInfoCheck(PSECURITY_DESCRIPTOR pSecurityDescriptor,
1021                       SECURITY_INFORMATION SecurityInfo,
1022                       PSID psidOwner,
1023                       PSID psidGroup,
1024                       PACL pDacl,
1025                       PACL pSacl)
1026 {
1027     /* initialize a security descriptor on the stack */
1028     if (!InitializeSecurityDescriptor(pSecurityDescriptor,
1029                                       SECURITY_DESCRIPTOR_REVISION))
1030     {
1031         return GetLastError();
1032     }
1033 
1034     if (SecurityInfo & OWNER_SECURITY_INFORMATION)
1035     {
1036         if (RtlValidSid(psidOwner))
1037         {
1038             if (!SetSecurityDescriptorOwner(pSecurityDescriptor,
1039                                             psidOwner,
1040                                             FALSE))
1041             {
1042                 return GetLastError();
1043             }
1044         }
1045         else
1046         {
1047             return ERROR_INVALID_PARAMETER;
1048         }
1049     }
1050 
1051     if (SecurityInfo & GROUP_SECURITY_INFORMATION)
1052     {
1053         if (RtlValidSid(psidGroup))
1054         {
1055             if (!SetSecurityDescriptorGroup(pSecurityDescriptor,
1056                                             psidGroup,
1057                                             FALSE))
1058             {
1059                 return GetLastError();
1060             }
1061         }
1062         else
1063         {
1064             return ERROR_INVALID_PARAMETER;
1065         }
1066     }
1067 
1068     if (SecurityInfo & DACL_SECURITY_INFORMATION)
1069     {
1070         if (pDacl != NULL)
1071         {
1072             if (SetSecurityDescriptorDacl(pSecurityDescriptor,
1073                                           TRUE,
1074                                           pDacl,
1075                                           FALSE))
1076             {
1077                 /* check if the DACL needs to be protected from being
1078                    modified by inheritable ACEs */
1079                 if (SecurityInfo & PROTECTED_DACL_SECURITY_INFORMATION)
1080                 {
1081                     goto ProtectDacl;
1082                 }
1083             }
1084             else
1085             {
1086                 return GetLastError();
1087             }
1088         }
1089         else
1090         {
1091 ProtectDacl:
1092             /* protect the DACL from being modified by inheritable ACEs */
1093             if (!SetSecurityDescriptorControl(pSecurityDescriptor,
1094                                               SE_DACL_PROTECTED,
1095                                               SE_DACL_PROTECTED))
1096             {
1097                 return GetLastError();
1098             }
1099         }
1100     }
1101 
1102     if (SecurityInfo & SACL_SECURITY_INFORMATION)
1103     {
1104         if (pSacl != NULL)
1105         {
1106             if (SetSecurityDescriptorSacl(pSecurityDescriptor,
1107                                           TRUE,
1108                                           pSacl,
1109                                           FALSE))
1110             {
1111                 /* check if the SACL needs to be protected from being
1112                    modified by inheritable ACEs */
1113                 if (SecurityInfo & PROTECTED_SACL_SECURITY_INFORMATION)
1114                 {
1115                     goto ProtectSacl;
1116                 }
1117             }
1118             else
1119             {
1120                 return GetLastError();
1121             }
1122         }
1123         else
1124         {
1125 ProtectSacl:
1126             /* protect the SACL from being modified by inheritable ACEs */
1127             if (!SetSecurityDescriptorControl(pSecurityDescriptor,
1128                                               SE_SACL_PROTECTED,
1129                                               SE_SACL_PROTECTED))
1130             {
1131                 return GetLastError();
1132             }
1133         }
1134     }
1135 
1136     return ERROR_SUCCESS;
1137 }
1138 
1139 
1140 /**********************************************************************
1141  * GetNamedSecurityInfoW			EXPORTED
1142  *
1143  * @implemented
1144  */
1145 DWORD
1146 WINAPI
GetNamedSecurityInfoW(LPWSTR pObjectName,SE_OBJECT_TYPE ObjectType,SECURITY_INFORMATION SecurityInfo,PSID * ppsidOwner,PSID * ppsidGroup,PACL * ppDacl,PACL * ppSacl,PSECURITY_DESCRIPTOR * ppSecurityDescriptor)1147 GetNamedSecurityInfoW(LPWSTR pObjectName,
1148                       SE_OBJECT_TYPE ObjectType,
1149                       SECURITY_INFORMATION SecurityInfo,
1150                       PSID *ppsidOwner,
1151                       PSID *ppsidGroup,
1152                       PACL *ppDacl,
1153                       PACL *ppSacl,
1154                       PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
1155 {
1156     DWORD ErrorCode;
1157 
1158     if (pObjectName != NULL)
1159     {
1160         ErrorCode = CheckNtMartaPresent();
1161         if (ErrorCode == ERROR_SUCCESS)
1162         {
1163             ErrorCode = pGetSecurityInfoCheck(SecurityInfo,
1164                                               ppsidOwner,
1165                                               ppsidGroup,
1166                                               ppDacl,
1167                                               ppSacl,
1168                                               ppSecurityDescriptor);
1169 
1170             if (ErrorCode == ERROR_SUCCESS)
1171             {
1172                 /* call the MARTA provider */
1173                 ErrorCode = AccRewriteGetNamedRights(pObjectName,
1174                                                      ObjectType,
1175                                                      SecurityInfo,
1176                                                      ppsidOwner,
1177                                                      ppsidGroup,
1178                                                      ppDacl,
1179                                                      ppSacl,
1180                                                      ppSecurityDescriptor);
1181             }
1182         }
1183     }
1184     else
1185         ErrorCode = ERROR_INVALID_PARAMETER;
1186 
1187     return ErrorCode;
1188 }
1189 
1190 /**********************************************************************
1191  * SetNamedSecurityInfoW			EXPORTED
1192  *
1193  * @implemented
1194  */
1195 DWORD
1196 WINAPI
SetNamedSecurityInfoW(LPWSTR pObjectName,SE_OBJECT_TYPE ObjectType,SECURITY_INFORMATION SecurityInfo,PSID psidOwner,PSID psidGroup,PACL pDacl,PACL pSacl)1197 SetNamedSecurityInfoW(LPWSTR pObjectName,
1198                       SE_OBJECT_TYPE ObjectType,
1199                       SECURITY_INFORMATION SecurityInfo,
1200                       PSID psidOwner,
1201                       PSID psidGroup,
1202                       PACL pDacl,
1203                       PACL pSacl)
1204 {
1205     DWORD ErrorCode;
1206 
1207     if (pObjectName != NULL)
1208     {
1209         ErrorCode = CheckNtMartaPresent();
1210         if (ErrorCode == ERROR_SUCCESS)
1211         {
1212             SECURITY_DESCRIPTOR SecurityDescriptor;
1213 
1214             ErrorCode = pSetSecurityInfoCheck(&SecurityDescriptor,
1215                                               SecurityInfo,
1216                                               psidOwner,
1217                                               psidGroup,
1218                                               pDacl,
1219                                               pSacl);
1220 
1221             if (ErrorCode == ERROR_SUCCESS)
1222             {
1223                 /* call the MARTA provider */
1224                 ErrorCode = AccRewriteSetNamedRights(pObjectName,
1225                                                      ObjectType,
1226                                                      SecurityInfo,
1227                                                      &SecurityDescriptor);
1228             }
1229         }
1230     }
1231     else
1232         ErrorCode = ERROR_INVALID_PARAMETER;
1233 
1234     return ErrorCode;
1235 }
1236 
1237 /**********************************************************************
1238  * GetSecurityInfo				EXPORTED
1239  *
1240  * @implemented
1241  */
1242 DWORD
1243 WINAPI
GetSecurityInfo(HANDLE handle,SE_OBJECT_TYPE ObjectType,SECURITY_INFORMATION SecurityInfo,PSID * ppsidOwner,PSID * ppsidGroup,PACL * ppDacl,PACL * ppSacl,PSECURITY_DESCRIPTOR * ppSecurityDescriptor)1244 GetSecurityInfo(HANDLE handle,
1245                 SE_OBJECT_TYPE ObjectType,
1246                 SECURITY_INFORMATION SecurityInfo,
1247                 PSID *ppsidOwner,
1248                 PSID *ppsidGroup,
1249                 PACL *ppDacl,
1250                 PACL *ppSacl,
1251                 PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
1252 {
1253     DWORD ErrorCode;
1254 
1255     if (handle != NULL)
1256     {
1257         ErrorCode = CheckNtMartaPresent();
1258         if (ErrorCode == ERROR_SUCCESS)
1259         {
1260             ErrorCode = pGetSecurityInfoCheck(SecurityInfo,
1261                                               ppsidOwner,
1262                                               ppsidGroup,
1263                                               ppDacl,
1264                                               ppSacl,
1265                                               ppSecurityDescriptor);
1266 
1267             if (ErrorCode == ERROR_SUCCESS)
1268             {
1269                 /* call the MARTA provider */
1270                 ErrorCode = AccRewriteGetHandleRights(handle,
1271                                                       ObjectType,
1272                                                       SecurityInfo,
1273                                                       ppsidOwner,
1274                                                       ppsidGroup,
1275                                                       ppDacl,
1276                                                       ppSacl,
1277                                                       ppSecurityDescriptor);
1278             }
1279         }
1280     }
1281     else
1282         ErrorCode = ERROR_INVALID_HANDLE;
1283 
1284     return ErrorCode;
1285 }
1286 
1287 
1288 /**********************************************************************
1289  * SetSecurityInfo				EXPORTED
1290  *
1291  * @implemented
1292  */
1293 DWORD
1294 WINAPI
SetSecurityInfo(HANDLE handle,SE_OBJECT_TYPE ObjectType,SECURITY_INFORMATION SecurityInfo,PSID psidOwner,PSID psidGroup,PACL pDacl,PACL pSacl)1295 SetSecurityInfo(HANDLE handle,
1296                 SE_OBJECT_TYPE ObjectType,
1297                 SECURITY_INFORMATION SecurityInfo,
1298                 PSID psidOwner,
1299                 PSID psidGroup,
1300                 PACL pDacl,
1301                 PACL pSacl)
1302 {
1303     DWORD ErrorCode;
1304 
1305     if (handle != NULL)
1306     {
1307         ErrorCode = CheckNtMartaPresent();
1308         if (ErrorCode == ERROR_SUCCESS)
1309         {
1310             SECURITY_DESCRIPTOR SecurityDescriptor;
1311 
1312             ErrorCode = pSetSecurityInfoCheck(&SecurityDescriptor,
1313                                               SecurityInfo,
1314                                               psidOwner,
1315                                               psidGroup,
1316                                               pDacl,
1317                                               pSacl);
1318 
1319             if (ErrorCode == ERROR_SUCCESS)
1320             {
1321                 /* call the MARTA provider */
1322                 ErrorCode = AccRewriteSetHandleRights(handle,
1323                                                       ObjectType,
1324                                                       SecurityInfo,
1325                                                       &SecurityDescriptor);
1326             }
1327         }
1328     }
1329     else
1330         ErrorCode = ERROR_INVALID_HANDLE;
1331 
1332     return ErrorCode;
1333 }
1334 
1335 /*
1336  * @implemented
1337  */
1338 BOOL
1339 WINAPI
CreatePrivateObjectSecurity(PSECURITY_DESCRIPTOR ParentDescriptor,PSECURITY_DESCRIPTOR CreatorDescriptor,PSECURITY_DESCRIPTOR * NewDescriptor,BOOL IsDirectoryObject,HANDLE Token,PGENERIC_MAPPING GenericMapping)1340 CreatePrivateObjectSecurity(PSECURITY_DESCRIPTOR ParentDescriptor,
1341                             PSECURITY_DESCRIPTOR CreatorDescriptor,
1342                             PSECURITY_DESCRIPTOR *NewDescriptor,
1343                             BOOL IsDirectoryObject,
1344                             HANDLE Token,
1345                             PGENERIC_MAPPING GenericMapping)
1346 {
1347     NTSTATUS Status;
1348 
1349     Status = RtlNewSecurityObject(ParentDescriptor,
1350                                   CreatorDescriptor,
1351                                   NewDescriptor,
1352                                   IsDirectoryObject,
1353                                   Token,
1354                                   GenericMapping);
1355     if (!NT_SUCCESS(Status))
1356     {
1357         SetLastError(RtlNtStatusToDosError(Status));
1358         return FALSE;
1359     }
1360 
1361     return TRUE;
1362 }
1363 
1364 
1365 /*
1366  * @unimplemented
1367  */
1368 BOOL
1369 WINAPI
CreatePrivateObjectSecurityEx(PSECURITY_DESCRIPTOR ParentDescriptor,PSECURITY_DESCRIPTOR CreatorDescriptor,PSECURITY_DESCRIPTOR * NewDescriptor,GUID * ObjectType,BOOL IsContainerObject,ULONG AutoInheritFlags,HANDLE Token,PGENERIC_MAPPING GenericMapping)1370 CreatePrivateObjectSecurityEx(PSECURITY_DESCRIPTOR ParentDescriptor,
1371                               PSECURITY_DESCRIPTOR CreatorDescriptor,
1372                               PSECURITY_DESCRIPTOR* NewDescriptor,
1373                               GUID* ObjectType,
1374                               BOOL IsContainerObject,
1375                               ULONG AutoInheritFlags,
1376                               HANDLE Token,
1377                               PGENERIC_MAPPING GenericMapping)
1378 {
1379     FIXME("%s() not implemented!\n", __FUNCTION__);
1380     return FALSE;
1381 }
1382 
1383 
1384 /*
1385  * @unimplemented
1386  */
1387 BOOL
1388 WINAPI
CreatePrivateObjectSecurityWithMultipleInheritance(PSECURITY_DESCRIPTOR ParentDescriptor,PSECURITY_DESCRIPTOR CreatorDescriptor,PSECURITY_DESCRIPTOR * NewDescriptor,GUID ** ObjectTypes,ULONG GuidCount,BOOL IsContainerObject,ULONG AutoInheritFlags,HANDLE Token,PGENERIC_MAPPING GenericMapping)1389 CreatePrivateObjectSecurityWithMultipleInheritance(PSECURITY_DESCRIPTOR ParentDescriptor,
1390                                                    PSECURITY_DESCRIPTOR CreatorDescriptor,
1391                                                    PSECURITY_DESCRIPTOR* NewDescriptor,
1392                                                    GUID** ObjectTypes,
1393                                                    ULONG GuidCount,
1394                                                    BOOL IsContainerObject,
1395                                                    ULONG AutoInheritFlags,
1396                                                    HANDLE Token,
1397                                                    PGENERIC_MAPPING GenericMapping)
1398 {
1399     FIXME("%s() semi-stub\n", __FUNCTION__);
1400     return CreatePrivateObjectSecurity(ParentDescriptor, CreatorDescriptor, NewDescriptor, IsContainerObject, Token, GenericMapping);
1401 }
1402 
1403 
1404 /*
1405  * @implemented
1406  */
1407 BOOL
1408 WINAPI
DestroyPrivateObjectSecurity(PSECURITY_DESCRIPTOR * ObjectDescriptor)1409 DestroyPrivateObjectSecurity(PSECURITY_DESCRIPTOR *ObjectDescriptor)
1410 {
1411     NTSTATUS Status;
1412 
1413     Status = RtlDeleteSecurityObject(ObjectDescriptor);
1414     if (!NT_SUCCESS(Status))
1415     {
1416         SetLastError(RtlNtStatusToDosError(Status));
1417         return FALSE;
1418     }
1419 
1420     return TRUE;
1421 }
1422 
1423 
1424 /*
1425  * @implemented
1426  */
1427 BOOL
1428 WINAPI
GetPrivateObjectSecurity(IN PSECURITY_DESCRIPTOR ObjectDescriptor,IN SECURITY_INFORMATION SecurityInformation,OUT PSECURITY_DESCRIPTOR ResultantDescriptor OPTIONAL,IN DWORD DescriptorLength,OUT PDWORD ReturnLength)1429 GetPrivateObjectSecurity(IN PSECURITY_DESCRIPTOR ObjectDescriptor,
1430                          IN SECURITY_INFORMATION SecurityInformation,
1431                          OUT PSECURITY_DESCRIPTOR ResultantDescriptor OPTIONAL,
1432                          IN DWORD DescriptorLength,
1433                          OUT PDWORD ReturnLength)
1434 {
1435     NTSTATUS Status;
1436 
1437     /* Call RTL */
1438     Status = RtlQuerySecurityObject(ObjectDescriptor,
1439                                     SecurityInformation,
1440                                     ResultantDescriptor,
1441                                     DescriptorLength,
1442                                     ReturnLength);
1443     if (!NT_SUCCESS(Status))
1444     {
1445         /* Fail */
1446         SetLastError(RtlNtStatusToDosError(Status));
1447         return FALSE;
1448     }
1449 
1450     /* Success */
1451     return TRUE;
1452 }
1453 
1454 
1455 /*
1456  * @implemented
1457  */
1458 BOOL
1459 WINAPI
SetPrivateObjectSecurity(SECURITY_INFORMATION SecurityInformation,PSECURITY_DESCRIPTOR ModificationDescriptor,PSECURITY_DESCRIPTOR * ObjectsSecurityDescriptor,PGENERIC_MAPPING GenericMapping,HANDLE Token)1460 SetPrivateObjectSecurity(SECURITY_INFORMATION SecurityInformation,
1461                          PSECURITY_DESCRIPTOR ModificationDescriptor,
1462                          PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
1463                          PGENERIC_MAPPING GenericMapping,
1464                          HANDLE Token)
1465 {
1466     NTSTATUS Status;
1467 
1468     Status = RtlSetSecurityObject(SecurityInformation,
1469                                   ModificationDescriptor,
1470                                   ObjectsSecurityDescriptor,
1471                                   GenericMapping,
1472                                   Token);
1473     if (!NT_SUCCESS(Status))
1474     {
1475         SetLastError(RtlNtStatusToDosError(Status));
1476         return FALSE;
1477     }
1478 
1479     return TRUE;
1480 }
1481 
1482 
1483 /*
1484  * @implemented
1485  */
1486 DWORD
1487 WINAPI
TreeResetNamedSecurityInfoW(LPWSTR pObjectName,SE_OBJECT_TYPE ObjectType,SECURITY_INFORMATION SecurityInfo,PSID pOwner,PSID pGroup,PACL pDacl,PACL pSacl,BOOL KeepExplicit,FN_PROGRESSW fnProgress,PROG_INVOKE_SETTING ProgressInvokeSetting,PVOID Args)1488 TreeResetNamedSecurityInfoW(LPWSTR pObjectName,
1489                             SE_OBJECT_TYPE ObjectType,
1490                             SECURITY_INFORMATION SecurityInfo,
1491                             PSID pOwner,
1492                             PSID pGroup,
1493                             PACL pDacl,
1494                             PACL pSacl,
1495                             BOOL KeepExplicit,
1496                             FN_PROGRESSW fnProgress,
1497                             PROG_INVOKE_SETTING ProgressInvokeSetting,
1498                             PVOID Args)
1499 {
1500     DWORD ErrorCode;
1501 
1502     if (pObjectName != NULL)
1503     {
1504         ErrorCode = CheckNtMartaPresent();
1505         if (ErrorCode == ERROR_SUCCESS)
1506         {
1507             switch (ObjectType)
1508             {
1509                 case SE_FILE_OBJECT:
1510                 case SE_REGISTRY_KEY:
1511                 {
1512                     /* check the SecurityInfo flags for sanity (both, the protected
1513                        and unprotected dacl/sacl flag must not be passed together) */
1514                     if (((SecurityInfo & DACL_SECURITY_INFORMATION) &&
1515                          (SecurityInfo & (PROTECTED_DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION)) ==
1516                              (PROTECTED_DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION))
1517 
1518                         ||
1519 
1520                         ((SecurityInfo & SACL_SECURITY_INFORMATION) &&
1521                          (SecurityInfo & (PROTECTED_SACL_SECURITY_INFORMATION | UNPROTECTED_SACL_SECURITY_INFORMATION)) ==
1522                              (PROTECTED_SACL_SECURITY_INFORMATION | UNPROTECTED_SACL_SECURITY_INFORMATION)))
1523                     {
1524                         ErrorCode = ERROR_INVALID_PARAMETER;
1525                         break;
1526                     }
1527 
1528                     /* call the MARTA provider */
1529                     ErrorCode = AccTreeResetNamedSecurityInfo(pObjectName,
1530                                                               ObjectType,
1531                                                               SecurityInfo,
1532                                                               pOwner,
1533                                                               pGroup,
1534                                                               pDacl,
1535                                                               pSacl,
1536                                                               KeepExplicit,
1537                                                               fnProgress,
1538                                                               ProgressInvokeSetting,
1539                                                               Args);
1540                     break;
1541                 }
1542 
1543                 default:
1544                     /* object type not supported */
1545                     ErrorCode = ERROR_INVALID_PARAMETER;
1546                     break;
1547             }
1548         }
1549     }
1550     else
1551         ErrorCode = ERROR_INVALID_PARAMETER;
1552 
1553     return ErrorCode;
1554 }
1555 
1556 #ifdef HAS_FN_PROGRESSW
1557 
1558 typedef struct _INTERNAL_FNPROGRESSW_DATA
1559 {
1560     FN_PROGRESSA fnProgress;
1561     PVOID Args;
1562 } INTERNAL_FNPROGRESSW_DATA, *PINTERNAL_FNPROGRESSW_DATA;
1563 
1564 static VOID WINAPI
InternalfnProgressW(LPWSTR pObjectName,DWORD Status,PPROG_INVOKE_SETTING pInvokeSetting,PVOID Args,BOOL SecuritySet)1565 InternalfnProgressW(LPWSTR pObjectName,
1566                     DWORD Status,
1567                     PPROG_INVOKE_SETTING pInvokeSetting,
1568                     PVOID Args,
1569                     BOOL SecuritySet)
1570 {
1571     PINTERNAL_FNPROGRESSW_DATA pifnProgressData = (PINTERNAL_FNPROGRESSW_DATA)Args;
1572     INT ObjectNameSize;
1573     LPSTR pObjectNameA;
1574 
1575     ObjectNameSize = WideCharToMultiByte(CP_ACP,
1576                                          0,
1577                                          pObjectName,
1578                                          -1,
1579                                          NULL,
1580                                          0,
1581                                          NULL,
1582                                          NULL);
1583 
1584     if (ObjectNameSize > 0)
1585     {
1586         pObjectNameA = RtlAllocateHeap(RtlGetProcessHeap(),
1587                                        0,
1588                                        ObjectNameSize);
1589         if (pObjectNameA != NULL)
1590         {
1591             pObjectNameA[0] = '\0';
1592             WideCharToMultiByte(CP_ACP,
1593                                 0,
1594                                 pObjectName,
1595                                 -1,
1596                                 pObjectNameA,
1597                                 ObjectNameSize,
1598                                 NULL,
1599                                 NULL);
1600 
1601             pifnProgressData->fnProgress((LPWSTR)pObjectNameA, /* FIXME: wrong cast!! */
1602                                          Status,
1603                                          pInvokeSetting,
1604                                          pifnProgressData->Args,
1605                                          SecuritySet);
1606 
1607             RtlFreeHeap(RtlGetProcessHeap(),
1608                         0,
1609                         pObjectNameA);
1610         }
1611     }
1612 }
1613 #endif
1614 
1615 
1616 /*
1617  * @implemented
1618  */
1619 DWORD
1620 WINAPI
TreeResetNamedSecurityInfoA(LPSTR pObjectName,SE_OBJECT_TYPE ObjectType,SECURITY_INFORMATION SecurityInfo,PSID pOwner,PSID pGroup,PACL pDacl,PACL pSacl,BOOL KeepExplicit,FN_PROGRESSA fnProgress,PROG_INVOKE_SETTING ProgressInvokeSetting,PVOID Args)1621 TreeResetNamedSecurityInfoA(LPSTR pObjectName,
1622                             SE_OBJECT_TYPE ObjectType,
1623                             SECURITY_INFORMATION SecurityInfo,
1624                             PSID pOwner,
1625                             PSID pGroup,
1626                             PACL pDacl,
1627                             PACL pSacl,
1628                             BOOL KeepExplicit,
1629                             FN_PROGRESSA fnProgress,
1630                             PROG_INVOKE_SETTING ProgressInvokeSetting,
1631                             PVOID Args)
1632 {
1633 #ifndef HAS_FN_PROGRESSW
1634     /* That's all this function does, at least up to w2k3... Even MS was too
1635        lazy to implement it... */
1636     return ERROR_CALL_NOT_IMPLEMENTED;
1637 #else
1638     INTERNAL_FNPROGRESSW_DATA ifnProgressData;
1639     UNICODE_STRING ObjectName;
1640     DWORD Ret;
1641 
1642     if (!RtlCreateUnicodeStringFromAsciiz(&ObjectName, pObjectName))
1643     {
1644         return ERROR_NOT_ENOUGH_MEMORY;
1645     }
1646 
1647     ifnProgressData.fnProgress = fnProgress;
1648     ifnProgressData.Args = Args;
1649 
1650     Ret = TreeResetNamedSecurityInfoW(ObjectName.Buffer,
1651                                       ObjectType,
1652                                       SecurityInfo,
1653                                       pOwner,
1654                                       pGroup,
1655                                       pDacl,
1656                                       pSacl,
1657                                       KeepExplicit,
1658                                       (fnProgress != NULL ? InternalfnProgressW : NULL),
1659                                       ProgressInvokeSetting,
1660                                       &ifnProgressData);
1661 
1662     RtlFreeUnicodeString(&ObjectName);
1663 
1664     return Ret;
1665 #endif
1666 }
1667 
1668 /* EOF */
1669