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