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");
100 /* Check for other failures */
101 if (!NT_SUCCESS(Status
))
103 DPRINT1("Failed to create process/thread structures: %lx\n", Status
);
107 /* FIXME: Should notify user32 */
109 /* FIXME: VDM vodoo */
111 /* Return the result of this operation */
115 CSR_API(BaseSrvCreateThread
)
118 PBASE_CREATE_THREAD CreateThreadRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.CreateThreadRequest
;
119 PCSR_THREAD CurrentThread
;
121 PCSR_PROCESS CsrProcess
;
123 /* Get the current CSR thread */
124 CurrentThread
= CsrGetClientThread();
127 DPRINT1("Server Thread TID: [%lx.%lx]\n",
128 CreateThreadRequest
->ClientId
.UniqueProcess
,
129 CreateThreadRequest
->ClientId
.UniqueThread
);
130 return STATUS_SUCCESS
; // server-to-server
133 /* Get the CSR Process for this request */
134 CsrProcess
= CurrentThread
->Process
;
135 if (CsrProcess
->ClientId
.UniqueProcess
!=
136 CreateThreadRequest
->ClientId
.UniqueProcess
)
138 /* This is a remote thread request -- is it within the server itself? */
139 if (CreateThreadRequest
->ClientId
.UniqueProcess
== NtCurrentTeb()->ClientId
.UniqueProcess
)
141 /* Accept this without any further work */
142 return STATUS_SUCCESS
;
145 /* Get the real CSR Process for the remote thread's process */
146 Status
= CsrLockProcessByClientId(CreateThreadRequest
->ClientId
.UniqueProcess
,
148 if (!NT_SUCCESS(Status
)) return Status
;
151 /* Duplicate the thread handle so we can own it */
152 Status
= NtDuplicateObject(CurrentThread
->Process
->ProcessHandle
,
153 CreateThreadRequest
->ThreadHandle
,
158 DUPLICATE_SAME_ACCESS
);
159 if (NT_SUCCESS(Status
))
161 /* Call CSRSRV to tell it about the new thread */
162 Status
= CsrCreateThread(CsrProcess
,
164 &CreateThreadRequest
->ClientId
,
168 /* Unlock the process and return */
169 if (CsrProcess
!= CurrentThread
->Process
) CsrUnlockProcess(CsrProcess
);
173 CSR_API(BaseSrvGetTempFile
)
175 static UINT CsrGetTempFileUnique
= 0;
176 PBASE_GET_TEMP_FILE GetTempFile
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.GetTempFile
;
178 /* Return 16-bits ID */
179 GetTempFile
->UniqueID
= (++CsrGetTempFileUnique
& 0xFFFF);
181 DPRINT("Returning: %u\n", GetTempFile
->UniqueID
);
183 return STATUS_SUCCESS
;
186 CSR_API(BaseSrvExitProcess
)
188 PCSR_THREAD CsrThread
= CsrGetClientThread();
189 ASSERT(CsrThread
!= NULL
);
191 /* Set the special reply value so we don't reply this message back */
194 /* Remove the CSR_THREADs and CSR_PROCESS */
195 return CsrDestroyProcess(&CsrThread
->ClientId
,
196 (NTSTATUS
)((PBASE_API_MESSAGE
)ApiMessage
)->Data
.ExitProcessRequest
.uExitCode
);
199 CSR_API(BaseSrvGetProcessShutdownParam
)
201 PBASE_GET_PROCESS_SHUTDOWN_PARAMS GetShutdownParametersRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.GetShutdownParametersRequest
;
202 PCSR_THREAD CsrThread
= CsrGetClientThread();
205 GetShutdownParametersRequest
->Level
= CsrThread
->Process
->ShutdownLevel
;
206 GetShutdownParametersRequest
->Flags
= CsrThread
->Process
->ShutdownFlags
;
208 return STATUS_SUCCESS
;
211 CSR_API(BaseSrvSetProcessShutdownParam
)
213 PBASE_SET_PROCESS_SHUTDOWN_PARAMS SetShutdownParametersRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.SetShutdownParametersRequest
;
214 PCSR_THREAD CsrThread
= CsrGetClientThread();
217 CsrThread
->Process
->ShutdownLevel
= SetShutdownParametersRequest
->Level
;
218 CsrThread
->Process
->ShutdownFlags
= SetShutdownParametersRequest
->Flags
;
220 return STATUS_SUCCESS
;
228 typedef BOOL (WINAPI
*PUSER_SOUND_SENTRY
)(VOID
);
229 BOOL NTAPI
FirstSoundSentry(VOID
);
231 PUSER_SOUND_SENTRY _UserSoundSentry
= FirstSoundSentry
;
235 FailSoundSentry(VOID
)
237 /* In case the function can't be found/is unimplemented */
243 FirstSoundSentry(VOID
)
245 UNICODE_STRING DllString
= RTL_CONSTANT_STRING(L
"winsrv");
246 STRING FuncString
= RTL_CONSTANT_STRING("_UserSoundSentry");
249 PUSER_SOUND_SENTRY NewSoundSentry
= FailSoundSentry
;
251 /* Load winsrv manually */
252 Status
= LdrGetDllHandle(NULL
, NULL
, &DllString
, &DllHandle
);
253 if (NT_SUCCESS(Status
))
255 /* If it was found, get SoundSentry export */
256 Status
= LdrGetProcedureAddress(DllHandle
,
259 (PVOID
*)&NewSoundSentry
);
262 /* Set it as the callback for the future, and call it */
263 _UserSoundSentry
= NewSoundSentry
;
264 return _UserSoundSentry();
267 CSR_API(BaseSrvSoundSentryNotification
)
269 /* Call the API and see if it succeeds */
270 return _UserSoundSentry() ? STATUS_SUCCESS
: STATUS_ACCESS_DENIED
;
275 *** Dos Devices (C) Pierre Schweitzer (pierre.schweitzer@reactos.org)
278 typedef struct tagBASE_DOS_DEVICE_HISTORY_ENTRY
280 UNICODE_STRING Device
;
281 UNICODE_STRING Target
;
283 } BASE_DOS_DEVICE_HISTORY_ENTRY
, *PBASE_DOS_DEVICE_HISTORY_ENTRY
;
285 LIST_ENTRY DosDeviceHistory
;
286 RTL_CRITICAL_SECTION BaseDefineDosDeviceCritSec
;
288 VOID
BaseCleanupDefineDosDevice(VOID
)
290 PLIST_ENTRY Entry
, ListHead
;
291 PBASE_DOS_DEVICE_HISTORY_ENTRY HistoryEntry
;
293 (void) RtlDeleteCriticalSection(&BaseDefineDosDeviceCritSec
);
295 ListHead
= &DosDeviceHistory
;
296 Entry
= ListHead
->Flink
;
297 while (Entry
!= ListHead
)
299 HistoryEntry
= (PBASE_DOS_DEVICE_HISTORY_ENTRY
)
300 CONTAINING_RECORD(Entry
,
301 BASE_DOS_DEVICE_HISTORY_ENTRY
,
303 Entry
= Entry
->Flink
;
307 if (HistoryEntry
->Target
.Buffer
)
308 (void) RtlFreeHeap(BaseSrvHeap
,
310 HistoryEntry
->Target
.Buffer
);
311 if (HistoryEntry
->Device
.Buffer
)
312 (void) RtlFreeHeap(BaseSrvHeap
,
314 HistoryEntry
->Device
.Buffer
);
315 (void) RtlFreeHeap(BaseSrvHeap
,
322 CSR_API(BaseSrvDefineDosDevice
)
325 PBASE_DEFINE_DOS_DEVICE DefineDosDeviceRequest
= &((PBASE_API_MESSAGE
)ApiMessage
)->Data
.DefineDosDeviceRequest
;
326 OBJECT_ATTRIBUTES ObjectAttributes
;
327 HANDLE LinkHandle
= NULL
;
328 UNICODE_STRING DeviceName
= {0};
329 UNICODE_STRING RequestDeviceName
= {0};
330 UNICODE_STRING LinkTarget
= {0};
331 PUNICODE_STRING RequestLinkTarget
;
333 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
334 SID_IDENTIFIER_AUTHORITY SystemAuthority
= {SECURITY_NT_AUTHORITY
};
335 PSECURITY_DESCRIPTOR SecurityDescriptor
;
341 PBASE_DOS_DEVICE_HISTORY_ENTRY HistoryEntry
;
343 PLIST_ENTRY ListHead
;
344 BOOLEAN Matched
, AddHistory
;
348 DPRINT("CsrDefineDosDevice entered, Flags:%d, DeviceName:%wZ, TargetName:%wZ\n",
349 DefineDosDeviceRequest
->dwFlags
,
350 &DefineDosDeviceRequest
->DeviceName
,
351 &DefineDosDeviceRequest
->TargetName
);
353 Matched
= AddHistory
= FALSE
;
355 AdminSid
= SystemSid
= WorldSid
= NULL
;
356 SecurityDescriptor
= NULL
;
357 ListHead
= &DosDeviceHistory
;
358 dwFlags
= DefineDosDeviceRequest
->dwFlags
;
360 /* Validate the flags */
361 if ( (dwFlags
& 0xFFFFFFF0) ||
362 ((dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
) &&
363 ! (dwFlags
& DDD_REMOVE_DEFINITION
)) )
365 return STATUS_INVALID_PARAMETER
;
368 Status
= RtlEnterCriticalSection(&BaseDefineDosDeviceCritSec
);
369 if (! NT_SUCCESS(Status
))
371 DPRINT1("RtlEnterCriticalSection() failed (Status %lx)\n",
379 RtlUpcaseUnicodeString(&RequestDeviceName
,
380 &DefineDosDeviceRequest
->DeviceName
,
382 if (! NT_SUCCESS(Status
))
385 RequestLinkTarget
= &DefineDosDeviceRequest
->TargetName
;
386 lpBuffer
= (PWSTR
) RtlAllocateHeap(BaseSrvHeap
,
388 RequestDeviceName
.MaximumLength
+ 5 * sizeof(WCHAR
));
391 DPRINT1("Failed to allocate memory\n");
392 Status
= STATUS_NO_MEMORY
;
399 RtlInitUnicodeString(&DeviceName
,
401 InitializeObjectAttributes(&ObjectAttributes
,
403 OBJ_CASE_INSENSITIVE
,
406 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
409 if (NT_SUCCESS(Status
))
411 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
414 if (! NT_SUCCESS(Status
) &&
415 Status
== STATUS_BUFFER_TOO_SMALL
)
417 LinkTarget
.Length
= 0;
418 LinkTarget
.MaximumLength
= Length
;
419 LinkTarget
.Buffer
= (PWSTR
)
420 RtlAllocateHeap(BaseSrvHeap
,
423 if (! LinkTarget
.Buffer
)
425 DPRINT1("Failed to allocate memory\n");
426 Status
= STATUS_NO_MEMORY
;
430 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
435 if (! NT_SUCCESS(Status
))
437 DPRINT1("NtQuerySymbolicLinkObject(%wZ) failed (Status %lx)\n",
438 &DeviceName
, Status
);
442 if ((dwFlags
& DDD_REMOVE_DEFINITION
))
444 /* If no target name specified we remove the current symlink target */
445 if (RequestLinkTarget
->Length
== 0)
449 if (dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
)
450 Matched
= ! RtlCompareUnicodeString(RequestLinkTarget
,
454 Matched
= RtlPrefixUnicodeString(RequestLinkTarget
,
459 if (Matched
&& IsListEmpty(ListHead
))
461 /* Current symlink target macthed and there is nothing to revert to */
462 RequestLinkTarget
= NULL
;
464 else if (Matched
&& ! IsListEmpty(ListHead
))
466 /* Fetch the first history entry we come across for the device name */
467 /* This will become the current symlink target for the device name */
469 Entry
= ListHead
->Flink
;
470 while (Entry
!= ListHead
)
472 HistoryEntry
= (PBASE_DOS_DEVICE_HISTORY_ENTRY
)
473 CONTAINING_RECORD(Entry
,
474 BASE_DOS_DEVICE_HISTORY_ENTRY
,
477 ! RtlCompareUnicodeString(&RequestDeviceName
,
478 &HistoryEntry
->Device
,
482 RemoveEntryList(&HistoryEntry
->Entry
);
483 RequestLinkTarget
= &HistoryEntry
->Target
;
486 Entry
= Entry
->Flink
;
490 /* Nothing to revert to so delete the symlink */
492 RequestLinkTarget
= NULL
;
496 /* Locate a previous symlink target as we did not get a hit earlier */
497 /* If we find one we need to remove it */
498 Entry
= ListHead
->Flink
;
499 while (Entry
!= ListHead
)
501 HistoryEntry
= (PBASE_DOS_DEVICE_HISTORY_ENTRY
)
502 CONTAINING_RECORD(Entry
,
503 BASE_DOS_DEVICE_HISTORY_ENTRY
,
506 ! RtlCompareUnicodeString(&RequestDeviceName
,
507 &HistoryEntry
->Device
,
512 Entry
= Entry
->Flink
;
517 if (dwFlags
& DDD_EXACT_MATCH_ON_REMOVE
)
519 if (! RtlCompareUnicodeString(RequestLinkTarget
,
520 &HistoryEntry
->Target
,
526 else if (RtlPrefixUnicodeString(RequestLinkTarget
,
527 &HistoryEntry
->Target
,
535 RemoveEntryList(&HistoryEntry
->Entry
);
538 Entry
= Entry
->Flink
;
542 /* Leave existing symlink as is */
544 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
546 Status
= STATUS_SUCCESS
;
555 Status
= NtMakeTemporaryObject(LinkHandle
);
556 if (! NT_SUCCESS(Status
))
558 DPRINT1("NtMakeTemporaryObject(%wZ) failed (Status %lx)\n",
559 &DeviceName
, Status
);
563 Status
= NtClose(LinkHandle
);
565 if (! NT_SUCCESS(Status
))
567 DPRINT1("NtClose(%wZ) failed (Status %lx)\n",
568 &DeviceName
, Status
);
573 /* Don't create symlink if we don't have a target */
574 if (! RequestLinkTarget
|| RequestLinkTarget
->Length
== 0)
579 HistoryEntry
= (PBASE_DOS_DEVICE_HISTORY_ENTRY
)
580 RtlAllocateHeap(BaseSrvHeap
,
582 sizeof(BASE_DOS_DEVICE_HISTORY_ENTRY
));
585 DPRINT1("Failed to allocate memory\n");
586 Status
= STATUS_NO_MEMORY
;
590 HistoryEntry
->Target
.Buffer
=
591 RtlAllocateHeap(BaseSrvHeap
,
594 if (! HistoryEntry
->Target
.Buffer
)
596 DPRINT1("Failed to allocate memory\n");
597 Status
= STATUS_NO_MEMORY
;
600 HistoryEntry
->Target
.Length
=
601 HistoryEntry
->Target
.MaximumLength
=
603 RtlCopyUnicodeString(&HistoryEntry
->Target
,
606 HistoryEntry
->Device
.Buffer
=
607 RtlAllocateHeap(BaseSrvHeap
,
609 RequestDeviceName
.Length
);
610 if (! HistoryEntry
->Device
.Buffer
)
612 DPRINT1("Failed to allocate memory\n");
613 Status
= STATUS_NO_MEMORY
;
616 HistoryEntry
->Device
.Length
=
617 HistoryEntry
->Device
.MaximumLength
=
618 RequestDeviceName
.Length
;
619 RtlCopyUnicodeString(&HistoryEntry
->Device
,
622 /* Remember previous symlink target for this device */
623 InsertHeadList(ListHead
,
624 &HistoryEntry
->Entry
);
628 RtlAllocateAndInitializeSid(&WorldAuthority
,
640 RtlAllocateAndInitializeSid(&SystemAuthority
,
642 SECURITY_LOCAL_SYSTEM_RID
,
652 RtlAllocateAndInitializeSid(&SystemAuthority
,
654 SECURITY_BUILTIN_DOMAIN_RID
,
655 DOMAIN_ALIAS_RID_ADMINS
,
664 SidLength
= RtlLengthSid(SystemSid
) +
665 RtlLengthSid(AdminSid
) +
666 RtlLengthSid(WorldSid
);
667 Length
= sizeof(ACL
) + SidLength
+ 3 * sizeof(ACCESS_ALLOWED_ACE
);
669 SecurityDescriptor
= RtlAllocateHeap(BaseSrvHeap
,
671 SECURITY_DESCRIPTOR_MIN_LENGTH
+ Length
);
672 if (! SecurityDescriptor
)
674 DPRINT1("Failed to allocate memory\n");
675 Status
= STATUS_NO_MEMORY
;
679 Dacl
= (PACL
)((ULONG_PTR
)SecurityDescriptor
+ SECURITY_DESCRIPTOR_MIN_LENGTH
);
680 Status
= RtlCreateSecurityDescriptor(SecurityDescriptor
,
681 SECURITY_DESCRIPTOR_REVISION
);
682 if (! NT_SUCCESS(Status
))
684 DPRINT1("RtlCreateSecurityDescriptor() failed (Status %lx)\n",
689 Status
= RtlCreateAcl(Dacl
,
692 if (! NT_SUCCESS(Status
))
694 DPRINT1("RtlCreateAcl() failed (Status %lx)\n",
699 (void) RtlAddAccessAllowedAce(Dacl
,
703 (void) RtlAddAccessAllowedAce(Dacl
,
707 (void) RtlAddAccessAllowedAce(Dacl
,
709 STANDARD_RIGHTS_READ
,
712 Status
= RtlSetDaclSecurityDescriptor(SecurityDescriptor
,
716 if (! NT_SUCCESS(Status
))
718 DPRINT1("RtlSetDaclSecurityDescriptor() failed (Status %lx)\n",
723 InitializeObjectAttributes(&ObjectAttributes
,
725 OBJ_CASE_INSENSITIVE
,
728 Status
= NtCreateSymbolicLinkObject(&LinkHandle
,
729 SYMBOLIC_LINK_ALL_ACCESS
,
732 if (NT_SUCCESS(Status
))
734 Status
= NtMakePermanentObject(LinkHandle
);
735 if (! NT_SUCCESS(Status
))
737 DPRINT1("NtMakePermanentObject(%wZ) failed (Status %lx)\n",
738 &DeviceName
, Status
);
743 DPRINT1("NtCreateSymbolicLinkObject(%wZ) failed (Status %lx)\n",
744 &DeviceName
, Status
);
749 (void) RtlLeaveCriticalSection(&BaseDefineDosDeviceCritSec
);
750 if (DeviceName
.Buffer
)
751 (void) RtlFreeHeap(BaseSrvHeap
,
754 if (LinkTarget
.Buffer
)
755 (void) RtlFreeHeap(BaseSrvHeap
,
758 if (SecurityDescriptor
)
759 (void) RtlFreeHeap(BaseSrvHeap
,
763 (void) NtClose(LinkHandle
);
765 (void) RtlFreeSid(SystemSid
);
767 (void) RtlFreeSid(AdminSid
);
769 (void) RtlFreeSid(WorldSid
);
770 RtlFreeUnicodeString(&RequestDeviceName
);
773 if (HistoryEntry
->Target
.Buffer
)
774 (void) RtlFreeHeap(BaseSrvHeap
,
776 HistoryEntry
->Target
.Buffer
);
777 if (HistoryEntry
->Device
.Buffer
)
778 (void) RtlFreeHeap(BaseSrvHeap
,
780 HistoryEntry
->Device
.Buffer
);
781 (void) RtlFreeHeap(BaseSrvHeap
,
788 DPRINT("CsrDefineDosDevice Exit, Statux: 0x%x\n", Status
);
797 /* PUBLIC API *****************************************************************/
799 NTSTATUS NTAPI
BaseSetProcessCreateNotify(IN BASE_PROCESS_CREATE_NOTIFY_ROUTINE ProcessCreateNotifyProc
)
801 DPRINT("BASESRV: %s(%08lx) called\n", __FUNCTION__
, ProcessCreateNotifyProc
);
802 return STATUS_NOT_IMPLEMENTED
;