Synchronize up to trunk's revision r57756.
[reactos.git] / subsystems / win / basesrv / server.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS/Win32 Base enviroment Subsystem Server
4 * FILE: subsystems/win/basesrv/server.c
5 * PURPOSE: Server APIs
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
7 */
8
9 #include "basesrv.h"
10
11 #define NDEBUG
12 #include <debug.h>
13
14 CSR_API(BaseSrvCreateProcess)
15 {
16 NTSTATUS Status;
17 PBASE_CREATE_PROCESS CreateProcessRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.CreateProcessRequest;
18 HANDLE ProcessHandle, ThreadHandle;
19 PCSR_THREAD CsrThread;
20 PCSR_PROCESS Process;
21 ULONG Flags = 0, VdmPower = 0, DebugFlags = 0;
22
23 /* Get the current client thread */
24 CsrThread = CsrGetClientThread();
25 ASSERT(CsrThread != NULL);
26
27 Process = CsrThread->Process;
28
29 /* Extract the flags out of the process handle */
30 Flags = (ULONG_PTR)CreateProcessRequest->ProcessHandle & 3;
31 CreateProcessRequest->ProcessHandle = (HANDLE)((ULONG_PTR)CreateProcessRequest->ProcessHandle & ~3);
32
33 /* Duplicate the process handle */
34 Status = NtDuplicateObject(Process->ProcessHandle,
35 CreateProcessRequest->ProcessHandle,
36 NtCurrentProcess(),
37 &ProcessHandle,
38 0,
39 0,
40 DUPLICATE_SAME_ACCESS);
41 if (!NT_SUCCESS(Status))
42 {
43 DPRINT1("Failed to duplicate process handle\n");
44 return Status;
45 }
46
47 /* Duplicate the thread handle */
48 Status = NtDuplicateObject(Process->ProcessHandle,
49 CreateProcessRequest->ThreadHandle,
50 NtCurrentProcess(),
51 &ThreadHandle,
52 0,
53 0,
54 DUPLICATE_SAME_ACCESS);
55 if (!NT_SUCCESS(Status))
56 {
57 DPRINT1("Failed to duplicate process handle\n");
58 NtClose(ProcessHandle);
59 return Status;
60 }
61
62 /* See if this is a VDM process */
63 if (VdmPower)
64 {
65 /* Request VDM powers */
66 Status = NtSetInformationProcess(ProcessHandle,
67 ProcessWx86Information,
68 &VdmPower,
69 sizeof(VdmPower));
70 if (!NT_SUCCESS(Status))
71 {
72 DPRINT1("Failed to get VDM powers\n");
73 NtClose(ProcessHandle);
74 NtClose(ThreadHandle);
75 return Status;
76 }
77 }
78
79 /* Flags conversion. FIXME: More need conversion */
80 if (CreateProcessRequest->CreationFlags & CREATE_NEW_PROCESS_GROUP)
81 {
82 DebugFlags |= CsrProcessCreateNewGroup;
83 }
84
85 /* FIXME: SxS Stuff */
86
87 /* Call CSRSRV to create the CSR_PROCESS structure and the first CSR_THREAD */
88 Status = CsrCreateProcess(ProcessHandle,
89 ThreadHandle,
90 &CreateProcessRequest->ClientId,
91 Process->NtSession,
92 DebugFlags,
93 NULL);
94 if (Status == STATUS_THREAD_IS_TERMINATING)
95 {
96 DPRINT1("Thread already dead\n");
97 return Status;
98 }
99
100 /* Check for other failures */
101 if (!NT_SUCCESS(Status))
102 {
103 DPRINT1("Failed to create process/thread structures: %lx\n", Status);
104 return Status;
105 }
106
107 /* FIXME: Should notify user32 */
108
109 /* FIXME: VDM vodoo */
110
111 /* Return the result of this operation */
112 return Status;
113 }
114
115 CSR_API(BaseSrvCreateThread)
116 {
117 NTSTATUS Status;
118 PBASE_CREATE_THREAD CreateThreadRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.CreateThreadRequest;
119 PCSR_THREAD CurrentThread;
120 HANDLE ThreadHandle;
121 PCSR_PROCESS CsrProcess;
122
123 /* Get the current CSR thread */
124 CurrentThread = CsrGetClientThread();
125 if (!CurrentThread)
126 {
127 DPRINT1("Server Thread TID: [%lx.%lx]\n",
128 CreateThreadRequest->ClientId.UniqueProcess,
129 CreateThreadRequest->ClientId.UniqueThread);
130 return STATUS_SUCCESS; // server-to-server
131 }
132
133 /* Get the CSR Process for this request */
134 CsrProcess = CurrentThread->Process;
135 if (CsrProcess->ClientId.UniqueProcess !=
136 CreateThreadRequest->ClientId.UniqueProcess)
137 {
138 /* This is a remote thread request -- is it within the server itself? */
139 if (CreateThreadRequest->ClientId.UniqueProcess == NtCurrentTeb()->ClientId.UniqueProcess)
140 {
141 /* Accept this without any further work */
142 return STATUS_SUCCESS;
143 }
144
145 /* Get the real CSR Process for the remote thread's process */
146 Status = CsrLockProcessByClientId(CreateThreadRequest->ClientId.UniqueProcess,
147 &CsrProcess);
148 if (!NT_SUCCESS(Status)) return Status;
149 }
150
151 /* Duplicate the thread handle so we can own it */
152 Status = NtDuplicateObject(CurrentThread->Process->ProcessHandle,
153 CreateThreadRequest->ThreadHandle,
154 NtCurrentProcess(),
155 &ThreadHandle,
156 0,
157 0,
158 DUPLICATE_SAME_ACCESS);
159 if (NT_SUCCESS(Status))
160 {
161 /* Call CSRSRV to tell it about the new thread */
162 Status = CsrCreateThread(CsrProcess,
163 ThreadHandle,
164 &CreateThreadRequest->ClientId,
165 TRUE);
166 }
167
168 /* Unlock the process and return */
169 if (CsrProcess != CurrentThread->Process) CsrUnlockProcess(CsrProcess);
170 return Status;
171 }
172
173 CSR_API(BaseSrvGetTempFile)
174 {
175 static UINT CsrGetTempFileUnique = 0;
176 PBASE_GET_TEMP_FILE GetTempFile = &((PBASE_API_MESSAGE)ApiMessage)->Data.GetTempFile;
177
178 /* Return 16-bits ID */
179 GetTempFile->UniqueID = (++CsrGetTempFileUnique & 0xFFFF);
180
181 DPRINT("Returning: %u\n", GetTempFile->UniqueID);
182
183 return STATUS_SUCCESS;
184 }
185
186 CSR_API(BaseSrvExitProcess)
187 {
188 PCSR_THREAD CsrThread = CsrGetClientThread();
189 ASSERT(CsrThread != NULL);
190
191 /* Set the special reply value so we don't reply this message back */
192 *Reply = 2;
193
194 /* Remove the CSR_THREADs and CSR_PROCESS */
195 return CsrDestroyProcess(&CsrThread->ClientId,
196 (NTSTATUS)((PBASE_API_MESSAGE)ApiMessage)->Data.ExitProcessRequest.uExitCode);
197 }
198
199 CSR_API(BaseSrvGetProcessShutdownParam)
200 {
201 PBASE_GET_PROCESS_SHUTDOWN_PARAMS GetShutdownParametersRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.GetShutdownParametersRequest;
202 PCSR_THREAD CsrThread = CsrGetClientThread();
203 ASSERT(CsrThread);
204
205 GetShutdownParametersRequest->Level = CsrThread->Process->ShutdownLevel;
206 GetShutdownParametersRequest->Flags = CsrThread->Process->ShutdownFlags;
207
208 return STATUS_SUCCESS;
209 }
210
211 CSR_API(BaseSrvSetProcessShutdownParam)
212 {
213 PBASE_SET_PROCESS_SHUTDOWN_PARAMS SetShutdownParametersRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.SetShutdownParametersRequest;
214 PCSR_THREAD CsrThread = CsrGetClientThread();
215 ASSERT(CsrThread);
216
217 CsrThread->Process->ShutdownLevel = SetShutdownParametersRequest->Level;
218 CsrThread->Process->ShutdownFlags = SetShutdownParametersRequest->Flags;
219
220 return STATUS_SUCCESS;
221 }
222
223
224 /***
225 *** Sound sentry
226 ***/
227
228 typedef BOOL (WINAPI *PUSER_SOUND_SENTRY)(VOID);
229 BOOL NTAPI FirstSoundSentry(VOID);
230
231 PUSER_SOUND_SENTRY _UserSoundSentry = FirstSoundSentry;
232
233 BOOL
234 NTAPI
235 FailSoundSentry(VOID)
236 {
237 /* In case the function can't be found/is unimplemented */
238 return FALSE;
239 }
240
241 BOOL
242 NTAPI
243 FirstSoundSentry(VOID)
244 {
245 UNICODE_STRING DllString = RTL_CONSTANT_STRING(L"winsrv");
246 STRING FuncString = RTL_CONSTANT_STRING("_UserSoundSentry");
247 HANDLE DllHandle;
248 NTSTATUS Status;
249 PUSER_SOUND_SENTRY NewSoundSentry = FailSoundSentry;
250
251 /* Load winsrv manually */
252 Status = LdrGetDllHandle(NULL, NULL, &DllString, &DllHandle);
253 if (NT_SUCCESS(Status))
254 {
255 /* If it was found, get SoundSentry export */
256 Status = LdrGetProcedureAddress(DllHandle,
257 &FuncString,
258 0,
259 (PVOID*)&NewSoundSentry);
260 }
261
262 /* Set it as the callback for the future, and call it */
263 _UserSoundSentry = NewSoundSentry;
264 return _UserSoundSentry();
265 }
266
267 CSR_API(BaseSrvSoundSentryNotification)
268 {
269 /* Call the API and see if it succeeds */
270 return _UserSoundSentry() ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
271 }
272
273
274 /***
275 *** Dos Devices (C) Pierre Schweitzer (pierre.schweitzer@reactos.org)
276 ***/
277
278 typedef struct tagBASE_DOS_DEVICE_HISTORY_ENTRY
279 {
280 UNICODE_STRING Device;
281 UNICODE_STRING Target;
282 LIST_ENTRY Entry;
283 } BASE_DOS_DEVICE_HISTORY_ENTRY, *PBASE_DOS_DEVICE_HISTORY_ENTRY;
284
285 LIST_ENTRY DosDeviceHistory;
286 RTL_CRITICAL_SECTION BaseDefineDosDeviceCritSec;
287
288 VOID BaseCleanupDefineDosDevice(VOID)
289 {
290 PLIST_ENTRY Entry, ListHead;
291 PBASE_DOS_DEVICE_HISTORY_ENTRY HistoryEntry;
292
293 (void) RtlDeleteCriticalSection(&BaseDefineDosDeviceCritSec);
294
295 ListHead = &DosDeviceHistory;
296 Entry = ListHead->Flink;
297 while (Entry != ListHead)
298 {
299 HistoryEntry = (PBASE_DOS_DEVICE_HISTORY_ENTRY)
300 CONTAINING_RECORD(Entry,
301 BASE_DOS_DEVICE_HISTORY_ENTRY,
302 Entry);
303 Entry = Entry->Flink;
304
305 if (HistoryEntry)
306 {
307 if (HistoryEntry->Target.Buffer)
308 (void) RtlFreeHeap(BaseSrvHeap,
309 0,
310 HistoryEntry->Target.Buffer);
311 if (HistoryEntry->Device.Buffer)
312 (void) RtlFreeHeap(BaseSrvHeap,
313 0,
314 HistoryEntry->Device.Buffer);
315 (void) RtlFreeHeap(BaseSrvHeap,
316 0,
317 HistoryEntry);
318 }
319 }
320 }
321
322 CSR_API(BaseSrvDefineDosDevice)
323 {
324 NTSTATUS Status;
325 PBASE_DEFINE_DOS_DEVICE DefineDosDeviceRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.DefineDosDeviceRequest;
326 OBJECT_ATTRIBUTES ObjectAttributes;
327 HANDLE LinkHandle = NULL;
328 UNICODE_STRING DeviceName = {0};
329 UNICODE_STRING RequestDeviceName = {0};
330 UNICODE_STRING LinkTarget = {0};
331 PUNICODE_STRING RequestLinkTarget;
332 ULONG Length;
333 SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
334 SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
335 PSECURITY_DESCRIPTOR SecurityDescriptor;
336 PACL Dacl;
337 PSID AdminSid;
338 PSID SystemSid;
339 PSID WorldSid;
340 ULONG SidLength;
341 PBASE_DOS_DEVICE_HISTORY_ENTRY HistoryEntry;
342 PLIST_ENTRY Entry;
343 PLIST_ENTRY ListHead;
344 BOOLEAN Matched, AddHistory;
345 DWORD dwFlags;
346 PWSTR lpBuffer;
347
348 DPRINT("CsrDefineDosDevice entered, Flags:%d, DeviceName:%wZ, TargetName:%wZ\n",
349 DefineDosDeviceRequest->dwFlags,
350 &DefineDosDeviceRequest->DeviceName,
351 &DefineDosDeviceRequest->TargetName);
352
353 Matched = AddHistory = FALSE;
354 HistoryEntry = NULL;
355 AdminSid = SystemSid = WorldSid = NULL;
356 SecurityDescriptor = NULL;
357 ListHead = &DosDeviceHistory;
358 dwFlags = DefineDosDeviceRequest->dwFlags;
359
360 /* Validate the flags */
361 if ( (dwFlags & 0xFFFFFFF0) ||
362 ((dwFlags & DDD_EXACT_MATCH_ON_REMOVE) &&
363 ! (dwFlags & DDD_REMOVE_DEFINITION)) )
364 {
365 return STATUS_INVALID_PARAMETER;
366 }
367
368 Status = RtlEnterCriticalSection(&BaseDefineDosDeviceCritSec);
369 if (! NT_SUCCESS(Status))
370 {
371 DPRINT1("RtlEnterCriticalSection() failed (Status %lx)\n",
372 Status);
373 return Status;
374 }
375
376 _SEH2_TRY
377 {
378 Status =
379 RtlUpcaseUnicodeString(&RequestDeviceName,
380 &DefineDosDeviceRequest->DeviceName,
381 TRUE);
382 if (! NT_SUCCESS(Status))
383 _SEH2_LEAVE;
384
385 RequestLinkTarget = &DefineDosDeviceRequest->TargetName;
386 lpBuffer = (PWSTR) RtlAllocateHeap(BaseSrvHeap,
387 HEAP_ZERO_MEMORY,
388 RequestDeviceName.MaximumLength + 5 * sizeof(WCHAR));
389 if (! lpBuffer)
390 {
391 DPRINT1("Failed to allocate memory\n");
392 Status = STATUS_NO_MEMORY;
393 _SEH2_LEAVE;
394 }
395
396 swprintf(lpBuffer,
397 L"\\??\\%wZ",
398 &RequestDeviceName);
399 RtlInitUnicodeString(&DeviceName,
400 lpBuffer);
401 InitializeObjectAttributes(&ObjectAttributes,
402 &DeviceName,
403 OBJ_CASE_INSENSITIVE,
404 NULL,
405 NULL);
406 Status = NtOpenSymbolicLinkObject(&LinkHandle,
407 DELETE | 0x1,
408 &ObjectAttributes);
409 if (NT_SUCCESS(Status))
410 {
411 Status = NtQuerySymbolicLinkObject(LinkHandle,
412 &LinkTarget,
413 &Length);
414 if (! NT_SUCCESS(Status) &&
415 Status == STATUS_BUFFER_TOO_SMALL)
416 {
417 LinkTarget.Length = 0;
418 LinkTarget.MaximumLength = Length;
419 LinkTarget.Buffer = (PWSTR)
420 RtlAllocateHeap(BaseSrvHeap,
421 HEAP_ZERO_MEMORY,
422 Length);
423 if (! LinkTarget.Buffer)
424 {
425 DPRINT1("Failed to allocate memory\n");
426 Status = STATUS_NO_MEMORY;
427 _SEH2_LEAVE;
428 }
429
430 Status = NtQuerySymbolicLinkObject(LinkHandle,
431 &LinkTarget,
432 &Length);
433 }
434
435 if (! NT_SUCCESS(Status))
436 {
437 DPRINT1("NtQuerySymbolicLinkObject(%wZ) failed (Status %lx)\n",
438 &DeviceName, Status);
439 _SEH2_LEAVE;
440 }
441
442 if ((dwFlags & DDD_REMOVE_DEFINITION))
443 {
444 /* If no target name specified we remove the current symlink target */
445 if (RequestLinkTarget->Length == 0)
446 Matched = TRUE;
447 else
448 {
449 if (dwFlags & DDD_EXACT_MATCH_ON_REMOVE)
450 Matched = ! RtlCompareUnicodeString(RequestLinkTarget,
451 &LinkTarget,
452 TRUE);
453 else
454 Matched = RtlPrefixUnicodeString(RequestLinkTarget,
455 &LinkTarget,
456 TRUE);
457 }
458
459 if (Matched && IsListEmpty(ListHead))
460 {
461 /* Current symlink target macthed and there is nothing to revert to */
462 RequestLinkTarget = NULL;
463 }
464 else if (Matched && ! IsListEmpty(ListHead))
465 {
466 /* Fetch the first history entry we come across for the device name */
467 /* This will become the current symlink target for the device name */
468 Matched = FALSE;
469 Entry = ListHead->Flink;
470 while (Entry != ListHead)
471 {
472 HistoryEntry = (PBASE_DOS_DEVICE_HISTORY_ENTRY)
473 CONTAINING_RECORD(Entry,
474 BASE_DOS_DEVICE_HISTORY_ENTRY,
475 Entry);
476 Matched =
477 ! RtlCompareUnicodeString(&RequestDeviceName,
478 &HistoryEntry->Device,
479 FALSE);
480 if (Matched)
481 {
482 RemoveEntryList(&HistoryEntry->Entry);
483 RequestLinkTarget = &HistoryEntry->Target;
484 break;
485 }
486 Entry = Entry->Flink;
487 HistoryEntry = NULL;
488 }
489
490 /* Nothing to revert to so delete the symlink */
491 if (! Matched)
492 RequestLinkTarget = NULL;
493 }
494 else if (! Matched)
495 {
496 /* Locate a previous symlink target as we did not get a hit earlier */
497 /* If we find one we need to remove it */
498 Entry = ListHead->Flink;
499 while (Entry != ListHead)
500 {
501 HistoryEntry = (PBASE_DOS_DEVICE_HISTORY_ENTRY)
502 CONTAINING_RECORD(Entry,
503 BASE_DOS_DEVICE_HISTORY_ENTRY,
504 Entry);
505 Matched =
506 ! RtlCompareUnicodeString(&RequestDeviceName,
507 &HistoryEntry->Device,
508 FALSE);
509 if (! Matched)
510 {
511 HistoryEntry = NULL;
512 Entry = Entry->Flink;
513 continue;
514 }
515
516 Matched = FALSE;
517 if (dwFlags & DDD_EXACT_MATCH_ON_REMOVE)
518 {
519 if (! RtlCompareUnicodeString(RequestLinkTarget,
520 &HistoryEntry->Target,
521 TRUE))
522 {
523 Matched = TRUE;
524 }
525 }
526 else if (RtlPrefixUnicodeString(RequestLinkTarget,
527 &HistoryEntry->Target,
528 TRUE))
529 {
530 Matched = TRUE;
531 }
532
533 if (Matched)
534 {
535 RemoveEntryList(&HistoryEntry->Entry);
536 break;
537 }
538 Entry = Entry->Flink;
539 HistoryEntry = NULL;
540 }
541
542 /* Leave existing symlink as is */
543 if (! Matched)
544 Status = STATUS_OBJECT_NAME_NOT_FOUND;
545 else
546 Status = STATUS_SUCCESS;
547 _SEH2_LEAVE;
548 }
549 }
550 else
551 {
552 AddHistory = TRUE;
553 }
554
555 Status = NtMakeTemporaryObject(LinkHandle);
556 if (! NT_SUCCESS(Status))
557 {
558 DPRINT1("NtMakeTemporaryObject(%wZ) failed (Status %lx)\n",
559 &DeviceName, Status);
560 _SEH2_LEAVE;
561 }
562
563 Status = NtClose(LinkHandle);
564 LinkHandle = NULL;
565 if (! NT_SUCCESS(Status))
566 {
567 DPRINT1("NtClose(%wZ) failed (Status %lx)\n",
568 &DeviceName, Status);
569 _SEH2_LEAVE;
570 }
571 }
572
573 /* Don't create symlink if we don't have a target */
574 if (! RequestLinkTarget || RequestLinkTarget->Length == 0)
575 _SEH2_LEAVE;
576
577 if (AddHistory)
578 {
579 HistoryEntry = (PBASE_DOS_DEVICE_HISTORY_ENTRY)
580 RtlAllocateHeap(BaseSrvHeap,
581 HEAP_ZERO_MEMORY,
582 sizeof(BASE_DOS_DEVICE_HISTORY_ENTRY));
583 if (! HistoryEntry)
584 {
585 DPRINT1("Failed to allocate memory\n");
586 Status = STATUS_NO_MEMORY;
587 _SEH2_LEAVE;
588 }
589
590 HistoryEntry->Target.Buffer =
591 RtlAllocateHeap(BaseSrvHeap,
592 HEAP_ZERO_MEMORY,
593 LinkTarget.Length);
594 if (! HistoryEntry->Target.Buffer)
595 {
596 DPRINT1("Failed to allocate memory\n");
597 Status = STATUS_NO_MEMORY;
598 _SEH2_LEAVE;
599 }
600 HistoryEntry->Target.Length =
601 HistoryEntry->Target.MaximumLength =
602 LinkTarget.Length;
603 RtlCopyUnicodeString(&HistoryEntry->Target,
604 &LinkTarget);
605
606 HistoryEntry->Device.Buffer =
607 RtlAllocateHeap(BaseSrvHeap,
608 HEAP_ZERO_MEMORY,
609 RequestDeviceName.Length);
610 if (! HistoryEntry->Device.Buffer)
611 {
612 DPRINT1("Failed to allocate memory\n");
613 Status = STATUS_NO_MEMORY;
614 _SEH2_LEAVE;
615 }
616 HistoryEntry->Device.Length =
617 HistoryEntry->Device.MaximumLength =
618 RequestDeviceName.Length;
619 RtlCopyUnicodeString(&HistoryEntry->Device,
620 &RequestDeviceName);
621
622 /* Remember previous symlink target for this device */
623 InsertHeadList(ListHead,
624 &HistoryEntry->Entry);
625 HistoryEntry = NULL;
626 }
627
628 RtlAllocateAndInitializeSid(&WorldAuthority,
629 1,
630 SECURITY_WORLD_RID,
631 SECURITY_NULL_RID,
632 SECURITY_NULL_RID,
633 SECURITY_NULL_RID,
634 SECURITY_NULL_RID,
635 SECURITY_NULL_RID,
636 SECURITY_NULL_RID,
637 SECURITY_NULL_RID,
638 &WorldSid);
639
640 RtlAllocateAndInitializeSid(&SystemAuthority,
641 1,
642 SECURITY_LOCAL_SYSTEM_RID,
643 SECURITY_NULL_RID,
644 SECURITY_NULL_RID,
645 SECURITY_NULL_RID,
646 SECURITY_NULL_RID,
647 SECURITY_NULL_RID,
648 SECURITY_NULL_RID,
649 SECURITY_NULL_RID,
650 &SystemSid);
651
652 RtlAllocateAndInitializeSid(&SystemAuthority,
653 2,
654 SECURITY_BUILTIN_DOMAIN_RID,
655 DOMAIN_ALIAS_RID_ADMINS,
656 SECURITY_NULL_RID,
657 SECURITY_NULL_RID,
658 SECURITY_NULL_RID,
659 SECURITY_NULL_RID,
660 SECURITY_NULL_RID,
661 SECURITY_NULL_RID,
662 &AdminSid);
663
664 SidLength = RtlLengthSid(SystemSid) +
665 RtlLengthSid(AdminSid) +
666 RtlLengthSid(WorldSid);
667 Length = sizeof(ACL) + SidLength + 3 * sizeof(ACCESS_ALLOWED_ACE);
668
669 SecurityDescriptor = RtlAllocateHeap(BaseSrvHeap,
670 0,
671 SECURITY_DESCRIPTOR_MIN_LENGTH + Length);
672 if (! SecurityDescriptor)
673 {
674 DPRINT1("Failed to allocate memory\n");
675 Status = STATUS_NO_MEMORY;
676 _SEH2_LEAVE;
677 }
678
679 Dacl = (PACL)((ULONG_PTR)SecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
680 Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
681 SECURITY_DESCRIPTOR_REVISION);
682 if (! NT_SUCCESS(Status))
683 {
684 DPRINT1("RtlCreateSecurityDescriptor() failed (Status %lx)\n",
685 Status);
686 _SEH2_LEAVE;
687 }
688
689 Status = RtlCreateAcl(Dacl,
690 Length,
691 ACL_REVISION);
692 if (! NT_SUCCESS(Status))
693 {
694 DPRINT1("RtlCreateAcl() failed (Status %lx)\n",
695 Status);
696 _SEH2_LEAVE;
697 }
698
699 (void) RtlAddAccessAllowedAce(Dacl,
700 ACL_REVISION,
701 GENERIC_ALL,
702 SystemSid);
703 (void) RtlAddAccessAllowedAce(Dacl,
704 ACL_REVISION,
705 GENERIC_ALL,
706 AdminSid);
707 (void) RtlAddAccessAllowedAce(Dacl,
708 ACL_REVISION,
709 STANDARD_RIGHTS_READ,
710 WorldSid);
711
712 Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
713 TRUE,
714 Dacl,
715 FALSE);
716 if (! NT_SUCCESS(Status))
717 {
718 DPRINT1("RtlSetDaclSecurityDescriptor() failed (Status %lx)\n",
719 Status);
720 _SEH2_LEAVE;
721 }
722
723 InitializeObjectAttributes(&ObjectAttributes,
724 &DeviceName,
725 OBJ_CASE_INSENSITIVE,
726 NULL,
727 SecurityDescriptor);
728 Status = NtCreateSymbolicLinkObject(&LinkHandle,
729 SYMBOLIC_LINK_ALL_ACCESS,
730 &ObjectAttributes,
731 RequestLinkTarget);
732 if (NT_SUCCESS(Status))
733 {
734 Status = NtMakePermanentObject(LinkHandle);
735 if (! NT_SUCCESS(Status))
736 {
737 DPRINT1("NtMakePermanentObject(%wZ) failed (Status %lx)\n",
738 &DeviceName, Status);
739 }
740 }
741 else
742 {
743 DPRINT1("NtCreateSymbolicLinkObject(%wZ) failed (Status %lx)\n",
744 &DeviceName, Status);
745 }
746 }
747 _SEH2_FINALLY
748 {
749 (void) RtlLeaveCriticalSection(&BaseDefineDosDeviceCritSec);
750 if (DeviceName.Buffer)
751 (void) RtlFreeHeap(BaseSrvHeap,
752 0,
753 DeviceName.Buffer);
754 if (LinkTarget.Buffer)
755 (void) RtlFreeHeap(BaseSrvHeap,
756 0,
757 LinkTarget.Buffer);
758 if (SecurityDescriptor)
759 (void) RtlFreeHeap(BaseSrvHeap,
760 0,
761 SecurityDescriptor);
762 if (LinkHandle)
763 (void) NtClose(LinkHandle);
764 if (SystemSid)
765 (void) RtlFreeSid(SystemSid);
766 if (AdminSid)
767 (void) RtlFreeSid(AdminSid);
768 if (WorldSid)
769 (void) RtlFreeSid(WorldSid);
770 RtlFreeUnicodeString(&RequestDeviceName);
771 if (HistoryEntry)
772 {
773 if (HistoryEntry->Target.Buffer)
774 (void) RtlFreeHeap(BaseSrvHeap,
775 0,
776 HistoryEntry->Target.Buffer);
777 if (HistoryEntry->Device.Buffer)
778 (void) RtlFreeHeap(BaseSrvHeap,
779 0,
780 HistoryEntry->Device.Buffer);
781 (void) RtlFreeHeap(BaseSrvHeap,
782 0,
783 HistoryEntry);
784 }
785 }
786 _SEH2_END
787
788 DPRINT("CsrDefineDosDevice Exit, Statux: 0x%x\n", Status);
789 return Status;
790 }
791
792
793
794
795
796
797 /* PUBLIC API *****************************************************************/
798
799 NTSTATUS NTAPI BaseSetProcessCreateNotify(IN BASE_PROCESS_CREATE_NOTIFY_ROUTINE ProcessCreateNotifyProc)
800 {
801 DPRINT("BASESRV: %s(%08lx) called\n", __FUNCTION__, ProcessCreateNotifyProc);
802 return STATUS_NOT_IMPLEMENTED;
803 }
804
805 /* EOF */