Fix a buffer overflow accessing the pKeepAce array in AccRewriteSetEntriesInAcl
[reactos.git] / reactos / dll / win32 / ntmarta / ntmarta.c
1 /*
2 * ReactOS MARTA provider
3 * Copyright (C) 2005 - 2006 ReactOS Team
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS MARTA provider
22 * FILE: lib/ntmarta/ntmarta.c
23 * PURPOSE: ReactOS MARTA provider
24 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
25 *
26 * UPDATE HISTORY:
27 * 07/26/2005 Created
28 */
29 #include <ntmarta.h>
30
31 #define NDEBUG
32 #include <debug.h>
33
34 HINSTANCE hDllInstance;
35
36 static ACCESS_MODE
37 AccpGetAceAccessMode(IN PACE_HEADER AceHeader)
38 {
39 ACCESS_MODE Mode = NOT_USED_ACCESS;
40
41 switch (AceHeader->AceType)
42 {
43 case ACCESS_ALLOWED_ACE_TYPE:
44 case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
45 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
46 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
47 Mode = GRANT_ACCESS;
48 break;
49
50 case ACCESS_DENIED_ACE_TYPE:
51 case ACCESS_DENIED_CALLBACK_ACE_TYPE:
52 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
53 case ACCESS_DENIED_OBJECT_ACE_TYPE:
54 Mode = DENY_ACCESS;
55 break;
56
57 case SYSTEM_AUDIT_ACE_TYPE:
58 case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
59 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
60 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
61 if (AceHeader->AceFlags & FAILED_ACCESS_ACE_FLAG)
62 Mode = SET_AUDIT_FAILURE;
63 else if (AceHeader->AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
64 Mode = SET_AUDIT_SUCCESS;
65 break;
66 }
67
68 return Mode;
69 }
70
71 static UINT
72 AccpGetAceStructureSize(IN PACE_HEADER AceHeader)
73 {
74 UINT Size = 0;
75
76 switch (AceHeader->AceType)
77 {
78 case ACCESS_ALLOWED_ACE_TYPE:
79 case ACCESS_DENIED_ACE_TYPE:
80 Size = FIELD_OFFSET(ACCESS_ALLOWED_ACE,
81 SidStart);
82 break;
83 case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
84 case ACCESS_DENIED_CALLBACK_ACE_TYPE:
85 Size = FIELD_OFFSET(ACCESS_ALLOWED_CALLBACK_ACE,
86 SidStart);
87 break;
88 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
89 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
90 {
91 PACCESS_ALLOWED_CALLBACK_OBJECT_ACE Ace = (PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader;
92 Size = FIELD_OFFSET(ACCESS_ALLOWED_CALLBACK_OBJECT_ACE,
93 ObjectType);
94 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
95 Size += sizeof(Ace->ObjectType);
96 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
97 Size += sizeof(Ace->InheritedObjectType);
98 break;
99 }
100 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
101 case ACCESS_DENIED_OBJECT_ACE_TYPE:
102 {
103 PACCESS_ALLOWED_OBJECT_ACE Ace = (PACCESS_ALLOWED_OBJECT_ACE)AceHeader;
104 Size = FIELD_OFFSET(ACCESS_ALLOWED_OBJECT_ACE,
105 ObjectType);
106 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
107 Size += sizeof(Ace->ObjectType);
108 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
109 Size += sizeof(Ace->InheritedObjectType);
110 break;
111 }
112
113 case SYSTEM_AUDIT_ACE_TYPE:
114 Size = FIELD_OFFSET(SYSTEM_AUDIT_ACE,
115 SidStart);
116 break;
117 case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
118 Size = FIELD_OFFSET(SYSTEM_AUDIT_CALLBACK_ACE,
119 SidStart);
120 break;
121 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
122 {
123 PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE Ace = (PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE)AceHeader;
124 Size = FIELD_OFFSET(SYSTEM_AUDIT_CALLBACK_OBJECT_ACE,
125 ObjectType);
126 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
127 Size += sizeof(Ace->ObjectType);
128 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
129 Size += sizeof(Ace->InheritedObjectType);
130 break;
131 }
132 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
133 {
134 PSYSTEM_AUDIT_OBJECT_ACE Ace = (PSYSTEM_AUDIT_OBJECT_ACE)AceHeader;
135 Size = FIELD_OFFSET(SYSTEM_AUDIT_OBJECT_ACE,
136 ObjectType);
137 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
138 Size += sizeof(Ace->ObjectType);
139 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
140 Size += sizeof(Ace->InheritedObjectType);
141 break;
142 }
143
144 case SYSTEM_MANDATORY_LABEL_ACE_TYPE:
145 Size = FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE,
146 SidStart);
147 break;
148 }
149
150 return Size;
151 }
152
153 static PSID
154 AccpGetAceSid(IN PACE_HEADER AceHeader)
155 {
156 return (PSID)((ULONG_PTR)AceHeader + AccpGetAceStructureSize(AceHeader));
157 }
158
159 static ACCESS_MASK
160 AccpGetAceAccessMask(IN PACE_HEADER AceHeader)
161 {
162 return *((PACCESS_MASK)(AceHeader + 1));
163 }
164
165 static BOOL
166 AccpIsObjectAce(IN PACE_HEADER AceHeader)
167 {
168 BOOL Ret;
169
170 switch (AceHeader->AceType)
171 {
172 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
173 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
174 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
175 case ACCESS_DENIED_OBJECT_ACE_TYPE:
176 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
177 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
178 Ret = TRUE;
179 break;
180
181 default:
182 Ret = FALSE;
183 break;
184 }
185
186 return Ret;
187 }
188
189 static GUID*
190 AccpGetObjectAceObjectType(IN PACE_HEADER AceHeader)
191 {
192 GUID *ObjectType = NULL;
193
194 switch (AceHeader->AceType)
195 {
196 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
197 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
198 {
199 PACCESS_ALLOWED_CALLBACK_OBJECT_ACE Ace = (PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader;
200 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
201 ObjectType = &Ace->ObjectType;
202 break;
203 }
204 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
205 case ACCESS_DENIED_OBJECT_ACE_TYPE:
206 {
207 PACCESS_ALLOWED_OBJECT_ACE Ace = (PACCESS_ALLOWED_OBJECT_ACE)AceHeader;
208 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
209 ObjectType = &Ace->ObjectType;
210 break;
211 }
212
213 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
214 {
215 PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE Ace = (PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE)AceHeader;
216 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
217 ObjectType = &Ace->ObjectType;
218 break;
219 }
220 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
221 {
222 PSYSTEM_AUDIT_OBJECT_ACE Ace = (PSYSTEM_AUDIT_OBJECT_ACE)AceHeader;
223 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
224 ObjectType = &Ace->ObjectType;
225 break;
226 }
227 }
228
229 return ObjectType;
230 }
231
232 static GUID*
233 AccpGetObjectAceInheritedObjectType(IN PACE_HEADER AceHeader)
234 {
235 GUID *ObjectType = NULL;
236
237 switch (AceHeader->AceType)
238 {
239 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
240 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
241 {
242 PACCESS_ALLOWED_CALLBACK_OBJECT_ACE Ace = (PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader;
243 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
244 {
245 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
246 ObjectType = &Ace->InheritedObjectType;
247 else
248 ObjectType = &Ace->ObjectType;
249 }
250 break;
251 }
252 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
253 case ACCESS_DENIED_OBJECT_ACE_TYPE:
254 {
255 PACCESS_ALLOWED_OBJECT_ACE Ace = (PACCESS_ALLOWED_OBJECT_ACE)AceHeader;
256 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
257 {
258 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
259 ObjectType = &Ace->InheritedObjectType;
260 else
261 ObjectType = &Ace->ObjectType;
262 }
263 break;
264 }
265
266 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
267 {
268 PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE Ace = (PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE)AceHeader;
269 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
270 {
271 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
272 ObjectType = &Ace->InheritedObjectType;
273 else
274 ObjectType = &Ace->ObjectType;
275 }
276 break;
277 }
278 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
279 {
280 PSYSTEM_AUDIT_OBJECT_ACE Ace = (PSYSTEM_AUDIT_OBJECT_ACE)AceHeader;
281 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
282 {
283 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
284 ObjectType = &Ace->InheritedObjectType;
285 else
286 ObjectType = &Ace->ObjectType;
287 }
288 break;
289 }
290 }
291
292 return ObjectType;
293 }
294
295
296 /**********************************************************************
297 * AccRewriteGetHandleRights EXPORTED
298 *
299 * @unimplemented
300 */
301 DWORD WINAPI
302 AccRewriteGetHandleRights(HANDLE handle,
303 SE_OBJECT_TYPE ObjectType,
304 SECURITY_INFORMATION SecurityInfo,
305 PSID* ppsidOwner,
306 PSID* ppsidGroup,
307 PACL* ppDacl,
308 PACL* ppSacl,
309 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
310 {
311 PSECURITY_DESCRIPTOR pSD = NULL;
312 ULONG SDSize = 0;
313 NTSTATUS Status;
314 DWORD LastErr;
315 DWORD Ret;
316
317 /* save the last error code */
318 LastErr = GetLastError();
319
320 do
321 {
322 Ret = ERROR_SUCCESS;
323
324 /* allocate a buffer large enough to hold the
325 security descriptor we need to return */
326 SDSize += 0x100;
327 if (pSD == NULL)
328 {
329 pSD = LocalAlloc(LMEM_FIXED,
330 (SIZE_T)SDSize);
331 }
332 else
333 {
334 PSECURITY_DESCRIPTOR newSD;
335
336 newSD = LocalReAlloc((HLOCAL)pSD,
337 (SIZE_T)SDSize,
338 LMEM_MOVEABLE);
339 if (newSD != NULL)
340 pSD = newSD;
341 }
342
343 if (pSD == NULL)
344 {
345 Ret = GetLastError();
346 break;
347 }
348
349 /* perform the actual query depending on the object type */
350 switch (ObjectType)
351 {
352 case SE_REGISTRY_KEY:
353 {
354 Ret = (DWORD)RegGetKeySecurity((HKEY)handle,
355 SecurityInfo,
356 pSD,
357 &SDSize);
358 break;
359 }
360
361 case SE_FILE_OBJECT:
362 /* FIXME - handle console handles? */
363 case SE_KERNEL_OBJECT:
364 {
365 Status = NtQuerySecurityObject(handle,
366 SecurityInfo,
367 pSD,
368 SDSize,
369 &SDSize);
370 if (!NT_SUCCESS(Status))
371 {
372 Ret = RtlNtStatusToDosError(Status);
373 }
374 break;
375 }
376
377 case SE_SERVICE:
378 {
379 if (!QueryServiceObjectSecurity((SC_HANDLE)handle,
380 SecurityInfo,
381 pSD,
382 SDSize,
383 &SDSize))
384 {
385 Ret = GetLastError();
386 }
387 break;
388 }
389
390 case SE_WINDOW_OBJECT:
391 {
392 if (!GetUserObjectSecurity(handle,
393 &SecurityInfo,
394 pSD,
395 SDSize,
396 &SDSize))
397 {
398 Ret = GetLastError();
399 }
400 break;
401 }
402
403 default:
404 {
405 UNIMPLEMENTED;
406 Ret = ERROR_CALL_NOT_IMPLEMENTED;
407 break;
408 }
409 }
410
411 } while (Ret == ERROR_INSUFFICIENT_BUFFER);
412
413 if (Ret == ERROR_SUCCESS)
414 {
415 BOOL Present, Defaulted;
416
417 if (SecurityInfo & OWNER_SECURITY_INFORMATION && ppsidOwner != NULL)
418 {
419 *ppsidOwner = NULL;
420 if (!GetSecurityDescriptorOwner(pSD,
421 ppsidOwner,
422 &Defaulted))
423 {
424 Ret = GetLastError();
425 goto Cleanup;
426 }
427 }
428
429 if (SecurityInfo & GROUP_SECURITY_INFORMATION && ppsidGroup != NULL)
430 {
431 *ppsidOwner = NULL;
432 if (!GetSecurityDescriptorGroup(pSD,
433 ppsidGroup,
434 &Defaulted))
435 {
436 Ret = GetLastError();
437 goto Cleanup;
438 }
439 }
440
441 if (SecurityInfo & DACL_SECURITY_INFORMATION && ppDacl != NULL)
442 {
443 *ppDacl = NULL;
444 if (!GetSecurityDescriptorDacl(pSD,
445 &Present,
446 ppDacl,
447 &Defaulted))
448 {
449 Ret = GetLastError();
450 goto Cleanup;
451 }
452 }
453
454 if (SecurityInfo & SACL_SECURITY_INFORMATION && ppSacl != NULL)
455 {
456 *ppSacl = NULL;
457 if (!GetSecurityDescriptorSacl(pSD,
458 &Present,
459 ppSacl,
460 &Defaulted))
461 {
462 Ret = GetLastError();
463 goto Cleanup;
464 }
465 }
466
467 *ppSecurityDescriptor = pSD;
468 }
469 else
470 {
471 Cleanup:
472 if (pSD != NULL)
473 {
474 LocalFree((HLOCAL)pSD);
475 }
476 }
477
478 /* restore the last error code */
479 SetLastError(LastErr);
480
481 return Ret;
482 }
483
484
485 /**********************************************************************
486 * AccRewriteSetHandleRights EXPORTED
487 *
488 * @unimplemented
489 */
490 DWORD WINAPI
491 AccRewriteSetHandleRights(HANDLE handle,
492 SE_OBJECT_TYPE ObjectType,
493 SECURITY_INFORMATION SecurityInfo,
494 PSECURITY_DESCRIPTOR pSecurityDescriptor)
495 {
496 NTSTATUS Status;
497 DWORD LastErr;
498 DWORD Ret = ERROR_SUCCESS;
499
500 /* save the last error code */
501 LastErr = GetLastError();
502
503 /* set the security according to the object type */
504 switch (ObjectType)
505 {
506 case SE_REGISTRY_KEY:
507 {
508 Ret = (DWORD)RegSetKeySecurity((HKEY)handle,
509 SecurityInfo,
510 pSecurityDescriptor);
511 break;
512 }
513
514 case SE_FILE_OBJECT:
515 /* FIXME - handle console handles? */
516 case SE_KERNEL_OBJECT:
517 {
518 Status = NtSetSecurityObject(handle,
519 SecurityInfo,
520 pSecurityDescriptor);
521 if (!NT_SUCCESS(Status))
522 {
523 Ret = RtlNtStatusToDosError(Status);
524 }
525 break;
526 }
527
528 case SE_SERVICE:
529 {
530 if (!SetServiceObjectSecurity((SC_HANDLE)handle,
531 SecurityInfo,
532 pSecurityDescriptor))
533 {
534 Ret = GetLastError();
535 }
536 break;
537 }
538
539 case SE_WINDOW_OBJECT:
540 {
541 if (!SetUserObjectSecurity(handle,
542 &SecurityInfo,
543 pSecurityDescriptor))
544 {
545 Ret = GetLastError();
546 }
547 break;
548 }
549
550 default:
551 {
552 UNIMPLEMENTED;
553 Ret = ERROR_CALL_NOT_IMPLEMENTED;
554 break;
555 }
556 }
557
558
559 /* restore the last error code */
560 SetLastError(LastErr);
561
562 return Ret;
563 }
564
565
566 static DWORD
567 AccpOpenNamedObject(LPWSTR pObjectName,
568 SE_OBJECT_TYPE ObjectType,
569 SECURITY_INFORMATION SecurityInfo,
570 PHANDLE Handle,
571 PHANDLE Handle2,
572 BOOL Write)
573 {
574 LPWSTR lpPath;
575 NTSTATUS Status;
576 ACCESS_MASK DesiredAccess = (ACCESS_MASK)0;
577 DWORD Ret = ERROR_SUCCESS;
578
579 /* determine the required access rights */
580 switch (ObjectType)
581 {
582 case SE_REGISTRY_KEY:
583 case SE_FILE_OBJECT:
584 case SE_KERNEL_OBJECT:
585 case SE_SERVICE:
586 case SE_WINDOW_OBJECT:
587 if (Write)
588 {
589 SetSecurityAccessMask(SecurityInfo,
590 (PDWORD)&DesiredAccess);
591 }
592 else
593 {
594 QuerySecurityAccessMask(SecurityInfo,
595 (PDWORD)&DesiredAccess);
596 }
597 break;
598
599 default:
600 break;
601 }
602
603 /* make a copy of the path if we're modifying the string */
604 switch (ObjectType)
605 {
606 case SE_REGISTRY_KEY:
607 case SE_SERVICE:
608 lpPath = (LPWSTR)LocalAlloc(LMEM_FIXED,
609 (wcslen(pObjectName) + 1) * sizeof(WCHAR));
610 if (lpPath == NULL)
611 {
612 Ret = GetLastError();
613 goto Cleanup;
614 }
615
616 wcscpy(lpPath,
617 pObjectName);
618 break;
619
620 default:
621 lpPath = pObjectName;
622 break;
623 }
624
625 /* open a handle to the path depending on the object type */
626 switch (ObjectType)
627 {
628 case SE_FILE_OBJECT:
629 {
630 IO_STATUS_BLOCK IoStatusBlock;
631 OBJECT_ATTRIBUTES ObjectAttributes;
632 UNICODE_STRING FileName;
633
634 if (!RtlDosPathNameToNtPathName_U(pObjectName,
635 &FileName,
636 NULL,
637 NULL))
638 {
639 Ret = ERROR_INVALID_NAME;
640 goto Cleanup;
641 }
642
643 InitializeObjectAttributes(&ObjectAttributes,
644 &FileName,
645 OBJ_CASE_INSENSITIVE,
646 NULL,
647 NULL);
648
649 Status = NtOpenFile(Handle,
650 DesiredAccess,
651 &ObjectAttributes,
652 &IoStatusBlock,
653 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
654 FILE_SYNCHRONOUS_IO_NONALERT);
655
656 RtlFreeHeap(RtlGetProcessHeap(),
657 0,
658 FileName.Buffer);
659
660 if (!NT_SUCCESS(Status))
661 {
662 Ret = RtlNtStatusToDosError(Status);
663 }
664 break;
665 }
666
667 case SE_REGISTRY_KEY:
668 {
669 static const struct
670 {
671 HKEY hRootKey;
672 LPCWSTR szRootKey;
673 } AccRegRootKeys[] =
674 {
675 {HKEY_CLASSES_ROOT, L"CLASSES_ROOT"},
676 {HKEY_CURRENT_USER, L"CURRENT_USER"},
677 {HKEY_LOCAL_MACHINE, L"MACHINE"},
678 {HKEY_USERS, L"USERS"},
679 {HKEY_CURRENT_CONFIG, L"CONFIG"},
680 };
681 LPWSTR lpMachineName, lpRootKeyName, lpKeyName;
682 HKEY hRootKey = NULL;
683 UINT i;
684
685 /* parse the registry path */
686 if (lpPath[0] == L'\\' && lpPath[1] == L'\\')
687 {
688 lpMachineName = lpPath;
689
690 lpRootKeyName = wcschr(lpPath + 2,
691 L'\\');
692 if (lpRootKeyName == NULL)
693 goto ParseRegErr;
694 else
695 *(lpRootKeyName++) = L'\0';
696 }
697 else
698 {
699 lpMachineName = NULL;
700 lpRootKeyName = lpPath;
701 }
702
703 lpKeyName = wcschr(lpRootKeyName,
704 L'\\');
705 if (lpKeyName != NULL)
706 {
707 *(lpKeyName++) = L'\0';
708 }
709
710 for (i = 0;
711 i != sizeof(AccRegRootKeys) / sizeof(AccRegRootKeys[0]);
712 i++)
713 {
714 if (!wcsicmp(lpRootKeyName,
715 AccRegRootKeys[i].szRootKey))
716 {
717 hRootKey = AccRegRootKeys[i].hRootKey;
718 break;
719 }
720 }
721
722 if (hRootKey == NULL)
723 {
724 ParseRegErr:
725 /* FIXME - right error code? */
726 Ret = ERROR_INVALID_PARAMETER;
727 goto Cleanup;
728 }
729
730 /* open the registry key */
731 if (lpMachineName != NULL)
732 {
733 Ret = RegConnectRegistry(lpMachineName,
734 hRootKey,
735 (PHKEY)Handle2);
736
737 if (Ret != ERROR_SUCCESS)
738 goto Cleanup;
739
740 hRootKey = (HKEY)(*Handle2);
741 }
742
743 Ret = RegOpenKeyEx(hRootKey,
744 lpKeyName,
745 0,
746 (REGSAM)DesiredAccess,
747 (PHKEY)Handle);
748 if (Ret != ERROR_SUCCESS)
749 {
750 if (*Handle2 != NULL)
751 {
752 RegCloseKey((HKEY)(*Handle2));
753 }
754
755 goto Cleanup;
756 }
757 break;
758 }
759
760 case SE_SERVICE:
761 {
762 LPWSTR lpServiceName, lpMachineName;
763
764 /* parse the service path */
765 if (lpPath[0] == L'\\' && lpPath[1] == L'\\')
766 {
767 DesiredAccess |= SC_MANAGER_CONNECT;
768
769 lpMachineName = lpPath;
770
771 lpServiceName = wcschr(lpPath + 2,
772 L'\\');
773 if (lpServiceName == NULL)
774 {
775 /* FIXME - right error code? */
776 Ret = ERROR_INVALID_PARAMETER;
777 goto Cleanup;
778 }
779 else
780 *(lpServiceName++) = L'\0';
781 }
782 else
783 {
784 lpMachineName = NULL;
785 lpServiceName = lpPath;
786 }
787
788 /* open the service */
789 *Handle2 = (HANDLE)OpenSCManager(lpMachineName,
790 NULL,
791 (DWORD)DesiredAccess);
792 if (*Handle2 == NULL)
793 {
794 goto FailOpenService;
795 }
796
797 DesiredAccess &= ~SC_MANAGER_CONNECT;
798 *Handle = (HANDLE)OpenService((SC_HANDLE)(*Handle2),
799 lpServiceName,
800 (DWORD)DesiredAccess);
801 if (*Handle == NULL)
802 {
803 if (*Handle2 != NULL)
804 {
805 CloseServiceHandle((SC_HANDLE)(*Handle2));
806 }
807
808 FailOpenService:
809 Ret = GetLastError();
810 goto Cleanup;
811 }
812 break;
813 }
814
815 default:
816 {
817 UNIMPLEMENTED;
818 Ret = ERROR_CALL_NOT_IMPLEMENTED;
819 break;
820 }
821 }
822
823 Cleanup:
824 if (lpPath != NULL && lpPath != pObjectName)
825 {
826 LocalFree((HLOCAL)lpPath);
827 }
828
829 return Ret;
830 }
831
832
833 static VOID
834 AccpCloseObjectHandle(SE_OBJECT_TYPE ObjectType,
835 HANDLE Handle,
836 HANDLE Handle2)
837 {
838 ASSERT(Handle != NULL);
839
840 /* close allocated handlees depending on the object type */
841 switch (ObjectType)
842 {
843 case SE_REGISTRY_KEY:
844 RegCloseKey((HKEY)Handle);
845 if (Handle2 != NULL)
846 RegCloseKey((HKEY)Handle2);
847 break;
848
849 case SE_FILE_OBJECT:
850 NtClose(Handle);
851 break;
852
853 case SE_KERNEL_OBJECT:
854 case SE_WINDOW_OBJECT:
855 CloseHandle(Handle);
856 break;
857
858 case SE_SERVICE:
859 CloseServiceHandle((SC_HANDLE)Handle);
860 ASSERT(Handle2 != NULL);
861 CloseServiceHandle((SC_HANDLE)Handle2);
862 break;
863
864 default:
865 break;
866 }
867 }
868
869
870 /**********************************************************************
871 * AccRewriteGetNamedRights EXPORTED
872 *
873 * @unimplemented
874 */
875 DWORD WINAPI
876 AccRewriteGetNamedRights(LPWSTR pObjectName,
877 SE_OBJECT_TYPE ObjectType,
878 SECURITY_INFORMATION SecurityInfo,
879 PSID* ppsidOwner,
880 PSID* ppsidGroup,
881 PACL* ppDacl,
882 PACL* ppSacl,
883 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
884 {
885 HANDLE Handle = NULL;
886 HANDLE Handle2 = NULL;
887 DWORD LastErr;
888 DWORD Ret;
889
890 /* save the last error code */
891 LastErr = GetLastError();
892
893 /* create the handle */
894 Ret = AccpOpenNamedObject(pObjectName,
895 ObjectType,
896 SecurityInfo,
897 &Handle,
898 &Handle2,
899 FALSE);
900
901 if (Ret == ERROR_SUCCESS)
902 {
903 ASSERT(Handle != NULL);
904
905 /* perform the operation */
906 Ret = AccRewriteGetHandleRights(Handle,
907 ObjectType,
908 SecurityInfo,
909 ppsidOwner,
910 ppsidGroup,
911 ppDacl,
912 ppSacl,
913 ppSecurityDescriptor);
914
915 /* close opened handles */
916 AccpCloseObjectHandle(ObjectType,
917 Handle,
918 Handle2);
919 }
920
921 /* restore the last error code */
922 SetLastError(LastErr);
923
924 return Ret;
925 }
926
927
928 /**********************************************************************
929 * AccRewriteSetNamedRights EXPORTED
930 *
931 * @unimplemented
932 */
933 DWORD WINAPI
934 AccRewriteSetNamedRights(LPWSTR pObjectName,
935 SE_OBJECT_TYPE ObjectType,
936 SECURITY_INFORMATION SecurityInfo,
937 PSECURITY_DESCRIPTOR pSecurityDescriptor)
938 {
939 HANDLE Handle = NULL;
940 HANDLE Handle2 = NULL;
941 DWORD LastErr;
942 DWORD Ret;
943
944 /* save the last error code */
945 LastErr = GetLastError();
946
947 /* create the handle */
948 Ret = AccpOpenNamedObject(pObjectName,
949 ObjectType,
950 SecurityInfo,
951 &Handle,
952 &Handle2,
953 TRUE);
954
955 if (Ret == ERROR_SUCCESS)
956 {
957 ASSERT(Handle != NULL);
958
959 /* perform the operation */
960 Ret = AccRewriteSetHandleRights(Handle,
961 ObjectType,
962 SecurityInfo,
963 pSecurityDescriptor);
964
965 /* close opened handles */
966 AccpCloseObjectHandle(ObjectType,
967 Handle,
968 Handle2);
969 }
970
971 /* restore the last error code */
972 SetLastError(LastErr);
973
974 return Ret;
975 }
976
977
978 static PSID
979 GetTrusteeSid(PTRUSTEE Trustee,
980 BOOL *Allocated)
981 {
982 if (Trustee->pMultipleTrustee || Trustee->MultipleTrusteeOperation != NO_MULTIPLE_TRUSTEE)
983 {
984 DPRINT1("Trustee form not supported\n");
985 return NULL;
986 }
987
988 switch (Trustee->TrusteeForm)
989 {
990 case TRUSTEE_IS_NAME:
991 case TRUSTEE_IS_OBJECTS_AND_NAME:
992 /* FIXME */
993 DPRINT1("Case not implemented\n");
994 ASSERT(FALSE);
995 return NULL;
996 case TRUSTEE_IS_OBJECTS_AND_SID:
997 *Allocated = FALSE;
998 return ((POBJECTS_AND_SID)Trustee->ptstrName)->pSid;
999 case TRUSTEE_IS_SID:
1000 *Allocated = FALSE;
1001 return (PSID)Trustee->ptstrName;
1002 default:
1003 DPRINT1("Wrong Trustee form\n");
1004 return NULL;
1005 }
1006 }
1007
1008
1009 /**********************************************************************
1010 * AccRewriteSetEntriesInAcl EXPORTED
1011 *
1012 * @implemented
1013 */
1014 DWORD WINAPI
1015 AccRewriteSetEntriesInAcl(ULONG cCountOfExplicitEntries,
1016 PEXPLICIT_ACCESS_W pListOfExplicitEntries,
1017 PACL OldAcl,
1018 PACL* NewAcl)
1019 {
1020 PACL pNew;
1021 ACL_SIZE_INFORMATION SizeInformation;
1022 PACE_HEADER pAce;
1023 BOOLEAN *pKeepAce = NULL;
1024 BOOL needToClean;
1025 PSID pSid1, pSid2;
1026 ULONG i;
1027 BOOL bRet;
1028 DWORD LastErr;
1029 DWORD Ret = ERROR_SUCCESS;
1030
1031 /* save the last error code */
1032 LastErr = GetLastError();
1033
1034 *NewAcl = NULL;
1035
1036 /* Get information about previous ACL */
1037 if (OldAcl)
1038 {
1039 if (!GetAclInformation(OldAcl, &SizeInformation, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
1040 {
1041 Ret = GetLastError();
1042 goto Cleanup;
1043 }
1044
1045 pKeepAce = (BOOLEAN *)LocalAlloc(LMEM_FIXED, SizeInformation.AceCount * sizeof(*pKeepAce));
1046 if (!pKeepAce)
1047 {
1048 Ret = ERROR_NOT_ENOUGH_MEMORY;
1049 goto Cleanup;
1050 }
1051
1052 memset(pKeepAce, TRUE, SizeInformation.AceCount * sizeof(*pKeepAce));
1053 }
1054 else
1055 {
1056 ZeroMemory(&SizeInformation, sizeof(ACL_SIZE_INFORMATION));
1057 SizeInformation.AclBytesInUse = sizeof(ACL);
1058 }
1059
1060 /* Get size required for new entries */
1061 for (i = 0; i < cCountOfExplicitEntries; i++)
1062 {
1063 switch (pListOfExplicitEntries[i].grfAccessMode)
1064 {
1065 case REVOKE_ACCESS:
1066 case SET_ACCESS:
1067 /* Discard all accesses for the trustee... */
1068 pSid1 = GetTrusteeSid(&pListOfExplicitEntries[i].Trustee, &needToClean);
1069 for (i = 0; i < SizeInformation.AceCount; i++)
1070 {
1071 if (!pKeepAce[i])
1072 continue;
1073 if (!GetAce(OldAcl, i, (PVOID*)&pAce))
1074 {
1075 Ret = GetLastError();
1076 goto Cleanup;
1077 }
1078
1079 pSid2 = AccpGetAceSid(pAce);
1080 if (RtlEqualSid(pSid1, pSid2))
1081 {
1082 pKeepAce[i] = FALSE;
1083 SizeInformation.AclBytesInUse -= pAce->AceSize;
1084 }
1085 }
1086 if (needToClean) LocalFree((HLOCAL)pSid1);
1087 if (pListOfExplicitEntries[i].grfAccessMode == REVOKE_ACCESS)
1088 break;
1089 /* ...and replace by the current access */
1090 case GRANT_ACCESS:
1091 /* Add to ACL */
1092 pSid1 = GetTrusteeSid(&pListOfExplicitEntries[i].Trustee, &needToClean);
1093 SizeInformation.AclBytesInUse += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + RtlLengthSid(pSid1);
1094 if (needToClean) LocalFree((HLOCAL)pSid1);
1095 break;
1096 case DENY_ACCESS:
1097 /* Add to ACL */
1098 pSid1 = GetTrusteeSid(&pListOfExplicitEntries[i].Trustee, &needToClean);
1099 SizeInformation.AclBytesInUse += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + RtlLengthSid(pSid1);
1100 if (needToClean) LocalFree((HLOCAL)pSid1);
1101 break;
1102 case SET_AUDIT_SUCCESS:
1103 case SET_AUDIT_FAILURE:
1104 /* FIXME */
1105 DPRINT1("Case not implemented!\n");
1106 break;
1107 default:
1108 DPRINT1("Unknown access mode 0x%x. Ignoring it\n", pListOfExplicitEntries[i].grfAccessMode);
1109 break;
1110 }
1111 }
1112
1113 /* OK, now create the new ACL */
1114 DPRINT("Allocating %u bytes for the new ACL\n", SizeInformation.AclBytesInUse);
1115 pNew = (PACL)LocalAlloc(LMEM_FIXED, SizeInformation.AclBytesInUse);
1116 if (!pNew)
1117 {
1118 Ret = ERROR_NOT_ENOUGH_MEMORY;
1119 goto Cleanup;
1120 }
1121 if (!InitializeAcl(pNew, SizeInformation.AclBytesInUse, ACL_REVISION))
1122 {
1123 Ret = GetLastError();
1124 goto Cleanup;
1125 }
1126
1127 /* Fill it */
1128 /* 1a) New audit entries (SET_AUDIT_SUCCESS, SET_AUDIT_FAILURE) */
1129 /* FIXME */
1130
1131 /* 1b) Existing audit entries */
1132 /* FIXME */
1133
1134 /* 2a) New denied entries (DENY_ACCESS) */
1135 for (i = 0; i < cCountOfExplicitEntries; i++)
1136 {
1137 if (pListOfExplicitEntries[i].grfAccessMode == DENY_ACCESS)
1138 {
1139 /* FIXME: take care of pListOfExplicitEntries[i].grfInheritance */
1140 pSid1 = GetTrusteeSid(&pListOfExplicitEntries[i].Trustee, &needToClean);
1141 bRet = AddAccessDeniedAce(pNew, ACL_REVISION, pListOfExplicitEntries[i].grfAccessPermissions, pSid1);
1142 if (needToClean) LocalFree((HLOCAL)pSid1);
1143 if (!bRet)
1144 {
1145 Ret = GetLastError();
1146 goto Cleanup;
1147 }
1148 }
1149 }
1150
1151 /* 2b) Existing denied entries */
1152 /* FIXME */
1153
1154 /* 3a) New allow entries (GRANT_ACCESS, SET_ACCESS) */
1155 for (i = 0; i < cCountOfExplicitEntries; i++)
1156 {
1157 if (pListOfExplicitEntries[i].grfAccessMode == SET_ACCESS ||
1158 pListOfExplicitEntries[i].grfAccessMode == GRANT_ACCESS)
1159 {
1160 /* FIXME: take care of pListOfExplicitEntries[i].grfInheritance */
1161 pSid1 = GetTrusteeSid(&pListOfExplicitEntries[i].Trustee, &needToClean);
1162 bRet = AddAccessAllowedAce(pNew, ACL_REVISION, pListOfExplicitEntries[i].grfAccessPermissions, pSid1);
1163 if (needToClean) LocalFree((HLOCAL)pSid1);
1164 if (!bRet)
1165 {
1166 Ret = GetLastError();
1167 goto Cleanup;
1168 }
1169 }
1170 }
1171
1172 /* 3b) Existing allow entries */
1173 /* FIXME */
1174
1175 *NewAcl = pNew;
1176
1177 Cleanup:
1178 if (pKeepAce)
1179 LocalFree((HLOCAL)pKeepAce);
1180
1181 /* restore the last error code */
1182 SetLastError(LastErr);
1183
1184 return Ret;
1185 }
1186
1187
1188 /**********************************************************************
1189 * AccGetInheritanceSource EXPORTED
1190 *
1191 * @unimplemented
1192 */
1193 DWORD WINAPI
1194 AccGetInheritanceSource(LPWSTR pObjectName,
1195 SE_OBJECT_TYPE ObjectType,
1196 SECURITY_INFORMATION SecurityInfo,
1197 BOOL Container,
1198 GUID** pObjectClassGuids,
1199 DWORD GuidCount,
1200 PACL pAcl,
1201 PFN_OBJECT_MGR_FUNCTS pfnArray,
1202 PGENERIC_MAPPING pGenericMapping,
1203 PINHERITED_FROMW pInheritArray)
1204 {
1205 UNIMPLEMENTED;
1206 return ERROR_CALL_NOT_IMPLEMENTED;
1207 }
1208
1209
1210 /**********************************************************************
1211 * AccFreeIndexArray EXPORTED
1212 *
1213 * @implemented
1214 */
1215 DWORD WINAPI
1216 AccFreeIndexArray(PINHERITED_FROMW pInheritArray,
1217 USHORT AceCnt,
1218 PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL)
1219 {
1220 PINHERITED_FROMW pLast;
1221
1222 UNREFERENCED_PARAMETER(pfnArray);
1223
1224 pLast = pInheritArray + AceCnt;
1225 while (pInheritArray != pLast)
1226 {
1227 if (pInheritArray->AncestorName != NULL)
1228 {
1229 LocalFree((HLOCAL)pInheritArray->AncestorName);
1230 pInheritArray->AncestorName = NULL;
1231 }
1232
1233 pInheritArray++;
1234 }
1235
1236 return ERROR_SUCCESS;
1237 }
1238
1239
1240 /**********************************************************************
1241 * AccRewriteGetExplicitEntriesFromAcl EXPORTED
1242 *
1243 * @implemented
1244 */
1245 DWORD WINAPI
1246 AccRewriteGetExplicitEntriesFromAcl(PACL pacl,
1247 PULONG pcCountOfExplicitEntries,
1248 PEXPLICIT_ACCESS_W* pListOfExplicitEntries)
1249 {
1250 PACE_HEADER AceHeader;
1251 PSID Sid, SidTarget;
1252 ULONG ObjectAceCount = 0;
1253 POBJECTS_AND_SID ObjSid;
1254 SIZE_T Size;
1255 PEXPLICIT_ACCESS_W peaw;
1256 DWORD LastErr, SidLen;
1257 DWORD AceIndex = 0;
1258 DWORD ErrorCode = ERROR_SUCCESS;
1259
1260 /* save the last error code */
1261 LastErr = GetLastError();
1262
1263 if (pacl != NULL)
1264 {
1265 if (pacl->AceCount != 0)
1266 {
1267 Size = (SIZE_T)pacl->AceCount * sizeof(EXPLICIT_ACCESS_W);
1268
1269 /* calculate the space needed */
1270 while (GetAce(pacl,
1271 AceIndex,
1272 (LPVOID*)&AceHeader))
1273 {
1274 Sid = AccpGetAceSid(AceHeader);
1275 Size += GetLengthSid(Sid);
1276
1277 if (AccpIsObjectAce(AceHeader))
1278 ObjectAceCount++;
1279
1280 AceIndex++;
1281 }
1282
1283 Size += ObjectAceCount * sizeof(OBJECTS_AND_SID);
1284
1285 ASSERT(pacl->AceCount == AceIndex);
1286
1287 /* allocate the array */
1288 peaw = (PEXPLICIT_ACCESS_W)LocalAlloc(LMEM_FIXED,
1289 Size);
1290 if (peaw != NULL)
1291 {
1292 AceIndex = 0;
1293 ObjSid = (POBJECTS_AND_SID)(peaw + pacl->AceCount);
1294 SidTarget = (PSID)(ObjSid + ObjectAceCount);
1295
1296 /* initialize the array */
1297 while (GetAce(pacl,
1298 AceIndex,
1299 (LPVOID*)&AceHeader))
1300 {
1301 Sid = AccpGetAceSid(AceHeader);
1302 SidLen = GetLengthSid(Sid);
1303
1304 peaw[AceIndex].grfAccessPermissions = AccpGetAceAccessMask(AceHeader);
1305 peaw[AceIndex].grfAccessMode = AccpGetAceAccessMode(AceHeader);
1306 peaw[AceIndex].grfInheritance = AceHeader->AceFlags & VALID_INHERIT_FLAGS;
1307
1308 if (CopySid(SidLen,
1309 SidTarget,
1310 Sid))
1311 {
1312 if (AccpIsObjectAce(AceHeader))
1313 {
1314 BuildTrusteeWithObjectsAndSid(&peaw[AceIndex].Trustee,
1315 ObjSid++,
1316 AccpGetObjectAceObjectType(AceHeader),
1317 AccpGetObjectAceInheritedObjectType(AceHeader),
1318 SidTarget);
1319 }
1320 else
1321 {
1322 BuildTrusteeWithSid(&peaw[AceIndex].Trustee,
1323 SidTarget);
1324 }
1325
1326 SidTarget = (PSID)((ULONG_PTR)SidTarget + SidLen);
1327 }
1328 else
1329 {
1330 /* copying the SID failed, treat it as an fatal error... */
1331 ErrorCode = GetLastError();
1332
1333 /* free allocated resources */
1334 LocalFree(peaw);
1335 peaw = NULL;
1336 AceIndex = 0;
1337 break;
1338 }
1339
1340 AceIndex++;
1341 }
1342
1343 *pcCountOfExplicitEntries = AceIndex;
1344 *pListOfExplicitEntries = peaw;
1345 }
1346 else
1347 ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1348 }
1349 else
1350 {
1351 goto EmptyACL;
1352 }
1353 }
1354 else
1355 {
1356 EmptyACL:
1357 *pcCountOfExplicitEntries = 0;
1358 *pListOfExplicitEntries = NULL;
1359 }
1360
1361 /* restore the last error code */
1362 SetLastError(LastErr);
1363
1364 return ErrorCode;
1365 }
1366
1367
1368 /**********************************************************************
1369 * AccTreeResetNamedSecurityInfo EXPORTED
1370 *
1371 * @unimplemented
1372 */
1373 DWORD WINAPI
1374 AccTreeResetNamedSecurityInfo(LPWSTR pObjectName,
1375 SE_OBJECT_TYPE ObjectType,
1376 SECURITY_INFORMATION SecurityInfo,
1377 PSID pOwner,
1378 PSID pGroup,
1379 PACL pDacl,
1380 PACL pSacl,
1381 BOOL KeepExplicit,
1382 FN_PROGRESSW fnProgress,
1383 PROG_INVOKE_SETTING ProgressInvokeSetting,
1384 PVOID Args)
1385 {
1386 UNIMPLEMENTED;
1387 return ERROR_CALL_NOT_IMPLEMENTED;
1388 }
1389
1390
1391 BOOL WINAPI
1392 DllMain(IN HINSTANCE hinstDLL,
1393 IN DWORD dwReason,
1394 IN LPVOID lpvReserved)
1395 {
1396 switch (dwReason)
1397 {
1398 case DLL_PROCESS_ATTACH:
1399 hDllInstance = hinstDLL;
1400 DisableThreadLibraryCalls(hinstDLL);
1401 break;
1402
1403 case DLL_PROCESS_DETACH:
1404 break;
1405 }
1406 return TRUE;
1407 }
1408