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