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