Beispiel #1
0
ULONG
BaseSrvSetProcessShutdownParam(
    IN OUT PCSR_API_MSG m,
    IN OUT PCSR_REPLY_STATUS ReplyStatus
    )
{
    PCSR_PROCESS p;
    PBASE_SHUTDOWNPARAM_MSG a = (PBASE_SHUTDOWNPARAM_MSG)&m->u.ApiMessageData;

    p = CSR_SERVER_QUERYCLIENTTHREAD()->Process;

    if (a->ShutdownFlags & (~(SHUTDOWN_NORETRY))) {
        return !STATUS_SUCCESS;
        }

    p->ShutdownLevel = a->ShutdownLevel;
    p->ShutdownFlags = a->ShutdownFlags;

    return STATUS_SUCCESS;
    ReplyStatus;
}
Beispiel #2
0
NTSTATUS
AllocateConsole(
    IN HANDLE ConsoleHandle,
    IN LPWSTR Title,
    IN USHORT TitleLength,
    IN HANDLE ClientProcessHandle,
    OUT PHANDLE StdIn,
    OUT PHANDLE StdOut,
    OUT PHANDLE StdErr,
    OUT PCONSOLE_PER_PROCESS_DATA ProcessData,
    IN OUT PCONSOLE_INFO ConsoleInfo,
    IN BOOLEAN WindowVisible,
    IN DWORD dwConsoleThreadId,
    IN HDESK Desktop
)

/*++

Routine Description:

    This routine allocates and initialized a console and its associated
    data - input buffer and screen buffer.

Arguments:

    ConsoleHandle - Handle of console to allocate.

    dwWindowSize - Initial size of screen buffer window, in rows and columns.

    nFont - Initial number of font text is displayed in.

    dwScreenBufferSize - Initial size of screen buffer, in rows and columns.

    nInputBufferSize - Initial size of input buffer, in events.

    dwWindowFlags -

    StdIn - On return, contains handle to stdin.

    StdOut - On return, contains handle to stdout.

    StdErr - On return, contains handle to stderr.

    ProcessData - On return, contains the initialized per-process data.

Return Value:

Note:

    The console handle table lock must be held when calling this routine.

--*/

{
    PCONSOLE_INFORMATION Console;
    NTSTATUS Status;
    BOOL Success;

    //
    // allocate console data
    //

    Console = (PCONSOLE_INFORMATION)HeapAlloc(pConHeap, MAKE_TAG( CONSOLE_TAG ) | HEAP_ZERO_MEMORY,
              sizeof(CONSOLE_INFORMATION));
    if (Console == NULL) {
        return STATUS_NO_MEMORY;
    }
    ConsoleHandles[IndexFromHandle(ConsoleHandle)] = Console;

    Console->Flags = WindowVisible ? 0 : CONSOLE_NO_WINDOW;
    Console->hIcon = ConsoleInfo->hIcon;
    Console->iIconId = ConsoleInfo->iIconId;
    Console->dwHotKey = ConsoleInfo->dwHotKey;
    Console->CP = OEMCP;
    Console->OutputCP = ConsoleOutputCP;
    Console->ReserveKeys = CONSOLE_NOSHORTCUTKEY;
    Console->ConsoleHandle = ConsoleHandle;
    Console->bIconInit = TRUE;
    Console->VerticalClientToWindow = VerticalClientToWindow;
    Console->HorizontalClientToWindow = HorizontalClientToWindow;

    //
    // must wait for window to be destroyed or client impersonation won't
    // work.
    //

    Status = NtDuplicateObject(NtCurrentProcess(),
                               CONSOLE_CLIENTTHREADHANDLE(CSR_SERVER_QUERYCLIENTTHREAD()),
                               NtCurrentProcess(),
                               &Console->ClientThreadHandle,
                               0,
                               FALSE,
                               DUPLICATE_SAME_ACCESS
                              );
    if (!NT_SUCCESS(Status)) {
        goto ErrorExit5;
    }

#if DBG
    //
    // Make sure the handle isn't protected so we can close it later
    //
    UnProtectHandle(Console->ClientThreadHandle);
#endif // DBG

    InitializeListHead(&Console->OutputQueue);
    InitializeListHead(&Console->ProcessHandleList);
    InitializeListHead(&Console->ExeAliasList);

    Status = NtCreateEvent(&Console->InitEvents[INITIALIZATION_SUCCEEDED],
                           EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE);
    if (!NT_SUCCESS(Status)) {
        goto ErrorExit4a;
    }
    Status = NtCreateEvent(&Console->InitEvents[INITIALIZATION_FAILED],
                           EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE);
    if (!NT_SUCCESS(Status)) {
        goto ErrorExit4;
    }
    Status = RtlInitializeCriticalSection(&Console->ConsoleLock);
    if (!NT_SUCCESS(Status)) {
        goto ErrorExit3a;
    }
    InitializeConsoleCommandData(Console);

    //
    // initialize input buffer
    //

    Status = CreateInputBuffer(ConsoleInfo->nInputBufferSize,
                               &Console->InputBuffer);
    if (!NT_SUCCESS(Status)) {
        goto ErrorExit3;
    }

    Console->Title = (PWCHAR)HeapAlloc(pConHeap,MAKE_TAG( TITLE_TAG ),TitleLength+sizeof(WCHAR));
    if (Console->Title == NULL) {
        Status = STATUS_NO_MEMORY;
        goto ErrorExit2;
    }
    RtlCopyMemory(Console->Title,Title,TitleLength);
    Console->Title[TitleLength/sizeof(WCHAR)] = (WCHAR)0;   // NULL terminate
    Console->TitleLength = TitleLength;

    Console->OriginalTitle = (PWCHAR)HeapAlloc(pConHeap,MAKE_TAG( TITLE_TAG ),TitleLength+sizeof(WCHAR));
    if (Console->OriginalTitle == NULL) {
        Status = STATUS_NO_MEMORY;
        goto ErrorExit1;
    }
    RtlCopyMemory(Console->OriginalTitle,Title,TitleLength);
    Console->OriginalTitle[TitleLength/sizeof(WCHAR)] = (WCHAR)0;   // NULL terminate
    Console->OriginalTitleLength = TitleLength;

    Status = NtCreateEvent(&Console->TerminationEvent,
                           EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE);
    if (!NT_SUCCESS(Status)) {
        goto ErrorExit1a;
    }

    //
    // initialize screen buffer. we don't call OpenConsole to do this
    // because we need to specify the font, windowsize, etc.
    //

    Status = DoCreateScreenBuffer(Console,
                                  ConsoleInfo,
                                  Console->Title);
    if (!NT_SUCCESS(Status)) {
        goto ErrorExit1b;
    }


    Console->CurrentScreenBuffer = Console->ScreenBuffers;
    Status = InitializeIoHandleTable(Console,
                                     ProcessData,
                                     StdIn,
                                     StdOut,
                                     StdErr
                                    );
    if (!NT_SUCCESS(Status)) {
        goto ErrorExit0;
    }

    //
    // map event handles
    //

    if (!MapHandle(ClientProcessHandle,
                   Console->InitEvents[INITIALIZATION_SUCCEEDED],
                   &ConsoleInfo->InitEvents[INITIALIZATION_SUCCEEDED]
                  )) {
        Status = STATUS_NO_MEMORY;
        goto ErrorExit0;
    }
    if (!MapHandle(ClientProcessHandle,
                   Console->InitEvents[INITIALIZATION_FAILED],
                   &ConsoleInfo->InitEvents[INITIALIZATION_FAILED]
                  )) {
        Status = STATUS_NO_MEMORY;
        goto ErrorExit0;
    }
    if (!MapHandle(ClientProcessHandle,
                   Console->InputBuffer.InputWaitEvent,
                   &ConsoleInfo->InputWaitHandle
                  )) {
        Status = STATUS_NO_MEMORY;
        goto ErrorExit0;
    }

    Success = PostThreadMessage(dwConsoleThreadId,
                                CM_CREATE_CONSOLE_WINDOW,
                                (DWORD)Console,
                                (LONG)ClientProcessHandle
                               );
    if (!Success) {
        KdPrint(("CONSRV: PostThreadMessage failed %d\n",GetLastError()));
        Status = STATUS_UNSUCCESSFUL;
        goto ErrorExit0;
    }

    return STATUS_SUCCESS;

ErrorExit0:
    Console->ScreenBuffers->RefCount = 0;
    FreeScreenBuffer(Console->ScreenBuffers);
ErrorExit1b:
    NtClose(Console->TerminationEvent);
ErrorExit1a:
    HeapFree(pConHeap,0,Console->OriginalTitle);
ErrorExit1:
    HeapFree(pConHeap,0,Console->Title);
ErrorExit2:
    Console->InputBuffer.RefCount = 0;
    FreeInputBuffer(&Console->InputBuffer);
ErrorExit3:
    RtlDeleteCriticalSection(&Console->ConsoleLock);

ErrorExit3a:
    NtClose(Console->InitEvents[INITIALIZATION_FAILED]);
ErrorExit4:
    NtClose(Console->InitEvents[INITIALIZATION_SUCCEEDED]);
ErrorExit4a:
    NtClose(Console->ClientThreadHandle);
ErrorExit5:
    HeapFree(pConHeap,0,Console);
    return Status;
}
Beispiel #3
0
ULONG
BaseSrvCreateProcess(
    IN OUT PCSR_API_MSG m,
    IN OUT PCSR_REPLY_STATUS ReplyStatus
    )
{
    NTSTATUS Status;
    PBASE_CREATEPROCESS_MSG a = (PBASE_CREATEPROCESS_MSG)&m->u.ApiMessageData;
    HANDLE Process, Thread;
    PCSR_THREAD t;
    ULONG DebugFlags;
    PCLIENT_ID DebugUserInterface;
    DWORD dwFlags;
    PCSR_PROCESS ProcessVDM;

    t = CSR_SERVER_QUERYCLIENTTHREAD();

    //
    // Get handles to the process and thread local to the
    // Windows server.
    //

    if (dwFlags = ((DWORD)a->ProcessHandle) & 3) {
        a->ProcessHandle = (HANDLE)((DWORD)a->ProcessHandle & ~3);
        }

    Status = NtDuplicateObject(
                t->Process->ProcessHandle,
                a->ProcessHandle,
                NtCurrentProcess(),
                &Process,
                0L,
                0L,
                DUPLICATE_SAME_ACCESS
                );
    if ( !NT_SUCCESS(Status) ) {
        return( (ULONG)Status );
        }

    Status = NtDuplicateObject(
                t->Process->ProcessHandle,
                a->ThreadHandle,
                NtCurrentProcess(),
                &Thread,
                0L,
                0L,
                DUPLICATE_SAME_ACCESS
                );
    if ( !NT_SUCCESS(Status) ) {
        //
        // FIX, FIX - error cleanup
        //
        NtClose(Process);
        return( (ULONG)Status );
        }

    DebugUserInterface = NULL;
    DebugFlags = 0;

    if ( a->CreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS) ) {
        if ( a->CreationFlags & DEBUG_PROCESS ) {
            DebugFlags |= CSR_DEBUG_PROCESS_TREE;
            }
        if ( a->CreationFlags & DEBUG_ONLY_THIS_PROCESS ) {
            DebugFlags |= CSR_DEBUG_THIS_PROCESS;
            }
        DebugUserInterface = &a->DebuggerClientId;
        }

    if ( a->CreationFlags & CREATE_NEW_PROCESS_GROUP ) {
        DebugFlags |= CSR_CREATE_PROCESS_GROUP;
        }

    if ( a->CreationFlags & NORMAL_PRIORITY_CLASS ) {
        DebugFlags |= CSR_NORMAL_PRIORITY_CLASS;
        }
    else if ( a->CreationFlags & IDLE_PRIORITY_CLASS ) {
        DebugFlags |= CSR_IDLE_PRIORITY_CLASS;
        }
    else if ( a->CreationFlags & HIGH_PRIORITY_CLASS ) {
        DebugFlags |= CSR_HIGH_PRIORITY_CLASS;
        }
    else if ( a->CreationFlags & REALTIME_PRIORITY_CLASS ) {
        DebugFlags |= CSR_REALTIME_PRIORITY_CLASS;
        }
    else {

        //
        // No class specified. If current process is idle class, then
        // new process is idle. Otherwise, new process is normal.
        //

        if ( CsrComputePriorityClass(t->Process) == CSR_IDLE_PRIORITY_CLASS ) {
            DebugFlags |= CSR_IDLE_PRIORITY_CLASS;
            }
        else {
            DebugFlags |= CSR_NORMAL_PRIORITY_CLASS;
            }
        }

    if ( !(dwFlags & 2) ) {
        DebugFlags |= CSR_PROCESS_CONSOLEAPP;
        }

    Status = CsrCreateProcess(
                Process,
                Thread,
                &a->ClientId,
                t->Process->NtSession,
                DebugFlags,
                DebugUserInterface
                );

    switch(Status) {
    case STATUS_THREAD_IS_TERMINATING:
        if (a->IsVDM && !(a->CreationFlags & CREATE_SEPARATE_WOW_VDM))
            BaseSrvVDMTerminated (a->hVDM, a->IsVDM);
        *ReplyStatus = CsrClientDied;
        break;

    case STATUS_SUCCESS:
        //
        // notify USER that a process is being created. USER needs to know
        // for various synchronization issues such as startup activation,
        // startup synchronization, and type ahead.
        //
        // Turn on 0x8 bit of dwFlags if this is a WOW process being
        // created so that UserSrv knows to ignore the console's call
        // to UserNotifyConsoleApplication.
        //

        if (a->IsVDM && a->hVDM == (HANDLE)-1)
            dwFlags |= 8;

        if (UserNotifyProcessCreate != NULL) {
            if (!(*UserNotifyProcessCreate)((DWORD)a->ClientId.UniqueProcess,
                    (DWORD)t->ClientId.UniqueThread,
                    0, dwFlags)) {
                //
                // FIX, FIX - error cleanup. Shouldn't we close the duplicated
                // process and thread handles above?
                //
                }
	    }

        //
        // Update the VDM sequence number.  Note BaseSrv doesn't keep track
        // of separate WOW VDMs.
        //

        if (a->IsVDM && !(a->CreationFlags & CREATE_SEPARATE_WOW_VDM)){
	    Status = CsrLockProcessByClientId( a->ClientId.UniqueProcess,
					   &ProcessVDM
                                         );
	    if (!NT_SUCCESS( Status )) {
		    //
		    // FIX, FIX - error cleanup. Shouldn't we close the
		    // duplicated process and thread handles above?
		    //
                        BaseSrvVDMTerminated (a->hVDM, a->IsVDM);
			break;
		}
		ProcessVDM->fVDM = TRUE;
		BaseSrvUpdateVDMSequenceNumber (a->hVDM,
                                                ProcessVDM->SequenceNumber,
                                                a->IsVDM
					       );
		CsrUnlockProcess(ProcessVDM);
	    }
	break;
	}
    return( (ULONG)Status );
}
Beispiel #4
0
BOOL _EndTask(
    HWND hwnd,
    BOOL fShutdown,
    BOOL fMeanKill)
{
    PCSR_THREAD pcsrt = CSR_SERVER_QUERYCLIENTTHREAD();
    PCSR_THREAD pcsrtKill;
    DWORD dwThreadId;
    DWORD dwProcessId;
    LPWSTR lpszMsg;
    BOOL fAllocated;
    DWORD dwCmd;

    /*
     * Note: fShutdown isn't used for anything in this routine!
     * They are still there because I haven't removed them: the old endtask
     * code relied on them.
     */
    UNREFERENCED_PARAMETER(fShutdown);

    /*
     * Get the process and thread that owns hwnd.
     */
    dwThreadId = GetWindowThreadProcessId(hwnd, &dwProcessId);
    if (dwThreadId == 0)
        return TRUE;

    /*
     * If this is a console window, then just send the close message to
     * it, and let console clean up the processes in it.
     */
    if ((HANDLE)GetWindowLong(hwnd, GWL_HINSTANCE) == hModuleWin) {
        PostMessage(hwnd, WM_CLOSE, 0, 0);
        return TRUE;
    }

    /*
     * Find the CSR_THREAD for the window.
     */
    LeaveCrit();
    CsrLockThreadByClientId((HANDLE)dwThreadId, &pcsrtKill);
    EnterCrit();
    if (pcsrtKill == NULL)
        return TRUE;
    CsrReferenceThread(pcsrtKill);
    CsrUnlockThread(pcsrtKill);

    /*
     * If this is a WOW app, then shutdown just this wow application.
     */
    if (!fMeanKill) {
        /*
         * Find out what to do now - did the user cancel or the app cancel,
         * etc? Only allow cancelling if we are not forcing the app to
         * exit.
         */
        dwCmd = MySendEndSessionMessages(hwnd, pcsrtKill, TRUE, 0);
        switch (dwCmd) {
        case CMDEND_APPSAYSNOTOK:
            /*
             * App says not ok - this'll let taskman bring up the "are you sure?"
             * dialog to the user.
             */
            CsrDereferenceThread(pcsrtKill);
            return FALSE;

        case CMDEND_USERSAYSCANCEL:
            /*
             * User hit cancel on the timeout dialog - so the user really meant
             * it. Let taskman know everything is ok by returning TRUE.
             */
            CsrDereferenceThread(pcsrtKill);
            return TRUE;
        }
    }

    /*
     * Kill the application now.  If the thread has not been destroyed,
     * nuke the task.  If WowExitTask returns that the thread is not
     * a WOW task, terminate the process.
     */
    if (!(pcsrtKill->Flags & CSR_THREAD_DESTROYED) && !WowExitTask(pcsrtKill)) {

        /*
         * Calling ExitProcess() in the app's context will not always work
         * because the app may have .dll termination deadlocks: so the thread
         * will hang with the rest of the process. To ensure apps go away,
         * we terminate the process with NtTerminateProcess().
         *
         * Pass this special value, DBG_TERMINATE_PROCESS, which tells
         * NtTerminateProcess() to return failure if it can't terminate the
         * process because the app is being debugged.
         */
        if (!NT_SUCCESS(NtTerminateProcess(pcsrtKill->Process->ProcessHandle,
                DBG_TERMINATE_PROCESS))) {
            /*
             * If the app is being debugged, don't close it - because that can
             * cause a hang to the NtTerminateProcess() call.
             */
            lpszMsg = ServerLoadString(hModuleWin, STR_APPDEBUGGED,
                    NULL, &fAllocated);
            if (lpszMsg) {
                if (NT_SUCCESS(NtUserSetInformationThread(NtCurrentThread(),
                        UserThreadUseDesktop, &pcsrt->ThreadHandle, sizeof(HANDLE)))) {
                    HANDLE hNull = NULL;

                    LeaveCrit();
                    MessageBoxEx(NULL, lpszMsg, NULL,
                                    MB_OK | MB_SETFOREGROUND, 0);
                    EnterCrit();
                    NtUserSetInformationThread(NtCurrentThread(), UserThreadUseDesktop,
                            &hNull, sizeof(HANDLE));
                }
                LocalFree(lpszMsg);
            }
        } else {
            pcsrtKill->Process->Flags |= CSR_PROCESS_TERMINATED;
        }
    }
    CsrDereferenceThread(pcsrtKill);

    return TRUE;
}