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