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
;
85 /* FIXME: SxS Stuff */
87 /* Call CSRSRV to create the CSR_PROCESS structure and the first CSR_THREAD */
88 Status
= CsrCreateProcess(ProcessHandle
,
90 &CreateProcessRequest
->ClientId
,
94 if (Status
== STATUS_THREAD_IS_TERMINATING
)
96 DPRINT1("Thread already dead\n");
98 /* Set the special reply value so we don't reply this message back */
99 *ReplyCode
= CsrReplyDeadClient
;
104 /* Check for other failures */
105 if (!NT_SUCCESS(Status
))
107 DPRINT1("Failed to create process/thread structures: %lx\n", Status
);
111 /* FIXME: Should notify user32 */
113 /* FIXME: VDM vodoo */
115 /* Return the result of this operation */
119 CSR_API(BaseSrvCreateThread
)
122 PBASE_CREATE_THREAD CreateThreadRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.CreateThreadRequest
;
123 PCSR_THREAD CurrentThread
;
125 PCSR_PROCESS CsrProcess
;
127 /* Get the current CSR thread */
128 CurrentThread
= CsrGetClientThread();
131 DPRINT1("Server Thread TID: [%lx.%lx]\n",
132 CreateThreadRequest
->ClientId
.UniqueProcess
,
133 CreateThreadRequest
->ClientId
.UniqueThread
);
134 return STATUS_SUCCESS
; // server-to-server
137 /* Get the CSR Process for this request */
138 CsrProcess
= CurrentThread
->Process
;
139 if (CsrProcess
->ClientId
.UniqueProcess
!=
140 CreateThreadRequest
->ClientId
.UniqueProcess
)
142 /* This is a remote thread request -- is it within the server itself? */
143 if (CreateThreadRequest
->ClientId
.UniqueProcess
== NtCurrentTeb()->ClientId
.UniqueProcess
)
145 /* Accept this without any further work */
146 return STATUS_SUCCESS
;
149 /* Get the real CSR Process for the remote thread's process */
150 Status
= CsrLockProcessByClientId(CreateThreadRequest
->ClientId
.UniqueProcess
,
152 if (!NT_SUCCESS(Status
)) return Status
;
155 /* Duplicate the thread handle so we can own it */
156 Status
= NtDuplicateObject(CurrentThread
->Process
->ProcessHandle
,
157 CreateThreadRequest
->ThreadHandle
,
162 DUPLICATE_SAME_ACCESS
);
163 if (NT_SUCCESS(Status
))
165 /* Call CSRSRV to tell it about the new thread */
166 Status
= CsrCreateThread(CsrProcess
,
168 &CreateThreadRequest
->ClientId
,
172 /* Unlock the process and return */
173 if (CsrProcess
!= CurrentThread
->Process
) CsrUnlockProcess(CsrProcess
);
177 CSR_API(BaseSrvGetTempFile
)
179 static UINT CsrGetTempFileUnique
= 0;
180 PBASE_GET_TEMP_FILE GetTempFile
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.GetTempFile
;
182 /* Return 16-bits ID */
183 GetTempFile
->UniqueID
= (++CsrGetTempFileUnique
& 0xFFFF);
185 DPRINT("Returning: %u\n", GetTempFile
->UniqueID
);
187 return STATUS_SUCCESS
;
190 CSR_API(BaseSrvExitProcess
)
192 PCSR_THREAD CsrThread
= CsrGetClientThread();
193 ASSERT(CsrThread
!= NULL
);
195 /* Set the special reply value so we don't reply this message back */
196 *ReplyCode
= CsrReplyDeadClient
;
198 /* Remove the CSR_THREADs and CSR_PROCESS */
199 return CsrDestroyProcess(&CsrThread
->ClientId
,
200 (NTSTATUS
)((PBASE_API_MESSAGE
)ApiMessage
)->Data
.ExitProcessRequest
.uExitCode
);
203 CSR_API(BaseSrvGetProcessShutdownParam
)
205 PBASE_GET_PROCESS_SHUTDOWN_PARAMS GetShutdownParametersRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.GetShutdownParametersRequest
;
206 PCSR_THREAD CsrThread
= CsrGetClientThread();
209 GetShutdownParametersRequest
->Level
= CsrThread
->Process
->ShutdownLevel
;
210 GetShutdownParametersRequest
->Flags
= CsrThread
->Process
->ShutdownFlags
;
212 return STATUS_SUCCESS
;
215 CSR_API(BaseSrvSetProcessShutdownParam
)
217 PBASE_SET_PROCESS_SHUTDOWN_PARAMS SetShutdownParametersRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.SetShutdownParametersRequest
;
218 PCSR_THREAD CsrThread
= CsrGetClientThread();
221 CsrThread
->Process
->ShutdownLevel
= SetShutdownParametersRequest
->Level
;
222 CsrThread
->Process
->ShutdownFlags
= SetShutdownParametersRequest
->Flags
;
224 return STATUS_SUCCESS
;
232 typedef BOOL (WINAPI
*PUSER_SOUND_SENTRY
)(VOID
);
233 BOOL NTAPI
FirstSoundSentry(VOID
);
235 PUSER_SOUND_SENTRY _UserSoundSentry
= FirstSoundSentry
;
239 FailSoundSentry(VOID
)
241 /* In case the function can't be found/is unimplemented */
247 FirstSoundSentry(VOID
)
249 UNICODE_STRING DllString
= RTL_CONSTANT_STRING(L
"winsrv");
250 STRING FuncString
= RTL_CONSTANT_STRING("_UserSoundSentry");
253 PUSER_SOUND_SENTRY NewSoundSentry
= FailSoundSentry
;
255 /* Load winsrv manually */
256 Status
= LdrGetDllHandle(NULL
, NULL
, &DllString
, &DllHandle
);
257 if (NT_SUCCESS(Status
))
259 /* If it was found, get SoundSentry export */
260 Status
= LdrGetProcedureAddress(DllHandle
,
263 (PVOID
*)&NewSoundSentry
);
266 /* Set it as the callback for the future, and call it */
267 _UserSoundSentry
= NewSoundSentry
;
268 return _UserSoundSentry();
271 CSR_API(BaseSrvSoundSentryNotification
)
273 /* Call the API and see if it succeeds */
274 return _UserSoundSentry() ? STATUS_SUCCESS
: STATUS_ACCESS_DENIED
;
279 *** Dos Devices (C) Pierre Schweitzer (pierre.schweitzer@reactos.org)
282 typedef struct tagBASE_DOS_DEVICE_HISTORY_ENTRY
284 UNICODE_STRING Device
;
285 UNICODE_STRING Target
;
287 } BASE_DOS_DEVICE_HISTORY_ENTRY
, *PBASE_DOS_DEVICE_HISTORY_ENTRY
;
289 LIST_ENTRY DosDeviceHistory
;
290 RTL_CRITICAL_SECTION BaseDefineDosDeviceCritSec
;
292 VOID
BaseCleanupDefineDosDevice(VOID
)
294 PLIST_ENTRY Entry
, ListHead
;
295 PBASE_DOS_DEVICE_HISTORY_ENTRY HistoryEntry
;
297 (void) RtlDeleteCriticalSection(&BaseDefineDosDeviceCritSec
);
299 ListHead
= &DosDeviceHistory
;
300 Entry
= ListHead
->Flink
;
301 while (Entry
!= ListHead
)
303 HistoryEntry
= (PBASE_DOS_DEVICE_HISTORY_ENTRY
)
304 CONTAINING_RECORD(Entry
,
305 BASE_DOS_DEVICE_HISTORY_ENTRY
,
307 Entry
= Entry
->Flink
;
311 if (HistoryEntry
->Target
.Buffer
)
312 (void) RtlFreeHeap(BaseSrvHeap
,
314 HistoryEntry
->Target
.Buffer
);
315 if (HistoryEntry
->Device
.Buffer
)
316 (void) RtlFreeHeap(BaseSrvHeap
,
318 HistoryEntry
->Device
.Buffer
);
319 (void) RtlFreeHeap(BaseSrvHeap
,
326 CSR_API(BaseSrvDefineDosDevice
)
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
;
337 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
338 SID_IDENTIFIER_AUTHORITY SystemAuthority
= {SECURITY_NT_AUTHORITY
};
339 PSECURITY_DESCRIPTOR SecurityDescriptor
;
345 PBASE_DOS_DEVICE_HISTORY_ENTRY HistoryEntry
;
347 PLIST_ENTRY ListHead
;
348 BOOLEAN Matched
, AddHistory
;
352 DPRINT("CsrDefineDosDevice entered, Flags:%d, DeviceName:%wZ, TargetName:%wZ\n",
353 DefineDosDeviceRequest
->dwFlags
,
354 &DefineDosDeviceRequest
->DeviceName
,
355 &DefineDosDeviceRequest
->TargetName
);
357 Matched
= AddHistory
= FALSE
;
359 AdminSid
= SystemSid
= WorldSid
= NULL
;
360 SecurityDescriptor
= NULL
;
361 ListHead
= &DosDeviceHistory
;
362 dwFlags
= DefineDosDeviceRequest
->dwFlags
;
364 /* Validate the flags */
365 if ( (dwFlags
& 0xFFFFFFF0) ||
366 ((dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
) &&
367 ! (dwFlags
& DDD_REMOVE_DEFINITION
)) )
369 return STATUS_INVALID_PARAMETER
;
372 Status
= RtlEnterCriticalSection(&BaseDefineDosDeviceCritSec
);
373 if (! NT_SUCCESS(Status
))
375 DPRINT1("RtlEnterCriticalSection() failed (Status %lx)\n",
383 RtlUpcaseUnicodeString(&RequestDeviceName
,
384 &DefineDosDeviceRequest
->DeviceName
,
386 if (! NT_SUCCESS(Status
))
389 RequestLinkTarget
= &DefineDosDeviceRequest
->TargetName
;
390 lpBuffer
= (PWSTR
) RtlAllocateHeap(BaseSrvHeap
,
392 RequestDeviceName
.MaximumLength
+ 5 * sizeof(WCHAR
));
395 DPRINT1("Failed to allocate memory\n");
396 Status
= STATUS_NO_MEMORY
;
403 RtlInitUnicodeString(&DeviceName
,
405 InitializeObjectAttributes(&ObjectAttributes
,
407 OBJ_CASE_INSENSITIVE
,
410 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
413 if (NT_SUCCESS(Status
))
415 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
418 if (! NT_SUCCESS(Status
) &&
419 Status
== STATUS_BUFFER_TOO_SMALL
)
421 LinkTarget
.Length
= 0;
422 LinkTarget
.MaximumLength
= Length
;
423 LinkTarget
.Buffer
= (PWSTR
)
424 RtlAllocateHeap(BaseSrvHeap
,
427 if (! LinkTarget
.Buffer
)
429 DPRINT1("Failed to allocate memory\n");
430 Status
= STATUS_NO_MEMORY
;
434 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
439 if (! NT_SUCCESS(Status
))
441 DPRINT1("NtQuerySymbolicLinkObject(%wZ) failed (Status %lx)\n",
442 &DeviceName
, Status
);
446 if ((dwFlags
& DDD_REMOVE_DEFINITION
))
448 /* If no target name specified we remove the current symlink target */
449 if (RequestLinkTarget
->Length
== 0)
453 if (dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
)
454 Matched
= ! RtlCompareUnicodeString(RequestLinkTarget
,
458 Matched
= RtlPrefixUnicodeString(RequestLinkTarget
,
463 if (Matched
&& IsListEmpty(ListHead
))
465 /* Current symlink target macthed and there is nothing to revert to */
466 RequestLinkTarget
= NULL
;
468 else if (Matched
&& ! IsListEmpty(ListHead
))
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 */
473 Entry
= ListHead
->Flink
;
474 while (Entry
!= ListHead
)
476 HistoryEntry
= (PBASE_DOS_DEVICE_HISTORY_ENTRY
)
477 CONTAINING_RECORD(Entry
,
478 BASE_DOS_DEVICE_HISTORY_ENTRY
,
481 ! RtlCompareUnicodeString(&RequestDeviceName
,
482 &HistoryEntry
->Device
,
486 RemoveEntryList(&HistoryEntry
->Entry
);
487 RequestLinkTarget
= &HistoryEntry
->Target
;
490 Entry
= Entry
->Flink
;
494 /* Nothing to revert to so delete the symlink */
496 RequestLinkTarget
= NULL
;
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
)
505 HistoryEntry
= (PBASE_DOS_DEVICE_HISTORY_ENTRY
)
506 CONTAINING_RECORD(Entry
,
507 BASE_DOS_DEVICE_HISTORY_ENTRY
,
510 ! RtlCompareUnicodeString(&RequestDeviceName
,
511 &HistoryEntry
->Device
,
516 Entry
= Entry
->Flink
;
521 if (dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
)
523 if (! RtlCompareUnicodeString(RequestLinkTarget
,
524 &HistoryEntry
->Target
,
530 else if (RtlPrefixUnicodeString(RequestLinkTarget
,
531 &HistoryEntry
->Target
,
539 RemoveEntryList(&HistoryEntry
->Entry
);
542 Entry
= Entry
->Flink
;
546 /* Leave existing symlink as is */
548 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
550 Status
= STATUS_SUCCESS
;
559 Status
= NtMakeTemporaryObject(LinkHandle
);
560 if (! NT_SUCCESS(Status
))
562 DPRINT1("NtMakeTemporaryObject(%wZ) failed (Status %lx)\n",
563 &DeviceName
, Status
);
567 Status
= NtClose(LinkHandle
);
569 if (! NT_SUCCESS(Status
))
571 DPRINT1("NtClose(%wZ) failed (Status %lx)\n",
572 &DeviceName
, Status
);
577 /* Don't create symlink if we don't have a target */
578 if (! RequestLinkTarget
|| RequestLinkTarget
->Length
== 0)
583 HistoryEntry
= (PBASE_DOS_DEVICE_HISTORY_ENTRY
)
584 RtlAllocateHeap(BaseSrvHeap
,
586 sizeof(BASE_DOS_DEVICE_HISTORY_ENTRY
));
589 DPRINT1("Failed to allocate memory\n");
590 Status
= STATUS_NO_MEMORY
;
594 HistoryEntry
->Target
.Buffer
=
595 RtlAllocateHeap(BaseSrvHeap
,
598 if (! HistoryEntry
->Target
.Buffer
)
600 DPRINT1("Failed to allocate memory\n");
601 Status
= STATUS_NO_MEMORY
;
604 HistoryEntry
->Target
.Length
=
605 HistoryEntry
->Target
.MaximumLength
=
607 RtlCopyUnicodeString(&HistoryEntry
->Target
,
610 HistoryEntry
->Device
.Buffer
=
611 RtlAllocateHeap(BaseSrvHeap
,
613 RequestDeviceName
.Length
);
614 if (! HistoryEntry
->Device
.Buffer
)
616 DPRINT1("Failed to allocate memory\n");
617 Status
= STATUS_NO_MEMORY
;
620 HistoryEntry
->Device
.Length
=
621 HistoryEntry
->Device
.MaximumLength
=
622 RequestDeviceName
.Length
;
623 RtlCopyUnicodeString(&HistoryEntry
->Device
,
626 /* Remember previous symlink target for this device */
627 InsertHeadList(ListHead
,
628 &HistoryEntry
->Entry
);
632 RtlAllocateAndInitializeSid(&WorldAuthority
,
644 RtlAllocateAndInitializeSid(&SystemAuthority
,
646 SECURITY_LOCAL_SYSTEM_RID
,
656 RtlAllocateAndInitializeSid(&SystemAuthority
,
658 SECURITY_BUILTIN_DOMAIN_RID
,
659 DOMAIN_ALIAS_RID_ADMINS
,
668 SidLength
= RtlLengthSid(SystemSid
) +
669 RtlLengthSid(AdminSid
) +
670 RtlLengthSid(WorldSid
);
671 Length
= sizeof(ACL
) + SidLength
+ 3 * sizeof(ACCESS_ALLOWED_ACE
);
673 SecurityDescriptor
= RtlAllocateHeap(BaseSrvHeap
,
675 SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
676 if (! SecurityDescriptor
)
678 DPRINT1("Failed to allocate memory\n");
679 Status
= STATUS_NO_MEMORY
;
683 Dacl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
684 Status
= RtlCreateSecurityDescriptor(SecurityDescriptor
,
685 SECURITY_DESCRIPTOR_REVISION
);
686 if (! NT_SUCCESS(Status
))
688 DPRINT1("RtlCreateSecurityDescriptor() failed (Status %lx)\n",
693 Status
= RtlCreateAcl(Dacl
,
696 if (! NT_SUCCESS(Status
))
698 DPRINT1("RtlCreateAcl() failed (Status %lx)\n",
703 (void) RtlAddAccessAllowedAce(Dacl
,
707 (void) RtlAddAccessAllowedAce(Dacl
,
711 (void) RtlAddAccessAllowedAce(Dacl
,
713 STANDARD_RIGHTS_READ
,
716 Status
= RtlSetDaclSecurityDescriptor(SecurityDescriptor
,
720 if (! NT_SUCCESS(Status
))
722 DPRINT1("RtlSetDaclSecurityDescriptor() failed (Status %lx)\n",
727 InitializeObjectAttributes(&ObjectAttributes
,
729 OBJ_CASE_INSENSITIVE
,
732 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
733 SYMBOLIC_LINK_ALL_ACCESS
,
736 if (NT_SUCCESS(Status
))
738 Status
= NtMakePermanentObject(LinkHandle
);
739 if (! NT_SUCCESS(Status
))
741 DPRINT1("NtMakePermanentObject(%wZ) failed (Status %lx)\n",
742 &DeviceName
, Status
);
747 DPRINT1("NtCreateSymbolicLinkObject(%wZ) failed (Status %lx)\n",
748 &DeviceName
, Status
);
753 (void) RtlLeaveCriticalSection(&BaseDefineDosDeviceCritSec
);
754 if (DeviceName
.Buffer
)
755 (void) RtlFreeHeap(BaseSrvHeap
,
758 if (LinkTarget
.Buffer
)
759 (void) RtlFreeHeap(BaseSrvHeap
,
762 if (SecurityDescriptor
)
763 (void) RtlFreeHeap(BaseSrvHeap
,
767 (void) NtClose(LinkHandle
);
769 (void) RtlFreeSid(SystemSid
);
771 (void) RtlFreeSid(AdminSid
);
773 (void) RtlFreeSid(WorldSid
);
774 RtlFreeUnicodeString(&RequestDeviceName
);
777 if (HistoryEntry
->Target
.Buffer
)
778 (void) RtlFreeHeap(BaseSrvHeap
,
780 HistoryEntry
->Target
.Buffer
);
781 if (HistoryEntry
->Device
.Buffer
)
782 (void) RtlFreeHeap(BaseSrvHeap
,
784 HistoryEntry
->Device
.Buffer
);
785 (void) RtlFreeHeap(BaseSrvHeap
,
792 DPRINT("CsrDefineDosDevice Exit, Statux: 0x%x\n", Status
);
801 /* PUBLIC API *****************************************************************/
803 NTSTATUS NTAPI
BaseSetProcessCreateNotify(IN BASE_PROCESS_CREATE_NOTIFY_ROUTINE ProcessCreateNotifyProc
)
805 DPRINT("BASESRV: %s(%08lx) called\n", __FUNCTION__
, ProcessCreateNotifyProc
);
806 return STATUS_NOT_IMPLEMENTED
;