2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS/Win32 Base enviroment Subsystem Server
4 * FILE: subsystems/win/basesrv/server.c
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
14 CSR_API(BaseSrvCreateProcess
)
17 PBASE_CREATE_PROCESS CreateProcessRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.CreateProcessRequest
;
18 HANDLE ProcessHandle
, ThreadHandle
;
19 PCSR_THREAD CsrThread
;
21 ULONG Flags
= 0, VdmPower
= 0, DebugFlags
= 0;
23 /* Get the current client thread */
24 CsrThread
= CsrGetClientThread();
25 ASSERT(CsrThread
!= NULL
);
27 Process
= CsrThread
->Process
;
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);
33 /* Duplicate the process handle */
34 Status
= NtDuplicateObject(Process
->ProcessHandle
,
35 CreateProcessRequest
->ProcessHandle
,
40 DUPLICATE_SAME_ACCESS
);
41 if (!NT_SUCCESS(Status
))
43 DPRINT1("Failed to duplicate process handle\n");
47 /* Duplicate the thread handle */
48 Status
= NtDuplicateObject(Process
->ProcessHandle
,
49 CreateProcessRequest
->ThreadHandle
,
54 DUPLICATE_SAME_ACCESS
);
55 if (!NT_SUCCESS(Status
))
57 DPRINT1("Failed to duplicate process handle\n");
58 NtClose(ProcessHandle
);
62 /* See if this is a VDM process */
65 /* Request VDM powers */
66 Status
= NtSetInformationProcess(ProcessHandle
,
67 ProcessWx86Information
,
70 if (!NT_SUCCESS(Status
))
72 DPRINT1("Failed to get VDM powers\n");
73 NtClose(ProcessHandle
);
74 NtClose(ThreadHandle
);
79 /* Flags conversion. FIXME: More need conversion */
80 if (CreateProcessRequest
->CreationFlags
& CREATE_NEW_PROCESS_GROUP
)
82 DebugFlags
|= CsrProcessCreateNewGroup
;
86 DPRINT1("BaseSrvCreateProcess - Launching a Console process\n");
87 DebugFlags
|= CsrProcessIsConsoleApp
;
90 /* FIXME: SxS Stuff */
92 /* Call CSRSRV to create the CSR_PROCESS structure and the first CSR_THREAD */
93 Status
= CsrCreateProcess(ProcessHandle
,
95 &CreateProcessRequest
->ClientId
,
99 if (Status
== STATUS_THREAD_IS_TERMINATING
)
101 DPRINT1("Thread already dead\n");
103 /* Set the special reply value so we don't reply this message back */
104 *ReplyCode
= CsrReplyDeadClient
;
109 /* Check for other failures */
110 if (!NT_SUCCESS(Status
))
112 DPRINT1("Failed to create process/thread structures: %lx\n", Status
);
116 /* FIXME: Should notify user32 */
118 /* FIXME: VDM vodoo */
120 /* Return the result of this operation */
124 CSR_API(BaseSrvCreateThread
)
127 PBASE_CREATE_THREAD CreateThreadRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.CreateThreadRequest
;
128 PCSR_THREAD CurrentThread
;
130 PCSR_PROCESS CsrProcess
;
132 /* Get the current CSR thread */
133 CurrentThread
= CsrGetClientThread();
136 DPRINT1("Server Thread TID: [%lx.%lx]\n",
137 CreateThreadRequest
->ClientId
.UniqueProcess
,
138 CreateThreadRequest
->ClientId
.UniqueThread
);
139 return STATUS_SUCCESS
; // server-to-server
142 /* Get the CSR Process for this request */
143 CsrProcess
= CurrentThread
->Process
;
144 if (CsrProcess
->ClientId
.UniqueProcess
!=
145 CreateThreadRequest
->ClientId
.UniqueProcess
)
147 /* This is a remote thread request -- is it within the server itself? */
148 if (CreateThreadRequest
->ClientId
.UniqueProcess
== NtCurrentTeb()->ClientId
.UniqueProcess
)
150 /* Accept this without any further work */
151 return STATUS_SUCCESS
;
154 /* Get the real CSR Process for the remote thread's process */
155 Status
= CsrLockProcessByClientId(CreateThreadRequest
->ClientId
.UniqueProcess
,
157 if (!NT_SUCCESS(Status
)) return Status
;
160 /* Duplicate the thread handle so we can own it */
161 Status
= NtDuplicateObject(CurrentThread
->Process
->ProcessHandle
,
162 CreateThreadRequest
->ThreadHandle
,
167 DUPLICATE_SAME_ACCESS
);
168 if (NT_SUCCESS(Status
))
170 /* Call CSRSRV to tell it about the new thread */
171 Status
= CsrCreateThread(CsrProcess
,
173 &CreateThreadRequest
->ClientId
,
177 /* Unlock the process and return */
178 if (CsrProcess
!= CurrentThread
->Process
) CsrUnlockProcess(CsrProcess
);
182 CSR_API(BaseSrvGetTempFile
)
184 static UINT CsrGetTempFileUnique
= 0;
185 PBASE_GET_TEMP_FILE GetTempFile
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.GetTempFile
;
187 /* Return 16-bits ID */
188 GetTempFile
->UniqueID
= (++CsrGetTempFileUnique
& 0xFFFF);
190 DPRINT("Returning: %u\n", GetTempFile
->UniqueID
);
192 return STATUS_SUCCESS
;
195 CSR_API(BaseSrvExitProcess
)
197 PCSR_THREAD CsrThread
= CsrGetClientThread();
198 ASSERT(CsrThread
!= NULL
);
200 /* Set the special reply value so we don't reply this message back */
201 *ReplyCode
= CsrReplyDeadClient
;
203 /* Remove the CSR_THREADs and CSR_PROCESS */
204 return CsrDestroyProcess(&CsrThread
->ClientId
,
205 (NTSTATUS
)((PBASE_API_MESSAGE
)ApiMessage
)->Data
.ExitProcessRequest
.uExitCode
);
208 CSR_API(BaseSrvGetProcessShutdownParam
)
210 PBASE_GET_PROCESS_SHUTDOWN_PARAMS GetShutdownParametersRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.GetShutdownParametersRequest
;
211 PCSR_THREAD CsrThread
= CsrGetClientThread();
214 GetShutdownParametersRequest
->Level
= CsrThread
->Process
->ShutdownLevel
;
215 GetShutdownParametersRequest
->Flags
= CsrThread
->Process
->ShutdownFlags
;
217 return STATUS_SUCCESS
;
220 CSR_API(BaseSrvSetProcessShutdownParam
)
222 PBASE_SET_PROCESS_SHUTDOWN_PARAMS SetShutdownParametersRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.SetShutdownParametersRequest
;
223 PCSR_THREAD CsrThread
= CsrGetClientThread();
226 CsrThread
->Process
->ShutdownLevel
= SetShutdownParametersRequest
->Level
;
227 CsrThread
->Process
->ShutdownFlags
= SetShutdownParametersRequest
->Flags
;
229 return STATUS_SUCCESS
;
237 typedef BOOL (WINAPI
*PUSER_SOUND_SENTRY
)(VOID
);
238 BOOL NTAPI
FirstSoundSentry(VOID
);
240 PUSER_SOUND_SENTRY _UserSoundSentry
= FirstSoundSentry
;
244 FailSoundSentry(VOID
)
246 /* In case the function can't be found/is unimplemented */
252 FirstSoundSentry(VOID
)
254 UNICODE_STRING DllString
= RTL_CONSTANT_STRING(L
"winsrv");
255 STRING FuncString
= RTL_CONSTANT_STRING("_UserSoundSentry");
258 PUSER_SOUND_SENTRY NewSoundSentry
= FailSoundSentry
;
260 /* Load winsrv manually */
261 Status
= LdrGetDllHandle(NULL
, NULL
, &DllString
, &DllHandle
);
262 if (NT_SUCCESS(Status
))
264 /* If it was found, get SoundSentry export */
265 Status
= LdrGetProcedureAddress(DllHandle
,
268 (PVOID
*)&NewSoundSentry
);
271 /* Set it as the callback for the future, and call it */
272 _UserSoundSentry
= NewSoundSentry
;
273 return _UserSoundSentry();
276 CSR_API(BaseSrvSoundSentryNotification
)
278 /* Call the API and see if it succeeds */
279 return _UserSoundSentry() ? STATUS_SUCCESS
: STATUS_ACCESS_DENIED
;
284 *** Dos Devices (C) Pierre Schweitzer (pierre.schweitzer@reactos.org)
287 typedef struct tagBASE_DOS_DEVICE_HISTORY_ENTRY
289 UNICODE_STRING Device
;
290 UNICODE_STRING Target
;
292 } BASE_DOS_DEVICE_HISTORY_ENTRY
, *PBASE_DOS_DEVICE_HISTORY_ENTRY
;
294 LIST_ENTRY DosDeviceHistory
;
295 RTL_CRITICAL_SECTION BaseDefineDosDeviceCritSec
;
297 VOID
BaseCleanupDefineDosDevice(VOID
)
299 PLIST_ENTRY Entry
, ListHead
;
300 PBASE_DOS_DEVICE_HISTORY_ENTRY HistoryEntry
;
302 (void) RtlDeleteCriticalSection(&BaseDefineDosDeviceCritSec
);
304 ListHead
= &DosDeviceHistory
;
305 Entry
= ListHead
->Flink
;
306 while (Entry
!= ListHead
)
308 HistoryEntry
= (PBASE_DOS_DEVICE_HISTORY_ENTRY
)
309 CONTAINING_RECORD(Entry
,
310 BASE_DOS_DEVICE_HISTORY_ENTRY
,
312 Entry
= Entry
->Flink
;
316 if (HistoryEntry
->Target
.Buffer
)
317 (void) RtlFreeHeap(BaseSrvHeap
,
319 HistoryEntry
->Target
.Buffer
);
320 if (HistoryEntry
->Device
.Buffer
)
321 (void) RtlFreeHeap(BaseSrvHeap
,
323 HistoryEntry
->Device
.Buffer
);
324 (void) RtlFreeHeap(BaseSrvHeap
,
331 CSR_API(BaseSrvDefineDosDevice
)
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
;
342 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
343 SID_IDENTIFIER_AUTHORITY SystemAuthority
= {SECURITY_NT_AUTHORITY
};
344 PSECURITY_DESCRIPTOR SecurityDescriptor
;
350 PBASE_DOS_DEVICE_HISTORY_ENTRY HistoryEntry
;
352 PLIST_ENTRY ListHead
;
353 BOOLEAN Matched
, AddHistory
;
357 DPRINT("CsrDefineDosDevice entered, Flags:%d, DeviceName:%wZ, TargetName:%wZ\n",
358 DefineDosDeviceRequest
->dwFlags
,
359 &DefineDosDeviceRequest
->DeviceName
,
360 &DefineDosDeviceRequest
->TargetName
);
362 Matched
= AddHistory
= FALSE
;
364 AdminSid
= SystemSid
= WorldSid
= NULL
;
365 SecurityDescriptor
= NULL
;
366 ListHead
= &DosDeviceHistory
;
367 dwFlags
= DefineDosDeviceRequest
->dwFlags
;
369 /* Validate the flags */
370 if ( (dwFlags
& 0xFFFFFFF0) ||
371 ((dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
) &&
372 ! (dwFlags
& DDD_REMOVE_DEFINITION
)) )
374 return STATUS_INVALID_PARAMETER
;
377 Status
= RtlEnterCriticalSection(&BaseDefineDosDeviceCritSec
);
378 if (! NT_SUCCESS(Status
))
380 DPRINT1("RtlEnterCriticalSection() failed (Status %lx)\n",
388 RtlUpcaseUnicodeString(&RequestDeviceName
,
389 &DefineDosDeviceRequest
->DeviceName
,
391 if (! NT_SUCCESS(Status
))
394 RequestLinkTarget
= &DefineDosDeviceRequest
->TargetName
;
395 lpBuffer
= (PWSTR
) RtlAllocateHeap(BaseSrvHeap
,
397 RequestDeviceName
.MaximumLength
+ 5 * sizeof(WCHAR
));
400 DPRINT1("Failed to allocate memory\n");
401 Status
= STATUS_NO_MEMORY
;
408 RtlInitUnicodeString(&DeviceName
,
410 InitializeObjectAttributes(&ObjectAttributes
,
412 OBJ_CASE_INSENSITIVE
,
415 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
418 if (NT_SUCCESS(Status
))
420 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
423 if (! NT_SUCCESS(Status
) &&
424 Status
== STATUS_BUFFER_TOO_SMALL
)
426 LinkTarget
.Length
= 0;
427 LinkTarget
.MaximumLength
= Length
;
428 LinkTarget
.Buffer
= (PWSTR
)
429 RtlAllocateHeap(BaseSrvHeap
,
432 if (! LinkTarget
.Buffer
)
434 DPRINT1("Failed to allocate memory\n");
435 Status
= STATUS_NO_MEMORY
;
439 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
444 if (! NT_SUCCESS(Status
))
446 DPRINT1("NtQuerySymbolicLinkObject(%wZ) failed (Status %lx)\n",
447 &DeviceName
, Status
);
451 if ((dwFlags
& DDD_REMOVE_DEFINITION
))
453 /* If no target name specified we remove the current symlink target */
454 if (RequestLinkTarget
->Length
== 0)
458 if (dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
)
459 Matched
= ! RtlCompareUnicodeString(RequestLinkTarget
,
463 Matched
= RtlPrefixUnicodeString(RequestLinkTarget
,
468 if (Matched
&& IsListEmpty(ListHead
))
470 /* Current symlink target macthed and there is nothing to revert to */
471 RequestLinkTarget
= NULL
;
473 else if (Matched
&& ! IsListEmpty(ListHead
))
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 */
478 Entry
= ListHead
->Flink
;
479 while (Entry
!= ListHead
)
481 HistoryEntry
= (PBASE_DOS_DEVICE_HISTORY_ENTRY
)
482 CONTAINING_RECORD(Entry
,
483 BASE_DOS_DEVICE_HISTORY_ENTRY
,
486 ! RtlCompareUnicodeString(&RequestDeviceName
,
487 &HistoryEntry
->Device
,
491 RemoveEntryList(&HistoryEntry
->Entry
);
492 RequestLinkTarget
= &HistoryEntry
->Target
;
495 Entry
= Entry
->Flink
;
499 /* Nothing to revert to so delete the symlink */
501 RequestLinkTarget
= NULL
;
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
)
510 HistoryEntry
= (PBASE_DOS_DEVICE_HISTORY_ENTRY
)
511 CONTAINING_RECORD(Entry
,
512 BASE_DOS_DEVICE_HISTORY_ENTRY
,
515 ! RtlCompareUnicodeString(&RequestDeviceName
,
516 &HistoryEntry
->Device
,
521 Entry
= Entry
->Flink
;
526 if (dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
)
528 if (! RtlCompareUnicodeString(RequestLinkTarget
,
529 &HistoryEntry
->Target
,
535 else if (RtlPrefixUnicodeString(RequestLinkTarget
,
536 &HistoryEntry
->Target
,
544 RemoveEntryList(&HistoryEntry
->Entry
);
547 Entry
= Entry
->Flink
;
551 /* Leave existing symlink as is */
553 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
555 Status
= STATUS_SUCCESS
;
564 Status
= NtMakeTemporaryObject(LinkHandle
);
565 if (! NT_SUCCESS(Status
))
567 DPRINT1("NtMakeTemporaryObject(%wZ) failed (Status %lx)\n",
568 &DeviceName
, Status
);
572 Status
= NtClose(LinkHandle
);
574 if (! NT_SUCCESS(Status
))
576 DPRINT1("NtClose(%wZ) failed (Status %lx)\n",
577 &DeviceName
, Status
);
582 /* Don't create symlink if we don't have a target */
583 if (! RequestLinkTarget
|| RequestLinkTarget
->Length
== 0)
588 HistoryEntry
= (PBASE_DOS_DEVICE_HISTORY_ENTRY
)
589 RtlAllocateHeap(BaseSrvHeap
,
591 sizeof(BASE_DOS_DEVICE_HISTORY_ENTRY
));
594 DPRINT1("Failed to allocate memory\n");
595 Status
= STATUS_NO_MEMORY
;
599 HistoryEntry
->Target
.Buffer
=
600 RtlAllocateHeap(BaseSrvHeap
,
603 if (! HistoryEntry
->Target
.Buffer
)
605 DPRINT1("Failed to allocate memory\n");
606 Status
= STATUS_NO_MEMORY
;
609 HistoryEntry
->Target
.Length
=
610 HistoryEntry
->Target
.MaximumLength
=
612 RtlCopyUnicodeString(&HistoryEntry
->Target
,
615 HistoryEntry
->Device
.Buffer
=
616 RtlAllocateHeap(BaseSrvHeap
,
618 RequestDeviceName
.Length
);
619 if (! HistoryEntry
->Device
.Buffer
)
621 DPRINT1("Failed to allocate memory\n");
622 Status
= STATUS_NO_MEMORY
;
625 HistoryEntry
->Device
.Length
=
626 HistoryEntry
->Device
.MaximumLength
=
627 RequestDeviceName
.Length
;
628 RtlCopyUnicodeString(&HistoryEntry
->Device
,
631 /* Remember previous symlink target for this device */
632 InsertHeadList(ListHead
,
633 &HistoryEntry
->Entry
);
637 RtlAllocateAndInitializeSid(&WorldAuthority
,
649 RtlAllocateAndInitializeSid(&SystemAuthority
,
651 SECURITY_LOCAL_SYSTEM_RID
,
661 RtlAllocateAndInitializeSid(&SystemAuthority
,
663 SECURITY_BUILTIN_DOMAIN_RID
,
664 DOMAIN_ALIAS_RID_ADMINS
,
673 SidLength
= RtlLengthSid(SystemSid
) +
674 RtlLengthSid(AdminSid
) +
675 RtlLengthSid(WorldSid
);
676 Length
= sizeof(ACL
) + SidLength
+ 3 * sizeof(ACCESS_ALLOWED_ACE
);
678 SecurityDescriptor
= RtlAllocateHeap(BaseSrvHeap
,
680 SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
681 if (! SecurityDescriptor
)
683 DPRINT1("Failed to allocate memory\n");
684 Status
= STATUS_NO_MEMORY
;
688 Dacl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
689 Status
= RtlCreateSecurityDescriptor(SecurityDescriptor
,
690 SECURITY_DESCRIPTOR_REVISION
);
691 if (! NT_SUCCESS(Status
))
693 DPRINT1("RtlCreateSecurityDescriptor() failed (Status %lx)\n",
698 Status
= RtlCreateAcl(Dacl
,
701 if (! NT_SUCCESS(Status
))
703 DPRINT1("RtlCreateAcl() failed (Status %lx)\n",
708 (void) RtlAddAccessAllowedAce(Dacl
,
712 (void) RtlAddAccessAllowedAce(Dacl
,
716 (void) RtlAddAccessAllowedAce(Dacl
,
718 STANDARD_RIGHTS_READ
,
721 Status
= RtlSetDaclSecurityDescriptor(SecurityDescriptor
,
725 if (! NT_SUCCESS(Status
))
727 DPRINT1("RtlSetDaclSecurityDescriptor() failed (Status %lx)\n",
732 InitializeObjectAttributes(&ObjectAttributes
,
734 OBJ_CASE_INSENSITIVE
,
737 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
738 SYMBOLIC_LINK_ALL_ACCESS
,
741 if (NT_SUCCESS(Status
))
743 Status
= NtMakePermanentObject(LinkHandle
);
744 if (! NT_SUCCESS(Status
))
746 DPRINT1("NtMakePermanentObject(%wZ) failed (Status %lx)\n",
747 &DeviceName
, Status
);
752 DPRINT1("NtCreateSymbolicLinkObject(%wZ) failed (Status %lx)\n",
753 &DeviceName
, Status
);
758 (void) RtlLeaveCriticalSection(&BaseDefineDosDeviceCritSec
);
759 if (DeviceName
.Buffer
)
760 (void) RtlFreeHeap(BaseSrvHeap
,
763 if (LinkTarget
.Buffer
)
764 (void) RtlFreeHeap(BaseSrvHeap
,
767 if (SecurityDescriptor
)
768 (void) RtlFreeHeap(BaseSrvHeap
,
772 (void) NtClose(LinkHandle
);
774 (void) RtlFreeSid(SystemSid
);
776 (void) RtlFreeSid(AdminSid
);
778 (void) RtlFreeSid(WorldSid
);
779 RtlFreeUnicodeString(&RequestDeviceName
);
782 if (HistoryEntry
->Target
.Buffer
)
783 (void) RtlFreeHeap(BaseSrvHeap
,
785 HistoryEntry
->Target
.Buffer
);
786 if (HistoryEntry
->Device
.Buffer
)
787 (void) RtlFreeHeap(BaseSrvHeap
,
789 HistoryEntry
->Device
.Buffer
);
790 (void) RtlFreeHeap(BaseSrvHeap
,
797 DPRINT("CsrDefineDosDevice Exit, Statux: 0x%x\n", Status
);
806 /* PUBLIC API *****************************************************************/
808 NTSTATUS NTAPI
BaseSetProcessCreateNotify(IN BASE_PROCESS_CREATE_NOTIFY_ROUTINE ProcessCreateNotifyProc
)
810 DPRINT("BASESRV: %s(%08lx) called\n", __FUNCTION__
, ProcessCreateNotifyProc
);
811 return STATUS_NOT_IMPLEMENTED
;