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