Beispiel #1
2
pid_t fork(void)
{
 NTSTATUS nErrCode;
 CONTEXT ctxThreadContext;
 HANDLE hProcess;
 HANDLE hThread;
 INITIAL_TEB itInitialTeb;
 CLIENT_ID ciClientId;
 MEMORY_BASIC_INFORMATION mbiStackInfo;
 THREAD_BASIC_INFORMATION tbiThreadInfo;

 struct __tagcsrmsg{
  PORT_MESSAGE PortMessage;
  struct CSRSS_MESSAGE CsrssMessage;
  PROCESS_INFORMATION ProcessInformation;
  CLIENT_ID Debugger;
  ULONG CreationFlags;
  ULONG VdmInfo[2];
 } csrmsg;

 /* STEP 1: Duplicate current process */ 
 nErrCode = NtCreateProcess
 (
  &hProcess,
  PROCESS_ALL_ACCESS,
  NULL,
  NtCurrentProcess(),
  TRUE,
  0,
  0,
  0
 );

 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtCreateProcess() failed with status 0x%08X\n", nErrCode);
  goto fail;
 }

 /* STEP 2: Duplicate current thread */
 /* 2.1: duplicate registers */
 ctxThreadContext.ContextFlags =
  CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS | CONTEXT_FLOATING_POINT;
 
 /* get the current thread's registers */
 nErrCode = NtGetContextThread(NtCurrentThread(), &ctxThreadContext);
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtGetContextThread() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }

 /* redirect the child process to the child_branch label (see 4.3 below) */
 ctxThreadContext.Eip = (ULONG)&&child_branch;
 
 /* 2.2: duplicate stack */
 /* get stack base and size */
 nErrCode = NtQueryVirtualMemory
 (
  NtCurrentProcess(),
  (PVOID)ctxThreadContext.Esp,
  MemoryBasicInformation,
  &mbiStackInfo,
  sizeof(mbiStackInfo),
  0
 );
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtQueryVirtualMemory() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }
 
 itInitialTeb.StackCommit = 0;
 itInitialTeb.StackReserve = 0;
 itInitialTeb.StackBase = (PVOID)((ULONG)(mbiStackInfo.BaseAddress) + mbiStackInfo.RegionSize);
 itInitialTeb.StackLimit = mbiStackInfo.BaseAddress;
 itInitialTeb.StackAllocate = mbiStackInfo.AllocationBase;
 
 /* 2.3: create duplicate thread */
 nErrCode = NtCreateThread
 (
  &hThread,
  THREAD_ALL_ACCESS,
  NULL,
  hProcess,
  (CLIENT_ID *)&ciClientId,
  &ctxThreadContext,
  &itInitialTeb,
  TRUE
 );
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtCreateThread() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }

 /* 2.4: duplicate the TEB */
 /* store the client id in the child thread's stack (see 4.3b) */
 nErrCode = NtWriteVirtualMemory
 (
  hProcess,
  &ciClientId,
  &ciClientId,
  sizeof(ciClientId),
  0
 );
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtWriteVirtualMemory() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }
 
 /* get the child thread's TEB base */
 nErrCode = NtQueryInformationThread
 (
  hThread,
  ThreadBasicInformation,
  &tbiThreadInfo,
  sizeof(tbiThreadInfo),
  0
 );
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtQueryInformationThread() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }
 
 /* copy the TEB */ 
 nErrCode = NtWriteVirtualMemory
 (
  hProcess,
  tbiThreadInfo.TebBaseAddress,
  NtCurrentTeb(),
  sizeof(TEB),
  0
 );
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtWriteVirtualMemory() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }
 
 /* STEP 3: Call Win32 subsystem */
 memset(&csrmsg, 0, sizeof(csrmsg));

 csrmsg.ProcessInformation.hProcess = hProcess;
 csrmsg.ProcessInformation.hThread = hThread;
 csrmsg.ProcessInformation.dwProcessId = (DWORD)ciClientId.UniqueProcess;
 csrmsg.ProcessInformation.dwThreadId = (DWORD)ciClientId.UniqueThread;

 nErrCode = CsrClientCallServer(&csrmsg, 0, 0x10000, 0x24);

 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("CsrClientCallServer() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }
 
 /* STEP 4: Finalization */
 /* 4.1: resume thread */
 nErrCode = NtResumeThread(hThread, 0);
 
 /* 4.2: close superfluous handles */
 NtClose(hProcess);
 NtClose(hThread);
 
 /* 4.3: (parent) return the child process id */
 return ((pid_t)(ciClientId.UniqueProcess));

 /* 4.3b: (child) cleanup and return 0 */
child_branch:
 /* restore the thread and process id in the TEB */ 
 memcpy(&NtCurrentTeb()->Cid, &ciClientId, sizeof(ciClientId));
 
 /* return 0 */
 return (0);

cleanup_and_fail:
 NtTerminateProcess(hProcess, nErrCode);

fail:
 errno = __status_to_errno(nErrCode);
 return (-1);
 
}
Beispiel #2
0
/**********************************************************************
 *	PdxRunServer/0						PRIVATE
 *
 * DESCRIPTION
 *	Wake up all suspended threads.
 */
PRIVATE NTSTATUS STDCALL
PdxRunServer (VOID)
{
    NTSTATUS Status;
    ULONG    ulIndex;
    ULONG    ulThreadIndex;

    for ( ulIndex = 0;
            (ulIndex < (sizeof Server.Port / sizeof Server.Port[0]));
            ulIndex ++)
    {
        for (ulThreadIndex = 0;
                (ulThreadIndex < PSXSS_THREADS_PER_PORT);
                ulThreadIndex ++
            )
        {
#ifdef __PSXSS_ON_W32__
            if (0xFFFFFFFF == ResumeThread (Server.Port[ulIndex].ThreadInfo[ulThreadIndex].hObject))
#else
            Status = NtResumeThread (Server.Port[ulIndex].ThreadInfo[ulThreadIndex].hObject, NULL);
            if (!NT_SUCCESS(Status))
#endif
            {
                debug_print(
                    L"PSXSS: "__FUNCTION__": NtResumeThread failed with Status = %08x",
                    Status
                );
                return Status;
            }
        }
    }
    return STATUS_SUCCESS;
}
Beispiel #3
0
VOID
SepServerSpawnClientProcess(VOID)

{


    RTL_USER_PROCESS_INFORMATION ProcessInformation;
    STRING ImagePathName, ProgramName;
    UNICODE_STRING UnicodeImagePathName, UnicodeProgramName;
    PRTL_USER_PROCESS_PARAMETERS ProcessParameters;

    RtlInitString( &ProgramName, "\\SystemRoot\\Bin\\utlpcqos.exe" );
    Status = RtlAnsiStringToUnicodeString(
                 &UnicodeProgramName,
                 &ProgramName,
                 TRUE );  SEASSERT_SUCCESS( NT_SUCCESS(Status) );
    RtlInitString( &ImagePathName, "utlpcqos.exe");
    Status = RtlAnsiStringToUnicodeString(
                 &UnicodeImagePathName,
                 &ImagePathName,
                 TRUE );  SEASSERT_SUCCESS( NT_SUCCESS(Status) );

    Status = RtlCreateProcessParameters(
                 &ProcessParameters,
                 &ImagePathName,        //UNICODEFIX &UnicodeImagePathName,
                 NULL,
                 NULL,
                 NULL,
                 NULL,
                 NULL,
                 NULL,
                 NULL,
                 NULL
                 );

    SEASSERT_SUCCESS(Status);


    Status = RtlCreateUserProcess(
                 &ProgramName,                   // UNICODEFIX &UnicodeProgramName,
                 ProcessParameters,              // ProcessParameters
                 NULL,                           // ProcessSecurityDescriptor
                 NULL,                           // ThreadSecurityDescriptor
                 NtCurrentProcess(),             // ParentProcess
                 FALSE,                          // InheritHandles
                 NULL,                           // DebugPort
                 NULL,                           // ExceptionPort
                 &ProcessInformation             // ProcessInformation
                 ); SEASSERT_SUCCESS(Status);

    Status = NtResumeThread(
                  ProcessInformation.Thread,
                  NULL
                  ); SEASSERT_SUCCESS(Status);

    RtlDestroyProcessParameters( ProcessParameters );
    RtlFreeUnicodeString( &UnicodeProgramName );
    RtlFreeUnicodeString( &UnicodeImagePathName );

}
Beispiel #4
0
NTSTATUS WINAPI SafeNtResumeThread(HANDLE hThread,PDWORD SuspendCount)
{
	NTSTATUS rc;

	if (CheckOldFunction(&OldNtResumeThread))
		rc=OldNtResumeThread(hThread,SuspendCount);
	else
		rc=NtResumeThread(hThread,SuspendCount);

	return rc;
}
Beispiel #5
0
NTSTATUS CreateNativeProcess(IN PCWSTR file_name, IN PCWSTR cmd_line, OUT PHANDLE hProcess)
{
 UNICODE_STRING fname, nt_file;
 PCWSTR file_part; 
 UNICODE_STRING EnvString, NullString, UnicodeSystemDriveString;
 NTSTATUS status; // Status
 UNICODE_STRING imgname; // ImageName
 UNICODE_STRING imgpath; // Nt ImagePath
 UNICODE_STRING dllpath; // Nt DllPath (DOS Name)
 UNICODE_STRING cmdline; // Nt CommandLine
 PRTL_USER_PROCESS_PARAMETERS processparameters; // ProcessParameters
 RTL_USER_PROCESS_INFORMATION processinformation={0}; // ProcessInformation
 WCHAR Env[2] = { 0,0 }; // Process Envirnoment
 PKUSER_SHARED_DATA SharedData = (PKUSER_SHARED_DATA)USER_SHARED_DATA; // Kernel Shared Data

 *hProcess = NULL;

 RtlDosPathNameToNtPathName_U(file_name, &nt_file, &file_part, NULL);
 
 RtlInitUnicodeString(&imgpath, nt_file.Buffer); // Image path
 RtlInitUnicodeString(&imgname, file_part); // Image name
 RtlInitUnicodeString(&dllpath, SharedData->NtSystemRoot); // DLL Path is %SystemRoot%
 RtlInitUnicodeString(&cmdline, cmd_line); // Command Line parameters
 
 status = RtlCreateProcessParameters(&processparameters, &imgname, &dllpath, &dllpath, &cmdline, Env, 0, 0, 0, 0);

 if (!NT_SUCCESS(status))
 {
   RtlCliDisplayString("RtlCreateProcessParameters failed\n");
   return STATUS_UNSUCCESSFUL;
 }

 DbgPrint("Launching Process: %s, DllPath=%s, CmdLine=%s", &imgname, &dllpath, &cmdline);
 status = RtlCreateUserProcess(&imgpath, OBJ_CASE_INSENSITIVE, processparameters,
                                NULL, NULL, NULL, FALSE, NULL, NULL, &processinformation);

 if (!NT_SUCCESS(status))
 {
   RtlCliDisplayString("RtlCreateUserProcess failed\n");
   return STATUS_UNSUCCESSFUL;
 }
 
 status = NtResumeThread(processinformation.ThreadHandle, NULL);

  if (!NT_SUCCESS(status))
 {
   RtlCliDisplayString("NtResumeThread failed\n");
   return STATUS_UNSUCCESSFUL;
 }

 *hProcess = processinformation.ProcessHandle;

  return STATUS_SUCCESS;
}
Beispiel #6
0
/**********************************************************************
 * ResumeThread [KERNEL32.@]  Resumes a thread.
 *
 * Decrements a thread's suspend count.  When count is zero, the
 * execution of the thread is resumed.
 *
 * RETURNS
 *    Success: Previous suspend count
 *    Failure: 0xFFFFFFFF
 *    Already running: 0
 */
DWORD WINAPI ResumeThread( HANDLE hthread ) /* [in] Identifies thread to restart */
{
    DWORD ret;
    NTSTATUS status = NtResumeThread( hthread, &ret );

    if (status)
    {
        ret = ~0U;
        SetLastError( RtlNtStatusToDosError(status) );
    }
    return ret;
}
Beispiel #7
0
BOOLEAN
EnableUserModePnpManager(VOID)
{
    LARGE_INTEGER Timeout;

    /* Start the PnP thread */
    if (hPnpThread != NULL)
        NtResumeThread(hPnpThread, NULL);

    /*
     * Wait a little bit so that we get a chance to have some events being
     * queued by the time the device-installation thread becomes resumed.
     */
    Timeout.QuadPart = -10000000LL; /* Wait for 1 second */
    NtWaitForSingleObject(hDeviceInstallListNotEmpty, FALSE, &Timeout);

    /* Start the device installation thread */
    if (hDeviceInstallThread != NULL)
        NtResumeThread(hDeviceInstallThread, NULL);

    return TRUE;
}
Beispiel #8
0
/***************************************************************************
 *                  CreateRemoteThread   (KERNEL32.@)
 *
 * Creates a thread that runs in the address space of another process
 *
 * PARAMS
 *
 * RETURNS
 *   Success: Handle to the new thread.
 *   Failure: NULL. Use GetLastError() to find the error cause.
 *
 * BUGS
 *   Improper memory allocation: there's no ability to free new_thread_info
 *   in other process.
 *   Bad start address for RtlCreateUserThread because the library
 *   may be loaded at different address in other process.
 */
HANDLE WINAPI CreateRemoteThread( HANDLE hProcess, SECURITY_ATTRIBUTES *sa, SIZE_T stack,
                                  LPTHREAD_START_ROUTINE start, LPVOID param,
                                  DWORD flags, LPDWORD id )
{
    HANDLE handle;
    CLIENT_ID client_id;
    NTSTATUS status;
    SIZE_T stack_reserve = 0, stack_commit = 0;

    if (flags & STACK_SIZE_PARAM_IS_A_RESERVATION) stack_reserve = stack;
    else stack_commit = stack;

    status = RtlCreateUserThread( hProcess, NULL, TRUE,
                                  NULL, stack_reserve, stack_commit,
                                  (PRTL_THREAD_START_ROUTINE)start, param, &handle, &client_id );
    if (status == STATUS_SUCCESS)
    {
        if (id) *id = HandleToULong(client_id.UniqueThread);
        if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
            SetHandleInformation( handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT );
        if (!(flags & CREATE_SUSPENDED))
        {
            ULONG ret;
            if (NtResumeThread( handle, &ret ))
            {
                NtClose( handle );
                SetLastError( ERROR_NOT_ENOUGH_MEMORY );
                handle = 0;
            }
        }
    }
    else
    {
        SetLastError( RtlNtStatusToDosError(status) );
        handle = 0;
    }
    return handle;
}
NTSTATUS PhCommandModeStart(
    VOID
    )
{
    static PH_COMMAND_LINE_OPTION options[] =
    {
        { PH_COMMAND_OPTION_HWND, L"hwnd", MandatoryArgumentType }
    };
    NTSTATUS status;
    PPH_STRING commandLine;

    if (!NT_SUCCESS(status = PhGetProcessCommandLine(NtCurrentProcess(), &commandLine)))
        return status;

    PhParseCommandLine(
        &commandLine->sr,
        options,
        sizeof(options) / sizeof(PH_COMMAND_LINE_OPTION),
        PH_COMMAND_LINE_IGNORE_UNKNOWN_OPTIONS,
        PhpCommandModeOptionCallback,
        NULL
        );
    PhDereferenceObject(commandLine);

    if (PhEqualString2(PhStartupParameters.CommandType, L"process", TRUE))
    {
        SIZE_T i;
        SIZE_T processIdLength;
        HANDLE processId;
        HANDLE processHandle;

        if (!PhStartupParameters.CommandObject)
            return STATUS_INVALID_PARAMETER;

        processIdLength = PhStartupParameters.CommandObject->Length / 2;

        for (i = 0; i < processIdLength; i++)
        {
            if (!PhIsDigitCharacter(PhStartupParameters.CommandObject->Buffer[i]))
                break;
        }

        if (i == processIdLength)
        {
            ULONG64 processId64;

            if (!PhStringToInteger64(&PhStartupParameters.CommandObject->sr, 10, &processId64))
                return STATUS_INVALID_PARAMETER;

            processId = (HANDLE)processId64;
        }
        else
        {
            PVOID processes;
            PSYSTEM_PROCESS_INFORMATION process;

            if (!NT_SUCCESS(status = PhEnumProcesses(&processes)))
                return status;

            if (!(process = PhFindProcessInformationByImageName(processes, &PhStartupParameters.CommandObject->sr)))
            {
                PhFree(processes);
                return STATUS_NOT_FOUND;
            }

            processId = process->UniqueProcessId;
            PhFree(processes);
        }

        if (PhEqualString2(PhStartupParameters.CommandAction, L"terminate", TRUE))
        {
            if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_TERMINATE, processId)))
            {
                status = NtTerminateProcess(processHandle, STATUS_SUCCESS);
                NtClose(processHandle);
            }
        }
        else if (PhEqualString2(PhStartupParameters.CommandAction, L"suspend", TRUE))
        {
            if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SUSPEND_RESUME, processId)))
            {
                status = NtSuspendProcess(processHandle);
                NtClose(processHandle);
            }
        }
        else if (PhEqualString2(PhStartupParameters.CommandAction, L"resume", TRUE))
        {
            if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SUSPEND_RESUME, processId)))
            {
                status = NtResumeProcess(processHandle);
                NtClose(processHandle);
            }
        }
        else if (PhEqualString2(PhStartupParameters.CommandAction, L"priority", TRUE))
        {
            UCHAR priority;

            if (!PhStartupParameters.CommandValue)
                return STATUS_INVALID_PARAMETER;

            if (PhEqualString2(PhStartupParameters.CommandValue, L"idle", TRUE))
                priority = PROCESS_PRIORITY_CLASS_IDLE;
            else if (PhEqualString2(PhStartupParameters.CommandValue, L"normal", TRUE))
                priority = PROCESS_PRIORITY_CLASS_NORMAL;
            else if (PhEqualString2(PhStartupParameters.CommandValue, L"high", TRUE))
                priority = PROCESS_PRIORITY_CLASS_HIGH;
            else if (PhEqualString2(PhStartupParameters.CommandValue, L"realtime", TRUE))
                priority = PROCESS_PRIORITY_CLASS_REALTIME;
            else if (PhEqualString2(PhStartupParameters.CommandValue, L"abovenormal", TRUE))
                priority = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
            else if (PhEqualString2(PhStartupParameters.CommandValue, L"belownormal", TRUE))
                priority = PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
            else
                return STATUS_INVALID_PARAMETER;

            if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SET_INFORMATION, processId)))
            {
                PROCESS_PRIORITY_CLASS priorityClass;
                priorityClass.Foreground = FALSE;
                priorityClass.PriorityClass = priority;
                status = NtSetInformationProcess(processHandle, ProcessPriorityClass, &priorityClass, sizeof(PROCESS_PRIORITY_CLASS));
                NtClose(processHandle);
            }
        }
        else if (PhEqualString2(PhStartupParameters.CommandAction, L"iopriority", TRUE))
        {
            ULONG ioPriority;

            if (!PhStartupParameters.CommandValue)
                return STATUS_INVALID_PARAMETER;

            if (PhEqualString2(PhStartupParameters.CommandValue, L"verylow", TRUE))
                ioPriority = 0;
            else if (PhEqualString2(PhStartupParameters.CommandValue, L"low", TRUE))
                ioPriority = 1;
            else if (PhEqualString2(PhStartupParameters.CommandValue, L"normal", TRUE))
                ioPriority = 2;
            else if (PhEqualString2(PhStartupParameters.CommandValue, L"high", TRUE))
                ioPriority = 3;
            else
                return STATUS_INVALID_PARAMETER;

            if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SET_INFORMATION, processId)))
            {
                status = PhSetProcessIoPriority(processHandle, ioPriority);
                NtClose(processHandle);
            }
        }
        else if (PhEqualString2(PhStartupParameters.CommandAction, L"pagepriority", TRUE))
        {
            ULONG64 pagePriority64;
            ULONG pagePriority;

            if (!PhStartupParameters.CommandValue)
                return STATUS_INVALID_PARAMETER;

            PhStringToInteger64(&PhStartupParameters.CommandValue->sr, 10, &pagePriority64);
            pagePriority = (ULONG)pagePriority64;

            if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SET_INFORMATION, processId)))
            {
                status = NtSetInformationProcess(
                    processHandle,
                    ProcessPagePriority,
                    &pagePriority,
                    sizeof(ULONG)
                    );
                NtClose(processHandle);
            }
        }
        else if (PhEqualString2(PhStartupParameters.CommandAction, L"injectdll", TRUE))
        {
            if (!PhStartupParameters.CommandValue)
                return STATUS_INVALID_PARAMETER;

            if (NT_SUCCESS(status = PhOpenProcessPublic(
                &processHandle,
                ProcessQueryAccess | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
                processId
                )))
            {
                LARGE_INTEGER timeout;

                timeout.QuadPart = -5 * PH_TIMEOUT_SEC;
                status = PhInjectDllProcess(
                    processHandle,
                    PhStartupParameters.CommandValue->Buffer,
                    &timeout
                    );
                NtClose(processHandle);
            }
        }
        else if (PhEqualString2(PhStartupParameters.CommandAction, L"unloaddll", TRUE))
        {
            if (!PhStartupParameters.CommandValue)
                return STATUS_INVALID_PARAMETER;

            if (NT_SUCCESS(status = PhOpenProcessPublic(
                &processHandle,
                ProcessQueryAccess | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
                processId
                )))
            {
                PVOID baseAddress;

                if (NT_SUCCESS(status = PhpGetDllBaseRemote(
                    processHandle,
                    &PhStartupParameters.CommandValue->sr,
                    &baseAddress
                    )))
                {
                    LARGE_INTEGER timeout;

                    timeout.QuadPart = -5 * PH_TIMEOUT_SEC;
                    status = PhUnloadDllProcess(
                        processHandle,
                        baseAddress,
                        &timeout
                        );
                }

                NtClose(processHandle);
            }
        }
    }
    else if (PhEqualString2(PhStartupParameters.CommandType, L"service", TRUE))
    {
        SC_HANDLE serviceHandle;
        SERVICE_STATUS serviceStatus;

        if (!PhStartupParameters.CommandObject)
            return STATUS_INVALID_PARAMETER;

        if (PhEqualString2(PhStartupParameters.CommandAction, L"start", TRUE))
        {
            if (!(serviceHandle = PhOpenService(
                PhStartupParameters.CommandObject->Buffer,
                SERVICE_START
                )))
                return PhGetLastWin32ErrorAsNtStatus();

            if (!StartService(serviceHandle, 0, NULL))
                status = PhGetLastWin32ErrorAsNtStatus();

            CloseServiceHandle(serviceHandle);
        }
        else if (PhEqualString2(PhStartupParameters.CommandAction, L"continue", TRUE))
        {
            if (!(serviceHandle = PhOpenService(
                PhStartupParameters.CommandObject->Buffer,
                SERVICE_PAUSE_CONTINUE
                )))
                return PhGetLastWin32ErrorAsNtStatus();

            if (!ControlService(serviceHandle, SERVICE_CONTROL_CONTINUE, &serviceStatus))
                status = PhGetLastWin32ErrorAsNtStatus();

            CloseServiceHandle(serviceHandle);
        }
        else if (PhEqualString2(PhStartupParameters.CommandAction, L"pause", TRUE))
        {
            if (!(serviceHandle = PhOpenService(
                PhStartupParameters.CommandObject->Buffer,
                SERVICE_PAUSE_CONTINUE
                )))
                return PhGetLastWin32ErrorAsNtStatus();

            if (!ControlService(serviceHandle, SERVICE_CONTROL_PAUSE, &serviceStatus))
                status = PhGetLastWin32ErrorAsNtStatus();

            CloseServiceHandle(serviceHandle);
        }
        else if (PhEqualString2(PhStartupParameters.CommandAction, L"stop", TRUE))
        {
            if (!(serviceHandle = PhOpenService(
                PhStartupParameters.CommandObject->Buffer,
                SERVICE_STOP
                )))
                return PhGetLastWin32ErrorAsNtStatus();

            if (!ControlService(serviceHandle, SERVICE_CONTROL_STOP, &serviceStatus))
                status = PhGetLastWin32ErrorAsNtStatus();

            CloseServiceHandle(serviceHandle);
        }
        else if (PhEqualString2(PhStartupParameters.CommandAction, L"delete", TRUE))
        {
            if (!(serviceHandle = PhOpenService(
                PhStartupParameters.CommandObject->Buffer,
                DELETE
                )))
                return PhGetLastWin32ErrorAsNtStatus();

            if (!DeleteService(serviceHandle))
                status = PhGetLastWin32ErrorAsNtStatus();

            CloseServiceHandle(serviceHandle);
        }
    }
    else if (PhEqualString2(PhStartupParameters.CommandType, L"thread", TRUE))
    {
        ULONG64 threadId64;
        HANDLE threadId;
        HANDLE threadHandle;

        if (!PhStartupParameters.CommandObject)
            return STATUS_INVALID_PARAMETER;

        if (!PhStringToInteger64(&PhStartupParameters.CommandObject->sr, 10, &threadId64))
            return STATUS_INVALID_PARAMETER;

        threadId = (HANDLE)threadId64;

        if (PhEqualString2(PhStartupParameters.CommandAction, L"terminate", TRUE))
        {
            if (NT_SUCCESS(status = PhOpenThreadPublic(&threadHandle, THREAD_TERMINATE, threadId)))
            {
                status = NtTerminateThread(threadHandle, STATUS_SUCCESS);
                NtClose(threadHandle);
            }
        }
        else if (PhEqualString2(PhStartupParameters.CommandAction, L"suspend", TRUE))
        {
            if (NT_SUCCESS(status = PhOpenThreadPublic(&threadHandle, THREAD_SUSPEND_RESUME, threadId)))
            {
                status = NtSuspendThread(threadHandle, NULL);
                NtClose(threadHandle);
            }
        }
        else if (PhEqualString2(PhStartupParameters.CommandAction, L"resume", TRUE))
        {
            if (NT_SUCCESS(status = PhOpenThreadPublic(&threadHandle, THREAD_SUSPEND_RESUME, threadId)))
            {
                status = NtResumeThread(threadHandle, NULL);
                NtClose(threadHandle);
            }
        }
    }

    return status;
}
Beispiel #10
0
NTSTATUS ModifySelfSizeOfImage(LPWSTR ExeFullPath, LPWSTR CommandLine, ULONG SizeOfImage)
{
    BOOL                        Result;
    ULONG                       Length;
    PVOID                       FakeCPInfoBuffer;
    WCHAR                       CmdFullPath[MAX_NTPATH];
    PWCHAR                      CmdLineBuffer;
    NTSTATUS                    Status;
    PLDR_MODULE                 LdrModule;
    PIMAGE_DOS_HEADER           DosHeader;
    PIMAGE_NT_HEADERS           NtHeader;
    PIMAGE_SECTION_HEADER       SectionHeader;
    FAKE_CREATE_PROCESS_INFO   *fcpi;
    PROCESS_INFORMATION         ProcessInformation;
    CONTEXT                     Context;
    NtFileDisk                 file;
    UNICODE_STRING              ExeNtPath, *ProcessCommandLine;

    UNREFERENCED_PARAMETER(CommandLine);

    LdrModule = Nt_FindLdrModuleByName(NULL);

    DosHeader   = (PIMAGE_DOS_HEADER)&__ImageBase;
    NtHeader    = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHeader + DosHeader->e_lfanew);

    fcpi = (FAKE_CREATE_PROCESS_INFO *)AllocStack(0x2000);
    fcpi->PeHeaderSize = (ULONG_PTR)(IMAGE_FIRST_SECTION(NtHeader) + NtHeader->FileHeader.NumberOfSections) - (ULONG_PTR)DosHeader;

    Status = file.Open(LdrModule->FullDllName.Buffer);
    if (!NT_SUCCESS(Status))
        return Status;

    Status = file.Read(fcpi->PeHeader, fcpi->PeHeaderSize);
    if (!NT_SUCCESS(Status))
        return Status;

    CmdLineBuffer = (PWCHAR)((ULONG_PTR)fcpi->PeHeader + fcpi->PeHeaderSize);

    fcpi->CommandLine.Buffer        = CmdLineBuffer;
    fcpi->CommandLine.Length        = (USHORT)(StrLengthW(ExeFullPath) * sizeof(WCHAR));

    ProcessCommandLine = &Nt_CurrentPeb()->ProcessParameters->CommandLine;
    CopyMemory(CmdLineBuffer, ProcessCommandLine->Buffer, ProcessCommandLine->Length);
    *(PULONG_PTR)&CmdLineBuffer += ProcessCommandLine->Length;
    CmdLineBuffer[0] = 0;

    fcpi->CommandLine.Length        = ProcessCommandLine->Length;
    fcpi->CommandLine.MaximumLength = fcpi->CommandLine.Length + sizeof(WCHAR);

    ++CmdLineBuffer;
    CmdLineBuffer = (PWCHAR)ROUND_UP((ULONG_PTR)CmdLineBuffer, 16);

    RtlDosPathNameToNtPathName_U(LdrModule->FullDllName.Buffer, &ExeNtPath, NULL, NULL);

    fcpi->ExeNtPath.Buffer = CmdLineBuffer;
    CopyMemory(CmdLineBuffer, ExeNtPath.Buffer, ExeNtPath.Length);
    *(PULONG_PTR)&CmdLineBuffer += ExeNtPath.Length;
    CmdLineBuffer[0] = 0;

    fcpi->ExeNtPath.Length        = ExeNtPath.Length;
    fcpi->ExeNtPath.MaximumLength = fcpi->ExeNtPath.Length + sizeof(WCHAR);

    *CmdLineBuffer++ = 0;

    RtlFreeUnicodeString(&ExeNtPath);

    DosHeader       = (PIMAGE_DOS_HEADER)fcpi->PeHeader;
    NtHeader        = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHeader + DosHeader->e_lfanew);
    SectionHeader   = IMAGE_FIRST_SECTION(NtHeader);

    SectionHeader   += NtHeader->FileHeader.NumberOfSections - 1;
    SizeOfImage     -= LdrModule->SizeOfImage;
    SizeOfImage      = ROUND_UP(SizeOfImage, MEMORY_PAGE_SIZE);

    SectionHeader->Misc.VirtualSize = ROUND_UP(SectionHeader->Misc.VirtualSize, MEMORY_PAGE_SIZE) + SizeOfImage;

    if (NtHeader->FileHeader.SizeOfOptionalHeader > FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, SizeOfImage) + RTL_FIELD_SIZE(IMAGE_OPTIONAL_HEADER, SizeOfImage))
        NtHeader->OptionalHeader.SizeOfImage += SizeOfImage;

    Length = Nt_GetSystemDirectory(CmdFullPath, countof(CmdFullPath));
    StrCopyW(CmdFullPath + Length, L"cmd.exe");

    ProcessInformation.hProcess = NtCurrentProcess();
    ProcessInformation.hThread  = NtCurrentThread();

#if 1
    Result = Nt_CreateProcess(NULL, CmdFullPath, NULL, CREATE_SUSPENDED, NULL, &ProcessInformation);
    if (!Result)
        return STATUS_UNSUCCESSFUL;
#endif

    FakeCPInfoBuffer = NULL;
    LOOP_ONCE
    {
        ULONG_PTR Offset;

        Status = NtDuplicateObject(
                    NtCurrentProcess(),
                    NtCurrentProcess(),
                    ProcessInformation.hProcess,
                    &fcpi->ProcessHandle,
                    0,
                    0,
                    DUPLICATE_SAME_ACCESS
                 );
        if (!NT_SUCCESS(Status))
            break;
/*
        Status = NtDuplicateObject(
                    NtCurrentProcess(),
                    file,
                    ProcessInformation.hProcess,
                    &fcpi->FileHandle,
                    0,
                    0,
                    DUPLICATE_SAME_ACCESS
                 );
        if (!NT_SUCCESS(Status))
            break;
*/
        Status = Nt_AllocateMemory(ProcessInformation.hProcess, &FakeCPInfoBuffer, MEMORY_PAGE_SIZE);
        if (!NT_SUCCESS(Status))
            break;

        fcpi->CreateProcessInternalW    = CreateProcessInternalW;
        fcpi->NtTerminateProcess        = NtTerminateProcess;
        fcpi->LdrShutdownProcess        = LdrShutdownProcess;
        fcpi->NtCreateFile              = NtCreateFile;
        fcpi->NtWriteFile               = NtWriteFile;
        fcpi->NtClose                   = NtClose;
        fcpi->NtWaitForSingleObject     = NtWaitForSingleObject;
        fcpi->InitialDirectory.Buffer   = NULL;

        Offset = (ULONG_PTR)FakeCPInfoBuffer - (ULONG_PTR)fcpi;
        *(PULONG_PTR)&fcpi->CommandLine.Buffer += Offset;
        *(PULONG_PTR)&fcpi->ExeNtPath.Buffer   += Offset;

        Status = Nt_WriteMemory(
                    ProcessInformation.hProcess,
                    FakeCPInfoBuffer,
                    fcpi,
                    (ULONG_PTR)CmdLineBuffer - (ULONG_PTR)fcpi,
                    &Length
                );
        if (!NT_SUCCESS(Status))
            break;

        Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
        Status = NtGetContextThread(ProcessInformation.hThread, &Context);
        if (!NT_SUCCESS(Status))
            break;

        Context.Eip = (ULONG_PTR)FakeCPInfoBuffer + Length;
        Context.Eip = ROUND_UP(Context.Eip, 16);
        Context.Ecx = (ULONG_PTR)FakeCPInfoBuffer;

        Status = Nt_WriteMemory(
                    ProcessInformation.hProcess,
                    (PVOID)Context.Eip,
                    ModifySizeOfImage,
                    (ULONG_PTR)ModifySizeOfImageEnd - (ULONG_PTR)ModifySizeOfImage,
                    &Length
                );
        if (!NT_SUCCESS(Status))
            break;

#if 1
        Status = NtSetContextThread(ProcessInformation.hThread, &Context);
        if (!NT_SUCCESS(Status))
            break;

        Status = NtResumeThread(ProcessInformation.hThread, NULL);
#else
        INLINE_ASM jmp Context.Eip;
#endif
    }

    if (!NT_SUCCESS(Status))
    {
        if (FakeCPInfoBuffer != NULL)
            Nt_FreeMemory(ProcessInformation.hProcess, FakeCPInfoBuffer);

        NtTerminateProcess(ProcessInformation.hProcess, 0);
    }

    NtClose(ProcessInformation.hProcess);
    NtClose(ProcessInformation.hThread);

    return Status;
}
Beispiel #11
0
NTSTATUS
NTAPI
SmpSbCreateSession(IN PVOID Reserved,
                   IN PSMP_SUBSYSTEM OtherSubsystem,
                   IN PRTL_USER_PROCESS_INFORMATION ProcessInformation,
                   IN ULONG MuSessionId,
                   IN PCLIENT_ID DbgClientId)
{
    NTSTATUS Status;
    PSMP_SUBSYSTEM KnownSubsys;
    SB_API_MSG SbApiMsg;
    ULONG SessionId;
    PSB_CREATE_SESSION_MSG CreateSessionMsg;

    /* Write out the create session message including its initial process */
    CreateSessionMsg = &SbApiMsg.CreateSession;
    CreateSessionMsg->ProcessInfo = *ProcessInformation;
    CreateSessionMsg->MuSessionId = MuSessionId;
    if (DbgClientId)
    {
        CreateSessionMsg->ClientId = *DbgClientId;
    }
    else
    {
        CreateSessionMsg->ClientId.UniqueThread = NULL;
        CreateSessionMsg->ClientId.UniqueProcess = NULL;
    }

    /* Find a subsystem responsible for this session */
    SmpGetProcessMuSessionId(ProcessInformation->ProcessHandle, &MuSessionId);
    if (!SmpCheckDuplicateMuSessionId(MuSessionId))
    {
        NtClose(ProcessInformation->ProcessHandle);
        NtClose(ProcessInformation->ThreadHandle);
        DPRINT1("SMSS: CreateSession status=%x\n", STATUS_OBJECT_NAME_NOT_FOUND);
        return STATUS_OBJECT_NAME_NOT_FOUND;
    }

    /* Find the subsystem we have for this initial process */
    KnownSubsys = SmpLocateKnownSubSysByType(MuSessionId,
                                             ProcessInformation->
                                             ImageInformation.SubSystemType);
    if (KnownSubsys)
    {
        /* Duplicate the process handle into the message */
        Status = NtDuplicateObject(NtCurrentProcess(),
                                   ProcessInformation->ProcessHandle,
                                   KnownSubsys->ProcessHandle,
                                   &CreateSessionMsg->ProcessInfo.ProcessHandle,
                                   PROCESS_ALL_ACCESS,
                                   0,
                                   0);
        if (NT_SUCCESS(Status))
        {
            /* Duplicate the thread handle into the message */
            Status = NtDuplicateObject(NtCurrentProcess(),
                                       ProcessInformation->ThreadHandle,
                                       KnownSubsys->ProcessHandle,
                                       &CreateSessionMsg->ProcessInfo.ThreadHandle,
                                       THREAD_ALL_ACCESS,
                                       0,
                                       0);
            if (!NT_SUCCESS(Status))
            {
                /* Close everything on failure */
                NtClose(ProcessInformation->ProcessHandle);
                NtClose(ProcessInformation->ThreadHandle);
                SmpDereferenceSubsystem(KnownSubsys);
                DbgPrint("SmpSbCreateSession: NtDuplicateObject (Thread) Failed %lx\n", Status);
                return Status;
            }

            /* Close the original handles as they are no longer needed */
            NtClose(ProcessInformation->ProcessHandle);
            NtClose(ProcessInformation->ThreadHandle);

            /* Finally, allocate a new SMSS session ID for this session */
            SessionId = SmpAllocateSessionId(KnownSubsys, OtherSubsystem);
            CreateSessionMsg->SessionId = SessionId;

            /* Fill out the LPC message header and send it to the client! */
            SbApiMsg.ApiNumber = SbpCreateSession;
            SbApiMsg.h.u2.ZeroInit = 0;
            SbApiMsg.h.u1.s1.DataLength = sizeof(SB_CREATE_SESSION_MSG) + 8;
            SbApiMsg.h.u1.s1.TotalLength = sizeof(SbApiMsg);
            Status = NtRequestWaitReplyPort(KnownSubsys->SbApiPort,
                                            &SbApiMsg.h,
                                            &SbApiMsg.h);
            if (!NT_SUCCESS(Status))
            {
                /* Bail out */
                DPRINT1("SmpSbCreateSession: NtRequestWaitReply Failed %lx\n", Status);
            }
            else
            {
                /* If the API succeeded, get the result value from the LPC */
                Status = SbApiMsg.ReturnValue;
            }

            /* Delete the session on any kind of failure */
            if (!NT_SUCCESS(Status)) SmpDeleteSession(SessionId);
        }
        else
        {
            /* Close the handles on failure */
            DPRINT1("SmpSbCreateSession: NtDuplicateObject (Process) Failed %lx\n", Status);
            NtClose(ProcessInformation->ProcessHandle);
            NtClose(ProcessInformation->ThreadHandle);
        }

        /* Dereference the subsystem and return the status of the LPC call */
        SmpDereferenceSubsystem(KnownSubsys);
        return Status;
    }

    /* If we don't yet have a subsystem, only native images can be launched */
    if (ProcessInformation->ImageInformation.SubSystemType != IMAGE_SUBSYSTEM_NATIVE)
    {
        /* Fail */
        DPRINT1("SMSS: %s SubSystem has not been started.\n",
                SmpSubSystemNames[ProcessInformation->ImageInformation.SubSystemType]);
        Status = STATUS_UNSUCCESSFUL;
        NtClose(ProcessInformation->ProcessHandle);
        NtClose(ProcessInformation->ThreadHandle);
        return Status;
    }

#if 0
    /* This code handles debug applications, but it seems vestigial... */
    if ((*(ULONGLONG)&CreateSessionMsg.ClientId) && (SmpDbgSsLoaded))
    {
        Process = RtlAllocateHeap(SmpHeap, SmBaseTag, sizeof(SMP_PROCESS));
        if (!Process)
        {
            DPRINT1("Unable to initialize debugging for Native App %lx.%lx -- out of memory\n",
                    ProcessInformation->ClientId.UniqueProcess,
                    ProcessInformation->ClientId.UniqueThread);
            NtClose(ProcessInformation->ProcessHandle);
            NtClose(ProcessInformation->ThreadHandle);
            return STATUS_NO_MEMORY;
        }

        Process->DbgClientId = CreateSessionMsg->ClientId;
        Process->ClientId = ProcessInformation->ClientId;
        InsertHeadList(&NativeProcessList, &Process->Entry);
        DPRINT1("Native Debug App %lx.%lx\n", Process->ClientId.UniqueProcess, Process->ClientId.UniqueThread);

        Status = NtSetInformationProcess(ProcessInformation->ProcessHandle, 7, &SmpDebugPort, 4);
        ASSERT(NT_SUCCESS(Status));
    }
#endif

    /* This is a native application being started as the initial command */
    DPRINT1("Subsystem active, starting thread\n");
    NtClose(ProcessInformation->ProcessHandle);
    NtResumeThread(ProcessInformation->ThreadHandle, NULL);
    NtClose(ProcessInformation->ThreadHandle);
    return STATUS_SUCCESS;
}
Beispiel #12
0
		void Thread::Resume()
		{
			NtResumeThread(&system_thread_handle, suspendCount);
			state = ThreadState::Running;
		}
Beispiel #13
0
UdbgTest2()
{
    NTSTATUS st;
    HANDLE ExceptionThread, DebugProcess;
    DBGKM_APIMSG m;
    PDBGKM_CREATE_THREAD CreateThreadArgs;
    PDBGKM_CREATE_PROCESS CreateProcessArgs;
    PDBGKM_EXIT_THREAD ExitThreadArgs;
    PDBGKM_EXIT_PROCESS ExitProcessArgs;
    PDBGKM_EXCEPTION ExceptionArgs;
    ULONG Psp;

    DbgPrint("UdbgTest2: (1)...\n");

        //
        // Verify that a process can be created with a debug
        // port.
        //

        st = NtCreateProcess(
                &DebugProcess,
                PROCESS_ALL_ACCESS,
                NULL,
                NtCurrentProcess(),
                FALSE,
                NULL,
                DebugPort,
                NULL
                );
        ASSERT(NT_SUCCESS(st));

        st = RtlCreateUserThread(
                DebugProcess,
                NULL,
                TRUE,
                0L,
                0L,
                0L,
                ThreadThatExcepts,
                (PVOID) STATUS_ABANDONED,
                &ExceptionThread,
                NULL
                );
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest2: (2)...\n");

        //
        // Verify that CreateThread Messages Arrive, and that
        // they are correct
        //

        st = NtResumeThread(ExceptionThread,NULL);
        ASSERT(NT_SUCCESS(st));

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmCreateProcessApi);

        CreateThreadArgs = &m.u.CreateProcess.InitialThread;
        CreateProcessArgs = &m.u.CreateProcess;
        ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatExcepts );
        ASSERT( CreateProcessArgs->SubSystemKey == 0);

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest2: (3)...\n");

        //
        // Verify that First Chance Exception Messages Arrive, and that
        // they are correct
        //

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmExceptionApi);

        ExceptionArgs = &m.u.Exception;
        ASSERT( ExceptionArgs->FirstChance == TRUE );

        m.ReturnedStatus = DBG_EXCEPTION_NOT_HANDLED;

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest2: (4)...\n");

        //
        // Verify that First Chance Exception Messages Arrive, and that
        // they are correct
        //

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmExceptionApi);

        ExceptionArgs = &m.u.Exception;
        ASSERT( ExceptionArgs->FirstChance == FALSE );

        m.ReturnedStatus = DBG_EXCEPTION_HANDLED;
skip4:
        st = NtTerminateProcess(DebugProcess,STATUS_REPARSE);
        ASSERT(NT_SUCCESS(st));

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmExitThreadApi);

        ExitThreadArgs = &m.u.ExitThread;
        ASSERT( ExitThreadArgs->ExitStatus == STATUS_REPARSE );

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest2: (5)...\n");

        //
        // Verify that ExitProcess Messages Arrive, and that
        // they are correct
        //

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmExitProcessApi);

        ExitProcessArgs = &m.u.ExitProcess;
        ASSERT( ExitProcessArgs->ExitStatus == STATUS_REPARSE );

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));


        st = NtWaitForSingleObject(ExceptionThread,FALSE,NULL);
        ASSERT(NT_SUCCESS(st));

        st = NtWaitForSingleObject(DebugProcess,FALSE,NULL);
        ASSERT(NT_SUCCESS(st));

    NtClose(ExceptionThread);
    NtClose(DebugProcess);

    DbgPrint("UdbgTest2: END OF TEST ***\n");
}
Beispiel #14
0
NTSTATUS InjectSelfToRemoteProcess(HANDLE hProcess, HANDLE hThread)
{
    NTSTATUS    Status;
    PVOID       pvBuffer;
    DWORD       Length;
    WCHAR       szSelfPath[MAX_PATH];
    CONTEXT     ThreadContext;
    LARGE_INTEGER TimeOut;
    INJECT_DLL_CURRENT_THREAD inj;

    ThreadContext.ContextFlags = CONTEXT_CONTROL;
    Status = NtGetContextThread(hThread, &ThreadContext);
    if (!NT_SUCCESS(Status))
    {
//        BaseSetLastNTError(Status);
//        PrintError(RtlGetLastWin32Error());
        return Status;
    }

//    PrintConsoleW(L"Eip = %08X\n", ThreadContext.Eip);
//    getch();

    Length = Nt_GetExeDirectory(szSelfPath, countof(szSelfPath));
    if (Length == NULL)
        return STATUS_UNSUCCESSFUL;

    static WCHAR szDll[] = L"LocaleEmulator.dll";
    StrCopyW(szSelfPath + Length, szDll);
    Length += CONST_STRLEN(szDll);

    pvBuffer = NULL;
    Status = Nt_AllocateMemory(hProcess, &pvBuffer, MEMORY_PAGE_SIZE);
    if (!NT_SUCCESS(Status))
    {
//        BaseSetLastNTError(Status);
//        PrintError(RtlGetLastWin32Error());
        return Status;
    }

    Length *= sizeof(WCHAR);
    inj.pfLdrLoadDll = LdrLoadDll;
    inj.ReturnAddr   = ThreadContext.Eip;
    inj.ModuleFileName.Length = Length;
    inj.ModuleFileName.MaximumLength = Length + sizeof(WCHAR);
    inj.ModuleFileName.Buffer = (LPWSTR)((ULONG_PTR)pvBuffer + sizeof(inj));

    Status = STATUS_UNSUCCESSFUL;
    LOOP_ONCE
    {
        Status = Nt_WriteMemory(hProcess, pvBuffer, &inj, sizeof(inj));
        if (!NT_SUCCESS(Status))
            break;

        Length += sizeof(WCHAR);
        Status = Nt_WriteMemory(hProcess, (PVOID)((ULONG_PTR)pvBuffer + sizeof(inj)), szSelfPath, Length);
        if (!NT_SUCCESS(Status))
            break;

        ThreadContext.Eip = (DWORD)(PBYTE)pvBuffer + sizeof(inj) + Length;
        Status = Nt_WriteMemory(
                    hProcess,
                    (PVOID)ThreadContext.Eip,
                    LoadExternDll,
                    (ULONG_PTR)_LoadExternDllEnd - (ULONG_PTR)LoadExternDll
                 );
        if (!NT_SUCCESS(Status))
            break;

        Status = NtSetContextThread(hThread, &ThreadContext);
        if (!NT_SUCCESS(Status))
            break;

        Status = NtResumeThread(hThread, NULL);
        if (!NT_SUCCESS(Status))
            break;

        BaseFormatTimeOut(&TimeOut, 500);
        for (DWORD TryTimes = 30; TryTimes; --TryTimes)
        {
            DWORD Val;
            Status = Nt_ReadMemory(hProcess, pvBuffer, &Val, sizeof(Val));
            if (!NT_SUCCESS(Status))
                break;

            if (Val != 0)
            {
                NtDelayExecution(FALSE, &TimeOut);
                continue;
            }

            break;
        }

        if (!NT_SUCCESS(Status))
            break;

        NtDelayExecution(FALSE, &TimeOut);
        Status = NtGetContextThread(hThread, &ThreadContext);
        if (!NT_SUCCESS(Status))
            break;

        if ((ULONG_PTR)ThreadContext.Eip < (ULONG_PTR)pvBuffer ||
            (ULONG_PTR)ThreadContext.Eip > (ULONG_PTR)pvBuffer + MEMORY_PAGE_SIZE)
        {
            Status = STATUS_SUCCESS;
        }
        else
        {
            Status = STATUS_UNSUCCESSFUL;
        }
    }

//    BaseSetLastNTError(Status);
//    PrintError(RtlGetLastWin32Error());

//    Nt_FreeMemory(hProcess, pvBuffer);

    return Status;
}
Beispiel #15
0
NTSTATUS
NTAPI
SmpExecuteInitialCommand(IN ULONG MuSessionId,
                         IN PUNICODE_STRING InitialCommand,
                         IN HANDLE InitialCommandProcess,
                         OUT PHANDLE ReturnPid)
{
    NTSTATUS Status;
    RTL_USER_PROCESS_INFORMATION ProcessInfo;
    UNICODE_STRING Arguments, ImageFileDirectory, ImageFileName;
    ULONG Flags = 0;

    /* Check if we haven't yet connected to ourselves */
    if (!SmApiPort)
    {
        /* Connect to ourselves, as a client */
        Status = SmConnectToSm(0, 0, 0, &SmApiPort);
        if (!NT_SUCCESS(Status))
        {
            DPRINT1("SMSS: Unable to connect to SM - Status == %lx\n", Status);
            return Status;
        }
    }

    /* Parse the initial command line */
    Status = SmpParseCommandLine(InitialCommand,
                                 &Flags,
                                 &ImageFileName,
                                 &ImageFileDirectory,
                                 &Arguments);
    if (Flags & SMP_INVALID_PATH)
    {
        /* Fail if it doesn't exist */
        DPRINT1("SMSS: Initial command image (%wZ) not found\n", &ImageFileName);
        if (ImageFileName.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, ImageFileName.Buffer);
        return STATUS_OBJECT_NAME_NOT_FOUND;
    }

    /* And fail if any other reason is also true */
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("SMSS: SmpParseCommandLine( %wZ ) failed - Status == %lx\n",
                InitialCommand, Status);
        return Status;
    }

    /* Execute the initial command -- but defer its full execution */
    Status = SmpExecuteImage(&ImageFileName,
                             &ImageFileDirectory,
                             InitialCommand,
                             MuSessionId,
                             SMP_DEFERRED_FLAG,
                             &ProcessInfo);

    /* Free any buffers we had lying around */
    if (ImageFileName.Buffer)
    {
        RtlFreeHeap(RtlGetProcessHeap(), 0, ImageFileName.Buffer);
    }
    if (ImageFileDirectory.Buffer)
    {
        RtlFreeHeap(RtlGetProcessHeap(), 0, ImageFileDirectory.Buffer);
    }
    if (Arguments.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Arguments.Buffer);

    /* Bail out if we couldn't execute the initial command */
    if (!NT_SUCCESS(Status)) return Status;

    /* Now duplicate the handle to this process */
    Status = NtDuplicateObject(NtCurrentProcess(),
                               ProcessInfo.ProcessHandle,
                               NtCurrentProcess(),
                               InitialCommandProcess,
                               PROCESS_ALL_ACCESS,
                               0,
                               0);
    if (!NT_SUCCESS(Status))
    {
        /* Kill it utterly if duplication failed */
        DPRINT1("SMSS: DupObject Failed. Status == %lx\n", Status);
        NtTerminateProcess(ProcessInfo.ProcessHandle, Status);
        NtResumeThread(ProcessInfo.ThreadHandle, NULL);
        NtClose(ProcessInfo.ThreadHandle);
        NtClose(ProcessInfo.ProcessHandle);
        return Status;
    }

    /* Return PID to the caller, and set this as the initial command PID */
    if (ReturnPid) *ReturnPid = ProcessInfo.ClientId.UniqueProcess;
    if (!MuSessionId) SmpInitialCommandProcessId = ProcessInfo.ClientId.UniqueProcess;

    /* Now call our server execution function to wrap up its initialization */
    Status = SmExecPgm(SmApiPort, &ProcessInfo, FALSE);
    if (!NT_SUCCESS(Status)) DPRINT1("SMSS: SmExecPgm Failed. Status == %lx\n", Status);
    return Status;
}
Beispiel #16
0
/******************************************************************************
 *              NtAlertResumeThread   (NTDLL.@)
 *              ZwAlertResumeThread   (NTDLL.@)
 */
NTSTATUS WINAPI NtAlertResumeThread( HANDLE handle, PULONG count )
{
    FIXME( "stub: should alert thread %p\n", handle );
    return NtResumeThread( handle, count );
}
Beispiel #17
0
/*++
 * @name CsrpCheckRequestThreads
 *
 * The CsrpCheckRequestThreads routine checks if there are no more threads
 * to handle CSR API Requests, and creates a new thread if possible, to
 * avoid starvation.
 *
 * @param None.
 *
 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
 *         if a new thread couldn't be created.
 *
 * @remarks None.
 *
 *--*/
NTSTATUS
NTAPI
CsrpCheckRequestThreads(VOID)
{
    HANDLE hThread;
    CLIENT_ID ClientId;
    NTSTATUS Status;

    /* Decrease the count, and see if we're out */
    if (InterlockedDecrementUL(&CsrpStaticThreadCount) == 0)
    {
        /* Check if we've still got space for a Dynamic Thread */
        if (CsrpDynamicThreadTotal < CsrMaxApiRequestThreads)
        {
            /* Create a new dynamic thread */
            Status = RtlCreateUserThread(NtCurrentProcess(),
                                         NULL,
                                         TRUE,
                                         0,
                                         0,
                                         0,
                                         (PVOID)CsrApiRequestThread,
                                         NULL,
                                         &hThread,
                                         &ClientId);
            /* Check success */
            if (NT_SUCCESS(Status))
            {
                /* Increase the thread counts */
                InterlockedIncrementUL(&CsrpStaticThreadCount);
                InterlockedIncrementUL(&CsrpDynamicThreadTotal);

                /* Add a new server thread */
                if (CsrAddStaticServerThread(hThread,
                                             &ClientId,
                                             CsrThreadIsServerThread))
                {
                    /* Activate it */
                    NtResumeThread(hThread, NULL);
                }
                else
                {
                    /* Failed to create a new static thread */
                    InterlockedDecrementUL(&CsrpStaticThreadCount);
                    InterlockedDecrementUL(&CsrpDynamicThreadTotal);

                    /* Terminate it */
                    DPRINT1("Failing\n");
                    NtTerminateThread(hThread, 0);
                    NtClose(hThread);

                    /* Return */
                    return STATUS_UNSUCCESSFUL;
                }
            }
        }
    }

    /* Success */
    return STATUS_SUCCESS;
}
Beispiel #18
0
// FIXME: Maybe return a NTSTATUS
static BOOL
GuiInit(IN PCONSOLE_INIT_INFO ConsoleInitInfo,
        IN HANDLE ConsoleLeaderProcessHandle,
        IN OUT PGUI_INIT_INFO GuiInitInfo)
{
    BOOL Success = TRUE;
    UNICODE_STRING DesktopPath;
    DESKTOP_CONSOLE_THREAD DesktopConsoleThreadInfo;
    HWINSTA hWinSta;
    HDESK hDesk;

    NTSTATUS Status;
    HANDLE hInputThread;
    CLIENT_ID ClientId;

    /*
     * Initialize and register the console window class, if needed.
     */
    if (!ConsInitialized)
    {
        if (!RegisterConWndClass(ConSrvDllInstance)) return FALSE;
        ConsInitialized = TRUE;
    }

    /*
     * Set-up the console input thread. We have
     * one console input thread per desktop.
     */

    if (!CsrImpersonateClient(NULL))
        // return STATUS_BAD_IMPERSONATION_LEVEL;
        return FALSE;

    if (ConsoleInitInfo->DesktopLength)
    {
        DesktopPath.MaximumLength = ConsoleInitInfo->DesktopLength;
        DesktopPath.Length = DesktopPath.MaximumLength - sizeof(UNICODE_NULL);
        DesktopPath.Buffer = ConsoleInitInfo->Desktop;
    }
    else
    {
        RtlInitUnicodeString(&DesktopPath, L"Default");
    }

    hDesk = NtUserResolveDesktop(ConsoleLeaderProcessHandle,
                                 &DesktopPath,
                                 0,
                                 &hWinSta);
    DPRINT("NtUserResolveDesktop(DesktopPath = '%wZ') returned hDesk = 0x%p; hWinSta = 0x%p\n",
           &DesktopPath, hDesk, hWinSta);

    CsrRevertToSelf();

    if (hDesk == NULL) return FALSE;

    /*
     * We need to see whether we need to create a
     * new console input thread for this desktop.
     */
    DesktopConsoleThreadInfo.DesktopHandle = hDesk;
    DesktopConsoleThreadInfo.ThreadId = (ULONG_PTR)INVALID_HANDLE_VALUE; // Special value to say we just want to retrieve the thread ID.
    NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread,
                         &DesktopConsoleThreadInfo,
                         sizeof(DesktopConsoleThreadInfo));
    DPRINT("NtUserConsoleControl returned ThreadId = 0x%p\n", DesktopConsoleThreadInfo.ThreadId);

    /*
     * Save the opened window station and desktop handles in the initialization
     * structure. They will be used later on, and released, by the GUI frontend.
     */
    GuiInitInfo->WinSta  = hWinSta;
    GuiInitInfo->Desktop = hDesk;

    /* Here GuiInitInfo contains original handles */

    /* If we already have a console input thread on this desktop... */
    if (DesktopConsoleThreadInfo.ThreadId != 0)
    {
        /* ... just use it... */
        DPRINT("Using input thread InputThreadId = 0x%p\n", DesktopConsoleThreadInfo.ThreadId);
        GuiInitInfo->InputThreadId = DesktopConsoleThreadInfo.ThreadId;
        goto Quit;
    }

    /* ... otherwise create a new one. */

    /* Initialize a startup event for the thread to signal it */
    Status = NtCreateEvent(&GuiInitInfo->GuiThreadStartupEvent, EVENT_ALL_ACCESS,
                           NULL, SynchronizationEvent, FALSE);
    if (!NT_SUCCESS(Status))
    {
        Success = FALSE;
        goto Quit;
    }

    /*
     * Duplicate the desktop handle for the console input thread internal needs.
     * If it happens to need also a window station handle in the future, then
     * it is there that you also need to duplicate the window station handle!
     *
     * Note also that we are going to temporarily overwrite the stored handles
     * in GuiInitInfo because it happens that we use also this structure to give
     * the duplicated handles to the input thread that is going to initialize.
     * After the input thread finishes its initialization, we restore the handles
     * in GuiInitInfo to their old values.
     */
    Status = NtDuplicateObject(NtCurrentProcess(),
                               hDesk,
                               NtCurrentProcess(),
                               (PHANDLE)&GuiInitInfo->Desktop,
                               0, 0, DUPLICATE_SAME_ACCESS);
    if (!NT_SUCCESS(Status))
    {
        Success = FALSE;
        goto Quit;
    }

    /* Here GuiInitInfo contains duplicated handles */

    Status = RtlCreateUserThread(NtCurrentProcess(),
                                 NULL,
                                 TRUE, // Start the thread in suspended state
                                 0,
                                 0,
                                 0,
                                 (PVOID)GuiConsoleInputThread,
                                 (PVOID)GuiInitInfo,
                                 &hInputThread,
                                 &ClientId);
    if (NT_SUCCESS(Status))
    {
        /* Add it as a static server thread and resume it */
        CsrAddStaticServerThread(hInputThread, &ClientId, 0);
        Status = NtResumeThread(hInputThread, NULL);
    }
    DPRINT("Thread creation hInputThread = 0x%p, InputThreadId = 0x%p, Status = 0x%08lx\n",
           hInputThread, ClientId.UniqueThread, Status);

    if (!NT_SUCCESS(Status) || hInputThread == NULL)
    {
        /* Close the thread's handle */
        if (hInputThread) NtClose(hInputThread);

        /* We need to close here the duplicated desktop handle */
        CloseDesktop(GuiInitInfo->Desktop); // NtUserCloseDesktop

        /* Close the startup event and bail out */
        NtClose(GuiInitInfo->GuiThreadStartupEvent);

        DPRINT1("CONSRV: Failed to create graphics console thread.\n");
        Success = FALSE;
        goto Quit;
    }

    /* No need to close hInputThread, this is done by CSR automatically */

    /* Wait for the thread to finish its initialization, and close the startup event */
    NtWaitForSingleObject(GuiInitInfo->GuiThreadStartupEvent, FALSE, NULL);
    NtClose(GuiInitInfo->GuiThreadStartupEvent);

    /*
     * Save the input thread ID for later use, and restore the original handles.
     * The copies are held by the console input thread.
     */
    GuiInitInfo->InputThreadId = (ULONG_PTR)ClientId.UniqueThread;
    GuiInitInfo->WinSta  = hWinSta;
    GuiInitInfo->Desktop = hDesk;

    /* Here GuiInitInfo contains again original handles */

Quit:
    if (!Success)
    {
        /*
         * Close the original handles. Do not use the copies in GuiInitInfo
         * because we may have failed in the middle of the duplicate operation
         * and the handles stored in GuiInitInfo may have changed.
         */
        CloseDesktop(hDesk); // NtUserCloseDesktop
        CloseWindowStation(hWinSta); // NtUserCloseWindowStation
    }

    return Success;
}
Beispiel #19
0
/**********************************************************************
 * SmCreateUserProcess/5
 *
 * DESCRIPTION
 *
 * ARGUMENTS
 *	ImagePath: absolute path of the image to run;
 *	CommandLine: arguments and options for ImagePath;
 *	Flags: Wait flag: Set for boot time processes and unset for
 *			subsystems bootstrapping;
 *		1Mb reserve flag: Set for subsystems, unset for everything
*			else
 *	Timeout: optional: used if WaitForIt==TRUE;
 *	ProcessHandle: optional: a duplicated handle for
 		the child process (storage provided by the caller).
 *
 * RETURN VALUE
 * 	NTSTATUS:
 *
 */
NTSTATUS NTAPI
SmCreateUserProcess (LPWSTR ImagePath,
		     LPWSTR CommandLine,
		     ULONG Flags,
		     PLARGE_INTEGER Timeout OPTIONAL,
		     PRTL_USER_PROCESS_INFORMATION UserProcessInfo OPTIONAL)
{
	UNICODE_STRING			ImagePathString   = { 0, 0, NULL };
	UNICODE_STRING			CommandLineString = { 0, 0, NULL };
	UNICODE_STRING			SystemDirectory   = { 0, 0, NULL };
	PRTL_USER_PROCESS_PARAMETERS	ProcessParameters = NULL;
	RTL_USER_PROCESS_INFORMATION	ProcessInfo  = {0};
	PRTL_USER_PROCESS_INFORMATION	pProcessInfo = & ProcessInfo;
	NTSTATUS			Status = STATUS_SUCCESS;

	DPRINT("SM: %s called\n", __FUNCTION__);

	if (NULL != UserProcessInfo)
	{
		pProcessInfo = UserProcessInfo;
	}

	RtlInitUnicodeString (& ImagePathString, ImagePath);
	RtlInitUnicodeString (& CommandLineString, CommandLine);

	SystemDirectory.MaximumLength = (wcslen(SharedUserData->NtSystemRoot) * sizeof(WCHAR)) + sizeof(szSystemDirectory);
	SystemDirectory.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
						 0,
						 SystemDirectory.MaximumLength);
	if (SystemDirectory.Buffer == NULL)
	{
		Status = STATUS_NO_MEMORY;
		DPRINT1("SM: %s: Allocating system directory string failed (Status=0x%08lx)\n",
			__FUNCTION__, Status);
		return Status;
	}

	Status = RtlAppendUnicodeToString(& SystemDirectory,
					  SharedUserData->NtSystemRoot);
	if (!NT_SUCCESS(Status))
	{
		goto FailProcParams;
	}

	Status = RtlAppendUnicodeToString(& SystemDirectory,
					  szSystemDirectory);
	if (!NT_SUCCESS(Status))
	{
		goto FailProcParams;
	}


	Status = RtlCreateProcessParameters(& ProcessParameters,
					    & ImagePathString,
					    NULL,
					    & SystemDirectory,
					    & CommandLineString,
					    SmSystemEnvironment,
					    NULL,
					    NULL,
					    NULL,
					    NULL);

	RtlFreeHeap(RtlGetProcessHeap(),
		    0,
		    SystemDirectory.Buffer);

	if (!NT_SUCCESS(Status))
	{
FailProcParams:
		DPRINT1("SM: %s: Creating process parameters failed (Status=0x%08lx)\n",
			__FUNCTION__, Status);
		return Status;
	}

	/* Reserve lower 1Mb, if requested */
	if (Flags & SM_CREATE_FLAG_RESERVE_1MB)
		ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;

	/* Create the user process */
	Status = RtlCreateUserProcess (& ImagePathString,
				       OBJ_CASE_INSENSITIVE,
				       ProcessParameters,
				       NULL,
				       NULL,
				       NULL,
				       FALSE,
				       NULL,
				       NULL,
				       pProcessInfo);

	RtlDestroyProcessParameters (ProcessParameters);

	if (!NT_SUCCESS(Status))
	{
		DPRINT1("SM: %s: Running \"%S\" failed (Status=0x%08lx)\n",
			__FUNCTION__, ImagePathString.Buffer, Status);
		return Status;
	}
	/*
	 * It the caller is *not* interested in the child info,
	 * resume it immediately.
	 */
	if (NULL == UserProcessInfo)
	{
		Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL);
		if(!NT_SUCCESS(Status))
		{
			DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",
				__FUNCTION__, Status);
		}
	}

	/* Wait for process termination */
	if (Flags & SM_CREATE_FLAG_WAIT)
	{
		Status = NtWaitForSingleObject (pProcessInfo->ProcessHandle,
						FALSE,
						Timeout);
		if (!NT_SUCCESS(Status))
		{
			DPRINT1("SM: %s: NtWaitForSingleObject failed with Status=0x%08lx\n",
				__FUNCTION__, Status);
		}
	}

    if (NULL == UserProcessInfo)
    {
        NtClose(pProcessInfo->ProcessHandle);
        NtClose(pProcessInfo->ThreadHandle);
    }
	return Status;
}
Beispiel #20
0
/*++
 * @name CsrSbCreateSession
 *
 * The CsrSbCreateSession API is called by the Session Manager whenever a new
 * session is created.
 *
 * @param ApiMessage
 *        Pointer to the Session Manager API Message.
 *
 * @return TRUE in case of success, FALSE otherwise.
 *
 * @remarks The CsrSbCreateSession routine will initialize a new CSR NT
 *          Session and allocate a new CSR Process for the subsystem process.
 *
 *--*/
BOOLEAN
NTAPI
CsrSbCreateSession(IN PSB_API_MSG ApiMessage)
{
    PSB_CREATE_SESSION_MSG CreateSession = &ApiMessage->CreateSession;
    HANDLE hProcess, hThread;
    PCSR_PROCESS CsrProcess;
    NTSTATUS Status;
    KERNEL_USER_TIMES KernelTimes;
    PCSR_THREAD CsrThread;
    //PVOID ProcessData;
    //ULONG i;

    /* Save the Process and Thread Handles */
    hProcess = CreateSession->ProcessInfo.ProcessHandle;
    hThread = CreateSession->ProcessInfo.ThreadHandle;

    /* Lock the Processes */
    CsrAcquireProcessLock();

    /* Allocate a new process */
    CsrProcess = CsrAllocateProcess();
    if (!CsrProcess)
    {
        /* Fail */
        ApiMessage->ReturnValue = STATUS_NO_MEMORY;
        CsrReleaseProcessLock();
        return TRUE;
    }

    /* Set the exception port */
    Status = NtSetInformationProcess(hProcess,
                                     ProcessExceptionPort,
                                     &CsrApiPort,
                                     sizeof(HANDLE));

    /* Check for success */
    if (!NT_SUCCESS(Status))
    {
        /* Fail the request */
        CsrDeallocateProcess(CsrProcess);
        CsrReleaseProcessLock();

        /* Strange as it seems, NTSTATUSes are actually returned */
        return (BOOLEAN)STATUS_NO_MEMORY;
    }

    /* Get the Create Time */
    Status = NtQueryInformationThread(hThread,
                                      ThreadTimes,
                                      &KernelTimes,
                                      sizeof(KERNEL_USER_TIMES),
                                      NULL);

    /* Check for success */
    if (!NT_SUCCESS(Status))
    {
        /* Fail the request */
        CsrDeallocateProcess(CsrProcess);
        CsrReleaseProcessLock();

        /* Strange as it seems, NTSTATUSes are actually returned */
        return (BOOLEAN)Status;
    }

    /* Allocate a new Thread */
    CsrThread = CsrAllocateThread(CsrProcess);
    if (!CsrThread)
    {
        /* Fail the request */
        CsrDeallocateProcess(CsrProcess);
        CsrReleaseProcessLock();

        ApiMessage->ReturnValue = STATUS_NO_MEMORY;
        return TRUE;
    }

    /* Setup the Thread Object */
    CsrThread->CreateTime = KernelTimes.CreateTime;
    CsrThread->ClientId = CreateSession->ProcessInfo.ClientId;
    CsrThread->ThreadHandle = hThread;
    ProtectHandle(hThread);
    CsrThread->Flags = 0;

    /* Insert it into the Process List */
    CsrInsertThread(CsrProcess, CsrThread);

    /* Setup Process Data */
    CsrProcess->ClientId = CreateSession->ProcessInfo.ClientId;
    CsrProcess->ProcessHandle = hProcess;
    CsrProcess->NtSession = CsrAllocateNtSession(CreateSession->SessionId);

    /* Set the Process Priority */
    CsrSetBackgroundPriority(CsrProcess);
#if 0
    /* Get the first data location */
    ProcessData = &CsrProcess->ServerData[CSR_SERVER_DLL_MAX];

    /* Loop every DLL */
    for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
    {
        /* Check if the DLL is loaded and has Process Data */
        if (CsrLoadedServerDll[i] && CsrLoadedServerDll[i]->SizeOfProcessData)
        {
            /* Write the pointer to the data */
            CsrProcess->ServerData[i] = ProcessData;

            /* Move to the next data location */
            ProcessData = (PVOID)((ULONG_PTR)ProcessData +
                                  CsrLoadedServerDll[i]->SizeOfProcessData);
        }
        else
        {
            /* Nothing for this Process */
            CsrProcess->ServerData[i] = NULL;
        }
    }
#else
    /* HACKZ: should go in BaseSrv part of CreateCallback done in Insert below */
    RtlInitializeCriticalSection(&CsrProcess->HandleTableLock);
#endif
    /* Insert the Process */
    CsrInsertProcess(NULL, NULL, CsrProcess);

    /* Activate the Thread */
    ApiMessage->ReturnValue = NtResumeThread(hThread, NULL);

    /* Release lock and return */
    CsrReleaseProcessLock();
    return TRUE;
}
Beispiel #21
0
main(
    int argc,
    char **argv,
    char **envp,
    int DebugFlag
    )
{
    NTSTATUS Status;
    STRING ImageName;
    PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
    RTL_USER_PROCESS_INFORMATION ProcessInformation;

    if (argc == 1) {
        TestParent();

        Parameters[ RTL_USER_PROC_PARAMS_IMAGEFILE ] = argv[ 0 ];

        Parameters[ RTL_USER_PROC_PARAMS_CMDLINE ] = " CHILD";

        Parameters[ RTL_USER_PROC_PARAMS_DEBUGFLAG ] =
             DebugFlag ? "1" : "0";

        Parameters[ RTL_USER_PROC_PARAMS_DEBUGFLAG+1 ] = NULL;

        Arguments[ 0 ] = argv[ 0 ];
        Arguments[ 1 ] = "CHILD";
        Arguments[ 2 ] = NULL;

        ProcessParameters = (PRTL_USER_PROCESS_PARAMETERS)ParameterBuffer;
        ProcessParameters->Length = 0;
        ProcessParameters->MaximumLength = sizeof( ParameterBuffer );

        Status = RtlVectorsToProcessParameters( Arguments,
                                                envp,
                                                Parameters,
                                                ProcessParameters
                                              );
        if (!NT_SUCCESS( Status )) {
            DbgPrint( "RtlVectorToProcessParameters failed - Status = %X\n",
                      Status
                    );
            }
        else {
            RtlInitString( &ImageName, "\\C:\\TMP\\UOB.EXE" );
            Status = RtlCreateUserProcess( &ImageName,
                                           NULL,
                                           NULL,
                                           NULL,
                                           TRUE,
                                           NULL,
                                           NULL,
                                           ProcessParameters,
                                           &ProcessInformation,
                                           NULL
                                         );
            if (!NT_SUCCESS( Status )) {
                DbgPrint( "RtlCreateUserProcess( %Z ) failed - Status = %X\n",
                          &ImageName, Status
                        );
                }
            else {
                Status = NtResumeThread( ProcessInformation.Thread, NULL );
                Status = NtWaitForSingleObject( ProcessInformation.Process,
                                                FALSE,
                                                (PLARGE_INTEGER)NULL
                                              );
                if (!NT_SUCCESS( Status )) {
                    DbgPrint( "NtWaitForSingleObject failed - Status = %X\n",
                              Status
                            );
                    }
                }
            }
        }
    else {
        TestChild();
        }

    NtTerminateProcess( NtCurrentProcess(), Status );
}
Beispiel #22
0
/*++
 * @name CsrSbApiPortInitialize
 *
 * The CsrSbApiPortInitialize routine initializes the LPC Port used for
 * communications with the Session Manager (SM) and initializes the static
 * thread that will handle connection requests and APIs.
 *
 * @param None
 *
 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
 *
 * @remarks None.
 *
 *--*/
NTSTATUS
NTAPI
CsrSbApiPortInitialize(VOID)
{
    ULONG Size;
    PSECURITY_DESCRIPTOR PortSd;
    OBJECT_ATTRIBUTES ObjectAttributes;
    NTSTATUS Status;
    HANDLE hRequestThread;
    CLIENT_ID ClientId;

    /* Calculate how much space we'll need for the Port Name */
    Size = CsrDirectoryName.Length + sizeof(SB_PORT_NAME) + sizeof(WCHAR);

    /* Create the buffer for it */
    CsrSbApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size);
    if (!CsrSbApiPortName.Buffer) return STATUS_NO_MEMORY;

    /* Setup the rest of the empty string */
    CsrSbApiPortName.Length = 0;
    CsrSbApiPortName.MaximumLength = (USHORT)Size;

    /* Now append the full port name */
    RtlAppendUnicodeStringToString(&CsrSbApiPortName, &CsrDirectoryName);
    RtlAppendUnicodeToString(&CsrSbApiPortName, UNICODE_PATH_SEP);
    RtlAppendUnicodeToString(&CsrSbApiPortName, SB_PORT_NAME);
    if (CsrDebug & 2) DPRINT1("CSRSS: Creating %wZ port and associated thread\n", &CsrSbApiPortName);

    /* Create Security Descriptor for this Port */
    Status = CsrCreateLocalSystemSD(&PortSd);
    if (!NT_SUCCESS(Status)) return Status;

    /* Initialize the Attributes */
    InitializeObjectAttributes(&ObjectAttributes,
                               &CsrSbApiPortName,
                               0,
                               NULL,
                               PortSd);

    /* Create the Port Object */
    Status = NtCreatePort(&CsrSbApiPort,
                          &ObjectAttributes,
                          sizeof(SB_CONNECTION_INFO),
                          sizeof(SB_API_MSG),
                          32 * sizeof(SB_API_MSG));
    if (PortSd) RtlFreeHeap(CsrHeap, 0, PortSd);

    if (NT_SUCCESS(Status))
    {
        /* Create the Thread to handle the API Requests */
        Status = RtlCreateUserThread(NtCurrentProcess(),
                                     NULL,
                                     TRUE,
                                     0,
                                     0,
                                     0,
                                     (PVOID)CsrSbApiRequestThread,
                                     NULL,
                                     &hRequestThread,
                                     &ClientId);
        if (NT_SUCCESS(Status))
        {
            /* Add it as a Static Server Thread */
            CsrSbApiRequestThreadPtr = CsrAddStaticServerThread(hRequestThread,
                                                                &ClientId,
                                                                0);

            /* Activate it */
            Status = NtResumeThread(hRequestThread, NULL);
        }
    }

    return Status;
}
Beispiel #23
0
UdbgTest1()
{
    NTSTATUS st;
    HANDLE ExitThread, SpinThread, DebugProcess;
    CLIENT_ID ExitClientId, SpinClientId;
    DBGKM_APIMSG m;
    PDBGKM_CREATE_THREAD CreateThreadArgs;
    PDBGKM_CREATE_PROCESS CreateProcessArgs;
    PDBGKM_EXIT_THREAD ExitThreadArgs;
    PDBGKM_EXIT_PROCESS ExitProcessArgs;
    ULONG Psp;

    DbgPrint("UdbgTest1: (1)...\n");

        //
        // Verify that a process can be created with a debug
        // port.
        //

        st = NtCreateProcess(
                &DebugProcess,
                PROCESS_ALL_ACCESS,
                NULL,
                NtCurrentProcess(),
                FALSE,
                NULL,
                DebugPort,
                NULL
                );
        ASSERT(NT_SUCCESS(st));

        st = RtlCreateUserThread(
                DebugProcess,
                NULL,
                TRUE,
                0L,
                0L,
                0L,
                ThreadThatExits,
                (PVOID) STATUS_ABANDONED,
                &ExitThread,
                &ExitClientId
                );
        ASSERT(NT_SUCCESS(st));

        st = RtlCreateUserThread(
                DebugProcess,
                NULL,
                TRUE,
                0L,
                0L,
                0L,
                ThreadThatSpins,
                NULL,
                &SpinThread,
                &SpinClientId
                );
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest1: (2)...\n");

        //
        // Verify that CreateProcess Messages Arrive, and that
        // they are correct
        //

        st = NtResumeThread(SpinThread,NULL);
        ASSERT(NT_SUCCESS(st));

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmCreateProcessApi);

        CreateThreadArgs = &m.u.CreateProcess.InitialThread;
        CreateProcessArgs = &m.u.CreateProcess;
        ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatSpins );
        ASSERT( CreateProcessArgs->SubSystemKey == 0);

    DbgPrint("UdbgTest1: (3)...\n");

        //
        // Verify that other threads in the process are properly suspended
        //

        st = NtSuspendThread(ExitThread,&Psp);
        ASSERT(NT_SUCCESS(st) && Psp == 2);

        st = NtResumeThread(ExitThread,&Psp);
        ASSERT(NT_SUCCESS(st) && Psp == 3);

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));


    DbgPrint("UdbgTest1: (4)...\n");

        //
        // Verify that CreateThread Messages Arrive, and that
        // they are correct
        //

        st = NtResumeThread(ExitThread,&Psp);
        ASSERT(NT_SUCCESS(st));

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmCreateThreadApi);

        CreateThreadArgs = &m.u.CreateThread;
        ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatExits );

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest1: (5)...\n");

        //
        // Verify that ExitThread Messages Arrive, and that
        // they are correct
        //

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmExitThreadApi);

        ExitThreadArgs = &m.u.ExitThread;
        ASSERT( ExitThreadArgs->ExitStatus == STATUS_ABANDONED );

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));

        st = NtWaitForSingleObject(ExitThread,FALSE,NULL);
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest1: (6)...\n");

        //
        // Verify that ExitThread Messages Arrive, and that
        // they are correct
        //

        st = NtTerminateProcess(DebugProcess,STATUS_REPARSE);
        ASSERT(NT_SUCCESS(st));

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmExitThreadApi);

        ExitThreadArgs = &m.u.ExitThread;
        ASSERT( ExitThreadArgs->ExitStatus == STATUS_REPARSE );

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest1: (7)...\n");

        //
        // Verify that ExitProcess Messages Arrive, and that
        // they are correct
        //

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmExitProcessApi);

        ExitProcessArgs = &m.u.ExitProcess;
        ASSERT( ExitProcessArgs->ExitStatus == STATUS_REPARSE );

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));


        st = NtWaitForSingleObject(ExitThread,FALSE,NULL);
        ASSERT(NT_SUCCESS(st));

        st = NtWaitForSingleObject(DebugProcess,FALSE,NULL);
        ASSERT(NT_SUCCESS(st));

    NtClose(ExitThread);
    NtClose(SpinThread);
    NtClose(DebugProcess);

    DbgPrint("UdbgTest1: END OF TEST ***\n");

}
Beispiel #24
0
/***********************************************************************
 *              NtSetContextThread  (NTDLL.@)
 *              ZwSetContextThread  (NTDLL.@)
 */
NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
{
    NTSTATUS ret;
    DWORD dummy, i;
    BOOL self = FALSE;

#ifdef __i386__
    /* on i386 debug registers always require a server call */
    self = (handle == GetCurrentThread());
    if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)))
    {
        self = (ntdll_get_thread_data()->dr0 == context->Dr0 &&
                ntdll_get_thread_data()->dr1 == context->Dr1 &&
                ntdll_get_thread_data()->dr2 == context->Dr2 &&
                ntdll_get_thread_data()->dr3 == context->Dr3 &&
                ntdll_get_thread_data()->dr6 == context->Dr6 &&
                ntdll_get_thread_data()->dr7 == context->Dr7);
    }
#endif

    if (!self)
    {
        context_t server_context;

        context_to_server( &server_context, context );

        SERVER_START_REQ( set_thread_context )
        {
            req->handle  = wine_server_obj_handle( handle );
            req->suspend = 1;
            wine_server_add_data( req, &server_context, sizeof(server_context) );
            ret = wine_server_call( req );
            self = reply->self;
        }
        SERVER_END_REQ;

        if (ret == STATUS_PENDING)
        {
            for (i = 0; i < 100; i++)
            {
                SERVER_START_REQ( set_thread_context )
                {
                    req->handle  = wine_server_obj_handle( handle );
                    req->suspend = 0;
                    wine_server_add_data( req, &server_context, sizeof(server_context) );
                    ret = wine_server_call( req );
                }
                SERVER_END_REQ;
                if (ret == STATUS_PENDING)
                {
                    LARGE_INTEGER timeout;
                    timeout.QuadPart = -10000;
                    NtDelayExecution( FALSE, &timeout );
                }
                else break;
            }
            NtResumeThread( handle, &dummy );
            if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED;
        }

        if (ret) return ret;
    }
Beispiel #25
0
static void test_NtSuspendProcess(char *process_name)
{
    PROCESS_INFORMATION info;
    DEBUG_EVENT ev;
    STARTUPINFOA startup;
    NTSTATUS status;
    HANDLE event;
    char buffer[MAX_PATH];
    ULONG count;
    DWORD ret;

    status = pNtResumeProcess(GetCurrentProcess());
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);

    event = CreateEventA(NULL, TRUE, FALSE, "wine_suspend_event");
    ok(!!event, "Failed to create event: %u\n", GetLastError());

    memset(&startup, 0, sizeof(startup));
    startup.cb = sizeof(startup);

    sprintf(buffer, "%s tests/process.c dummy_process wine_suspend_event", process_name);
    ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info);
    ok(ret, "CreateProcess failed with error %u\n", GetLastError());

    ret = WaitForSingleObject(event, 500);
    ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret);

    status = pNtSuspendProcess(info.hProcess);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);

    ResetEvent(event);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    status = NtResumeThread(info.hThread, &count);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);
    ok(count == 1, "Expected count 1, got %d\n", count);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret);

    status = pNtResumeProcess(info.hProcess);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);

    status = pNtSuspendThread(info.hThread, &count);
    ok(status == STATUS_SUCCESS, "NtSuspendThread failed: %x\n", status);
    ok(count == 0, "Expected count 0, got %d\n", count);

    ResetEvent(event);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    status = pNtResumeProcess(info.hProcess);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret);

    status = pNtSuspendThread(info.hThread, &count);
    ok(status == STATUS_SUCCESS, "NtSuspendThread failed: %x\n", status);
    ok(count == 0, "Expected count 0, got %d\n", count);

    status = pNtSuspendThread(info.hThread, &count);
    ok(status == STATUS_SUCCESS, "NtSuspendThread failed: %x\n", status);
    ok(count == 1, "Expected count 1, got %d\n", count);

    ResetEvent(event);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    status = pNtResumeProcess(info.hProcess);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    status = pNtResumeProcess(info.hProcess);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret);

    ret = DebugActiveProcess(info.dwProcessId);
    ok(ret, "Failed to debug process: %d\n", GetLastError());

    ResetEvent(event);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    for (;;)
    {
        ret = WaitForDebugEvent(&ev, INFINITE);
        ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
        if (!ret) break;

        if (ev.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT) break;

        ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
        ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
        if (!ret) break;
    }

    ResetEvent(event);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    status = pNtResumeProcess(info.hProcess);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    status = NtResumeThread(info.hThread, &count);
    ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status);
    ok(count == 0, "Expected count 0, got %d\n", count);

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret);

    ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
    ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());

    ret = WaitForSingleObject(event, 200);
    ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret);

    TerminateProcess(info.hProcess, 0);

    CloseHandle(info.hProcess);
    CloseHandle(info.hThread);
}
Beispiel #26
0
NTSTATUS
NTAPI
SmpExecuteImage(IN PUNICODE_STRING FileName,
                IN PUNICODE_STRING Directory,
                IN PUNICODE_STRING CommandLine,
                IN ULONG MuSessionId,
                IN ULONG Flags,
                IN PRTL_USER_PROCESS_INFORMATION ProcessInformation)
{
    PRTL_USER_PROCESS_INFORMATION ProcessInfo;
    NTSTATUS Status;
    RTL_USER_PROCESS_INFORMATION LocalProcessInfo;
    PRTL_USER_PROCESS_PARAMETERS ProcessParameters;

    /* Use the input process information if we have it, otherwise use local */
    ProcessInfo = ProcessInformation;
    if (!ProcessInfo) ProcessInfo = &LocalProcessInfo;

    /* Create parameters for the target process */
    Status = RtlCreateProcessParameters(&ProcessParameters,
                                        FileName,
                                        SmpDefaultLibPath.Length ?
                                        &SmpDefaultLibPath : NULL,
                                        Directory,
                                        CommandLine,
                                        SmpDefaultEnvironment,
                                        NULL,
                                        NULL,
                                        NULL,
                                        0);
    if (!NT_SUCCESS(Status))
    {
        /* This is a pretty bad failure. ASSERT on checked builds and exit */
        ASSERTMSG("RtlCreateProcessParameters", NT_SUCCESS(Status));
        DPRINT1("SMSS: RtlCreateProcessParameters failed for %wZ - Status == %lx\n",
                FileName, Status);
        return Status;
    }

    /* Set the size field as required */
    ProcessInfo->Size = sizeof(RTL_USER_PROCESS_INFORMATION);

    /* Check if the debug flag was requested */
    if (Flags & SMP_DEBUG_FLAG)
    {
        /* Write it in the process parameters */
        ProcessParameters->DebugFlags = 1;
    }
    else
    {
        /* Otherwise inherit the flag that was passed to SMSS itself */
        ProcessParameters->DebugFlags = SmpDebug;
    }

    /* Subsystems get the first 1MB of memory reserved for DOS/IVT purposes */
    if (Flags & SMP_SUBSYSTEM_FLAG)
    {
        ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;
    }

    /* And always force NX for anything that SMSS launches */
    ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_NX;

    /* Now create the process */
    Status = RtlCreateUserProcess(FileName,
                                  OBJ_CASE_INSENSITIVE,
                                  ProcessParameters,
                                  NULL,
                                  NULL,
                                  NULL,
                                  FALSE,
                                  NULL,
                                  NULL,
                                  ProcessInfo);
    RtlDestroyProcessParameters(ProcessParameters);
    if (!NT_SUCCESS(Status))
    {
        /* If we couldn't create it, fail back to the caller */
        DPRINT1("SMSS: Failed load of %wZ - Status  == %lx\n",
                FileName, Status);
        return Status;
    }

    /* Associate a session with this process */
    Status = SmpSetProcessMuSessionId(ProcessInfo->ProcessHandle, MuSessionId);

    /* If the application is deferred (suspended), there's nothing to do */
    if (Flags & SMP_DEFERRED_FLAG) return Status;

    /* Otherwise, get ready to start it, but make sure it's a native app */
    if (ProcessInfo->ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_NATIVE)
    {
        /* Resume it */
        NtResumeThread(ProcessInfo->ThreadHandle, NULL);
        if (!(Flags & SMP_ASYNC_FLAG))
        {
            /* Block on it unless Async was requested */
            NtWaitForSingleObject(ProcessInfo->ThreadHandle, FALSE, NULL);
        }

        /* It's up and running now, close our handles */
        NtClose(ProcessInfo->ThreadHandle);
        NtClose(ProcessInfo->ProcessHandle);
    }
    else
    {
        /* This image is invalid, so kill it, close our handles, and fail */
        Status = STATUS_INVALID_IMAGE_FORMAT;
        NtTerminateProcess(ProcessInfo->ProcessHandle, Status);
        NtWaitForSingleObject(ProcessInfo->ThreadHandle, 0, 0);
        NtClose(ProcessInfo->ThreadHandle);
        NtClose(ProcessInfo->ProcessHandle);
        DPRINT1("SMSS: Not an NT image - %wZ\n", FileName);
    }

    /* Return the outcome of the process create */
    return Status;
}
Beispiel #27
0
NTSTATUS
Nt_CreateProcess(
    LPCWSTR                 ApplicationName,
    LPWSTR                  CommandLine,
    ULONG                   CreationFlags,
    LPCWSTR                 CurrentDirectory,
    LPSTARTUPINFO           StartupInfo,
    LPPROCESS_INFORMATION   ProcessInformation
)
{
    NTSTATUS                        Status;
    WCHAR                           FullPathBuffer[MAX_PATH *2], DllPathBuffer[0x3000];
    UNICODE_STRING                  PathVariableName, DllPath, ImagePathName;
    UNICODE_STRING                  _CommandLine, _CurrentDirectory;
    PRTL_USER_PROCESS_PARAMETERS    ProcessParameters;
    RTL_USER_PROCESS_INFORMATION    ProcessInfo;

    if (!RtlDosPathNameToNtPathName_U(ApplicationName, &ImagePathName, NULL, NULL))
        return STATUS_OBJECT_PATH_NOT_FOUND;

    RTL_CONST_STRING(PathVariableName, L"Path");
    DllPath.Length = 0;
    DllPath.MaximumLength = sizeof(DllPathBuffer);
    DllPath.Buffer = DllPathBuffer;
    RtlQueryEnvironmentVariable_U(NULL, &PathVariableName, &DllPath);

    if (CommandLine != NULL)
        RtlInitUnicodeString(&_CommandLine, CommandLine);
    if (CurrentDirectory != NULL)
        RtlInitUnicodeString(&_CurrentDirectory, CurrentDirectory);

    Status = RtlCreateProcessParameters(
                &ProcessParameters,
                &ImagePathName,
                &DllPath,
                CurrentDirectory == NULL ? NULL : &_CurrentDirectory,
                CommandLine == NULL ? NULL : &_CommandLine,
                NULL,
                NULL,
                NULL,
                NULL,
                NULL
             );

    if (!NT_SUCCESS(Status))
    {
        RtlFreeUnicodeString(&ImagePathName);
        return Status;
    }

    ProcessInfo.Size = sizeof(ProcessInfo);
    Status = RtlCreateUserProcess(
                &ImagePathName,
                OBJ_CASE_INSENSITIVE,
                ProcessParameters,
                NULL,
                NULL,
                NULL,
                FALSE,
                NULL,
                NULL,
                &ProcessInfo
             );

    RtlDestroyProcessParameters(ProcessParameters);
    RtlFreeUnicodeString(&ImagePathName);

    if (!NT_SUCCESS(Status))
        return Status;

    if (!FLAG_ON(CreationFlags, CREATE_SUSPENDED))
    {
        NtResumeThread(ProcessInfo.ThreadHandle, NULL);
    }

    if (ProcessInformation == NULL)
    {
        NtClose(ProcessInfo.ProcessHandle);
        NtClose(ProcessInfo.ThreadHandle);
        return Status;
    }

    ProcessInformation->dwProcessId = (ULONG)ProcessInfo.ClientId.UniqueProcess;
    ProcessInformation->dwThreadId  = (ULONG)ProcessInfo.ClientId.UniqueThread;
    ProcessInformation->hProcess    = ProcessInfo.ProcessHandle;
    ProcessInformation->hThread     = ProcessInfo.ThreadHandle;

    return Status;
}