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