1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Base API Server DLL 4 * FILE: subsystems/win/basesrv/proc.c 5 * PURPOSE: Process and Thread Management 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include "basesrv.h" 12 #include "vdm.h" 13 14 #define NDEBUG 15 #include <debug.h> 16 17 /* GLOBALS ********************************************************************/ 18 19 /* User notification procedure to be called when a process is created */ 20 static BASE_PROCESS_CREATE_NOTIFY_ROUTINE UserNotifyProcessCreate = NULL; 21 22 /* PUBLIC SERVER APIS *********************************************************/ 23 24 CSR_API(BaseSrvDebugProcess) 25 { 26 /* Deprecated */ 27 return STATUS_UNSUCCESSFUL; 28 } 29 30 CSR_API(BaseSrvRegisterThread) 31 { 32 DPRINT1("%s not yet implemented\n", __FUNCTION__); 33 return STATUS_NOT_IMPLEMENTED; 34 } 35 36 CSR_API(BaseSrvSxsCreateActivationContext) 37 { 38 DPRINT1("%s not yet implemented\n", __FUNCTION__); 39 return STATUS_NOT_IMPLEMENTED; 40 } 41 42 CSR_API(BaseSrvSetTermsrvAppInstallMode) 43 { 44 DPRINT1("%s not yet implemented\n", __FUNCTION__); 45 return STATUS_NOT_IMPLEMENTED; 46 } 47 48 CSR_API(BaseSrvSetTermsrvClientTimeZone) 49 { 50 DPRINT1("%s not yet implemented\n", __FUNCTION__); 51 return STATUS_NOT_IMPLEMENTED; 52 } 53 54 CSR_API(BaseSrvGetTempFile) 55 { 56 static UINT BaseGetTempFileUnique = 0; 57 PBASE_GET_TEMP_FILE GetTempFile = &((PBASE_API_MESSAGE)ApiMessage)->Data.GetTempFileRequest; 58 59 /* Return 16-bits ID */ 60 GetTempFile->UniqueID = (++BaseGetTempFileUnique & 0xFFFF); 61 62 DPRINT("Returning: %u\n", GetTempFile->UniqueID); 63 64 return GetTempFile->UniqueID; 65 } 66 67 CSR_API(BaseSrvCreateProcess) 68 { 69 NTSTATUS Status; 70 PBASE_CREATE_PROCESS CreateProcessRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.CreateProcessRequest; 71 HANDLE ProcessHandle, ThreadHandle; 72 PCSR_THREAD CsrThread; 73 PCSR_PROCESS Process; 74 ULONG Flags = 0, DebugFlags = 0, VdmPower = 0; 75 76 /* Get the current client thread */ 77 CsrThread = CsrGetClientThread(); 78 ASSERT(CsrThread != NULL); 79 80 Process = CsrThread->Process; 81 82 /* Extract the flags out of the process handle */ 83 Flags = (ULONG_PTR)CreateProcessRequest->ProcessHandle & 3; 84 CreateProcessRequest->ProcessHandle = (HANDLE)((ULONG_PTR)CreateProcessRequest->ProcessHandle & ~3); 85 86 /* Some things should be done if this is a VDM process */ 87 if (CreateProcessRequest->VdmBinaryType) 88 { 89 /* We need to set the VDM power later on */ 90 VdmPower = 1; 91 } 92 93 /* Duplicate the process handle */ 94 Status = NtDuplicateObject(Process->ProcessHandle, 95 CreateProcessRequest->ProcessHandle, 96 NtCurrentProcess(), 97 &ProcessHandle, 98 0, 99 0, 100 DUPLICATE_SAME_ACCESS); 101 if (!NT_SUCCESS(Status)) 102 { 103 DPRINT1("Failed to duplicate process handle: %lx\n", Status); 104 return Status; 105 } 106 107 /* Duplicate the thread handle */ 108 Status = NtDuplicateObject(Process->ProcessHandle, 109 CreateProcessRequest->ThreadHandle, 110 NtCurrentProcess(), 111 &ThreadHandle, 112 0, 113 0, 114 DUPLICATE_SAME_ACCESS); 115 if (!NT_SUCCESS(Status)) 116 { 117 DPRINT1("Failed to duplicate thread handle: %lx\n", Status); 118 NtClose(ProcessHandle); 119 return Status; 120 } 121 122 /* If this is a VDM process, request VDM power */ 123 if (VdmPower) 124 { 125 Status = NtSetInformationProcess(ProcessHandle, 126 ProcessWx86Information, 127 &VdmPower, 128 sizeof(VdmPower)); 129 if (!NT_SUCCESS(Status)) 130 { 131 DPRINT1("Failed to get VDM powers\n"); 132 NtClose(ProcessHandle); 133 NtClose(ThreadHandle); 134 return Status; 135 } 136 } 137 138 /* Flags conversion. FIXME: More need conversion */ 139 if (CreateProcessRequest->CreationFlags & CREATE_NEW_PROCESS_GROUP) 140 { 141 DebugFlags |= CsrProcessCreateNewGroup; 142 } 143 if ((Flags & 2) == 0) 144 { 145 /* We are launching a console process */ 146 DebugFlags |= CsrProcessIsConsoleApp; 147 } 148 149 /* FIXME: SxS Stuff */ 150 151 /* Call CSRSRV to create the CSR_PROCESS structure and the first CSR_THREAD */ 152 Status = CsrCreateProcess(ProcessHandle, 153 ThreadHandle, 154 &CreateProcessRequest->ClientId, 155 Process->NtSession, 156 DebugFlags, 157 NULL); 158 if (Status == STATUS_THREAD_IS_TERMINATING) 159 { 160 DPRINT1("Thread already dead\n"); 161 162 /* Set the special reply value so we don't reply this message back */ 163 *ReplyCode = CsrReplyDeadClient; 164 165 return Status; 166 } 167 168 /* Check for other failures */ 169 if (!NT_SUCCESS(Status)) 170 { 171 DPRINT1("Failed to create process/thread structures: %lx\n", Status); 172 return Status; 173 } 174 175 /* Call the user notification procedure */ 176 if (UserNotifyProcessCreate) 177 { 178 UserNotifyProcessCreate(CreateProcessRequest->ClientId.UniqueProcess, 179 Process->ClientId.UniqueThread, 180 0, 181 Flags); 182 } 183 184 /* Check if this is a VDM process */ 185 if (CreateProcessRequest->VdmBinaryType) 186 { 187 PVDM_CONSOLE_RECORD ConsoleRecord; 188 189 if (CreateProcessRequest->VdmTask != 0) 190 { 191 /* Get the console record using the task ID */ 192 Status = GetConsoleRecordBySessionId(CreateProcessRequest->VdmTask, 193 &ConsoleRecord); 194 } 195 else 196 { 197 /* Get the console record using the console handle */ 198 Status = BaseSrvGetConsoleRecord(CreateProcessRequest->hVDM, 199 &ConsoleRecord); 200 } 201 202 /* Check if it failed */ 203 if (!NT_SUCCESS(Status)) return Status; 204 205 /* Store the process ID of the VDM in the console record */ 206 ConsoleRecord->ProcessId = HandleToUlong(CreateProcessRequest->ClientId.UniqueProcess); 207 } 208 209 /* Return the result of this operation */ 210 return Status; 211 } 212 213 CSR_API(BaseSrvCreateThread) 214 { 215 NTSTATUS Status; 216 PBASE_CREATE_THREAD CreateThreadRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.CreateThreadRequest; 217 PCSR_THREAD CurrentThread; 218 HANDLE ThreadHandle; 219 PCSR_PROCESS CsrProcess; 220 221 /* Get the current CSR thread */ 222 CurrentThread = CsrGetClientThread(); 223 if (!CurrentThread) 224 { 225 DPRINT1("Server Thread TID: [%lx.%lx]\n", 226 CreateThreadRequest->ClientId.UniqueProcess, 227 CreateThreadRequest->ClientId.UniqueThread); 228 return STATUS_SUCCESS; // server-to-server 229 } 230 231 /* Get the CSR Process for this request */ 232 CsrProcess = CurrentThread->Process; 233 if (CsrProcess->ClientId.UniqueProcess != 234 CreateThreadRequest->ClientId.UniqueProcess) 235 { 236 /* This is a remote thread request -- is it within the server itself? */ 237 if (CreateThreadRequest->ClientId.UniqueProcess == NtCurrentTeb()->ClientId.UniqueProcess) 238 { 239 /* Accept this without any further work */ 240 return STATUS_SUCCESS; 241 } 242 243 /* Get the real CSR Process for the remote thread's process */ 244 Status = CsrLockProcessByClientId(CreateThreadRequest->ClientId.UniqueProcess, 245 &CsrProcess); 246 if (!NT_SUCCESS(Status)) return Status; 247 } 248 249 /* Duplicate the thread handle so we can own it */ 250 Status = NtDuplicateObject(CurrentThread->Process->ProcessHandle, 251 CreateThreadRequest->ThreadHandle, 252 NtCurrentProcess(), 253 &ThreadHandle, 254 0, 255 0, 256 DUPLICATE_SAME_ACCESS); 257 if (NT_SUCCESS(Status)) 258 { 259 /* Call CSRSRV to tell it about the new thread */ 260 Status = CsrCreateThread(CsrProcess, 261 ThreadHandle, 262 &CreateThreadRequest->ClientId, 263 TRUE); 264 } 265 266 /* Unlock the process and return */ 267 if (CsrProcess != CurrentThread->Process) CsrUnlockProcess(CsrProcess); 268 return Status; 269 } 270 271 CSR_API(BaseSrvExitProcess) 272 { 273 PCSR_THREAD CsrThread = CsrGetClientThread(); 274 ASSERT(CsrThread != NULL); 275 276 /* Set the special reply value so we don't reply this message back */ 277 *ReplyCode = CsrReplyDeadClient; 278 279 /* Remove the CSR_THREADs and CSR_PROCESS */ 280 return CsrDestroyProcess(&CsrThread->ClientId, 281 (NTSTATUS)((PBASE_API_MESSAGE)ApiMessage)->Data.ExitProcessRequest.uExitCode); 282 } 283 284 CSR_API(BaseSrvGetProcessShutdownParam) 285 { 286 PBASE_GETSET_PROCESS_SHUTDOWN_PARAMS ShutdownParametersRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.ShutdownParametersRequest; 287 PCSR_THREAD CsrThread = CsrGetClientThread(); 288 ASSERT(CsrThread); 289 290 ShutdownParametersRequest->ShutdownLevel = CsrThread->Process->ShutdownLevel; 291 /* Only SHUTDOWN_NORETRY flag is valid for this API. The other private flags are for CSRSRV/WINSRV only. */ 292 ShutdownParametersRequest->ShutdownFlags = CsrThread->Process->ShutdownFlags & SHUTDOWN_NORETRY; 293 294 return STATUS_SUCCESS; 295 } 296 297 CSR_API(BaseSrvSetProcessShutdownParam) 298 { 299 PBASE_GETSET_PROCESS_SHUTDOWN_PARAMS ShutdownParametersRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.ShutdownParametersRequest; 300 PCSR_THREAD CsrThread = CsrGetClientThread(); 301 ASSERT(CsrThread); 302 303 /* Only SHUTDOWN_NORETRY flag is valid for this API. The other private flags are for CSRSRV/WINSRV only. */ 304 if (ShutdownParametersRequest->ShutdownFlags & ~SHUTDOWN_NORETRY) 305 { 306 /* If there were other flags specified, fail the call */ 307 return STATUS_INVALID_PARAMETER; 308 } 309 310 CsrThread->Process->ShutdownLevel = ShutdownParametersRequest->ShutdownLevel; 311 /* Notice that all the possible other private flags are reinitialized here */ 312 CsrThread->Process->ShutdownFlags = ShutdownParametersRequest->ShutdownFlags; 313 314 return STATUS_SUCCESS; 315 } 316 317 /* PUBLIC API *****************************************************************/ 318 319 VOID 320 NTAPI 321 BaseSetProcessCreateNotify(IN BASE_PROCESS_CREATE_NOTIFY_ROUTINE ProcessCreateNotifyProc) 322 { 323 /* Set the user notification procedure to be called when a process is created */ 324 UserNotifyProcessCreate = ProcessCreateNotifyProc; 325 } 326 327 /* EOF */ 328