Example #1
0
VOID PhShowHandleObjectProperties1(
    _In_ HWND hWnd,
    _In_ PPH_HANDLE_ITEM_INFO Info
    )
{
    if (PhIsNullOrEmptyString(Info->TypeName))
        return;

    if (PhEqualString2(Info->TypeName, L"File", TRUE) || PhEqualString2(Info->TypeName, L"DLL", TRUE) ||
        PhEqualString2(Info->TypeName, L"Mapped file", TRUE) || PhEqualString2(Info->TypeName, L"Mapped image", TRUE))
    {
        if (Info->BestObjectName)
        {
            PhShellExecuteUserString(
                PhMainWndHandle,
                L"FileBrowseExecutable",
                Info->BestObjectName->Buffer,
                FALSE,
                L"Make sure the Explorer executable file is present."
                );
        }
        else
            PhShowError(hWnd, L"Unable to open file location because the object is unnamed.");
    }
    else if (PhEqualString2(Info->TypeName, L"Key", TRUE))
    {
        if (Info->BestObjectName)
            PhShellOpenKey2(hWnd, Info->BestObjectName);
        else
            PhShowError(hWnd, L"Unable to open key because the object is unnamed.");
    }
    else if (PhEqualString2(Info->TypeName, L"Process", TRUE))
    {
        HANDLE processHandle;
        HANDLE processId;
        PPH_PROCESS_ITEM targetProcessItem;

        processId = NULL;

        if (KphIsConnected())
        {
            if (NT_SUCCESS(PhOpenProcess(
                &processHandle,
                PROCESS_QUERY_LIMITED_INFORMATION,
                Info->ProcessId
                )))
            {
                PROCESS_BASIC_INFORMATION basicInfo;

                if (NT_SUCCESS(KphQueryInformationObject(
                    processHandle,
                    Info->Handle,
                    KphObjectProcessBasicInformation,
                    &basicInfo,
                    sizeof(PROCESS_BASIC_INFORMATION),
                    NULL
                    )))
                {
                    processId = basicInfo.UniqueProcessId;
                }

                NtClose(processHandle);
            }
        }
        else
        {
            HANDLE handle;
            PROCESS_BASIC_INFORMATION basicInfo;

            if (NT_SUCCESS(PhpDuplicateHandleFromProcessItem(
                &handle,
                PROCESS_QUERY_LIMITED_INFORMATION,
                Info->ProcessId,
                Info->Handle
                )))
            {
                if (NT_SUCCESS(PhGetProcessBasicInformation(handle, &basicInfo)))
                    processId = basicInfo.UniqueProcessId;

                NtClose(handle);
            }
        }

        if (processId)
        {
            targetProcessItem = PhReferenceProcessItem(processId);

            if (targetProcessItem)
            {
                ProcessHacker_ShowProcessProperties(PhMainWndHandle, targetProcessItem);
                PhDereferenceObject(targetProcessItem);
            }
            else
            {
                PhShowError(hWnd, L"The process does not exist.");
            }
        }
    }
    else if (PhEqualString2(Info->TypeName, L"Section", TRUE))
    {
        NTSTATUS status;
        HANDLE handle = NULL;
        BOOLEAN readOnly = FALSE;

        if (!NT_SUCCESS(status = PhpDuplicateHandleFromProcessItem(
            &handle,
            SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE,
            Info->ProcessId,
            Info->Handle
            )))
        {
            status = PhpDuplicateHandleFromProcessItem(
                &handle,
                SECTION_QUERY | SECTION_MAP_READ,
                Info->ProcessId,
                Info->Handle
                );
            readOnly = TRUE;
        }

        if (handle)
        {
            PPH_STRING sectionName = NULL;
            SECTION_BASIC_INFORMATION basicInfo;
            SIZE_T viewSize = PH_MAX_SECTION_EDIT_SIZE;
            PVOID viewBase = NULL;
            BOOLEAN tooBig = FALSE;

            PhGetHandleInformation(NtCurrentProcess(), handle, ULONG_MAX, NULL, NULL, NULL, &sectionName);

            if (NT_SUCCESS(status = PhGetSectionBasicInformation(handle, &basicInfo)))
            {
                if (basicInfo.MaximumSize.QuadPart <= PH_MAX_SECTION_EDIT_SIZE)
                    viewSize = (SIZE_T)basicInfo.MaximumSize.QuadPart;
                else
                    tooBig = TRUE;

                status = NtMapViewOfSection(
                    handle,
                    NtCurrentProcess(),
                    &viewBase,
                    0,
                    0,
                    NULL,
                    &viewSize,
                    ViewShare,
                    0,
                    readOnly ? PAGE_READONLY : PAGE_READWRITE
                    );

                if (status == STATUS_SECTION_PROTECTION && !readOnly)
                {
                    status = NtMapViewOfSection(
                        handle,
                        NtCurrentProcess(),
                        &viewBase,
                        0,
                        0,
                        NULL,
                        &viewSize,
                        ViewShare,
                        0,
                        PAGE_READONLY
                        );
                }

                if (NT_SUCCESS(status))
                {
                    PPH_SHOW_MEMORY_EDITOR showMemoryEditor = PhAllocate(sizeof(PH_SHOW_MEMORY_EDITOR));

                    if (tooBig)
                        PhShowWarning(hWnd, L"The section size is greater than 32 MB. Only the first 32 MB will be available for editing.");

                    memset(showMemoryEditor, 0, sizeof(PH_SHOW_MEMORY_EDITOR));
                    showMemoryEditor->ProcessId = NtCurrentProcessId();
                    showMemoryEditor->BaseAddress = viewBase;
                    showMemoryEditor->RegionSize = viewSize;
                    showMemoryEditor->SelectOffset = ULONG_MAX;
                    showMemoryEditor->SelectLength = 0;
                    showMemoryEditor->Title = sectionName ? PhConcatStrings2(L"Section - ", sectionName->Buffer) : PhCreateString(L"Section");
                    showMemoryEditor->Flags = PH_MEMORY_EDITOR_UNMAP_VIEW_OF_SECTION;
                    ProcessHacker_ShowMemoryEditor(PhMainWndHandle, showMemoryEditor);
                }
                else
                {
                    PhShowStatus(hWnd, L"Unable to map a view of the section.", status, 0);
                }
            }

            PhClearReference(&sectionName);

            NtClose(handle);
        }

        if (!NT_SUCCESS(status))
        {
            PhShowStatus(hWnd, L"Unable to query the section.", status, 0);
        }
    }
    else if (PhEqualString2(Info->TypeName, L"Thread", TRUE))
    {
        HANDLE processHandle;
        CLIENT_ID clientId;
        PPH_PROCESS_ITEM targetProcessItem;
        PPH_PROCESS_PROPCONTEXT propContext;

        clientId.UniqueProcess = NULL;
        clientId.UniqueThread = NULL;

        if (KphIsConnected())
        {
            if (NT_SUCCESS(PhOpenProcess(
                &processHandle,
                PROCESS_QUERY_LIMITED_INFORMATION,
                Info->ProcessId
                )))
            {
                THREAD_BASIC_INFORMATION basicInfo;

                if (NT_SUCCESS(KphQueryInformationObject(
                    processHandle,
                    Info->Handle,
                    KphObjectThreadBasicInformation,
                    &basicInfo,
                    sizeof(THREAD_BASIC_INFORMATION),
                    NULL
                    )))
                {
                    clientId = basicInfo.ClientId;
                }

                NtClose(processHandle);
            }
        }
        else
        {
            HANDLE handle;
            THREAD_BASIC_INFORMATION basicInfo;

            if (NT_SUCCESS(PhpDuplicateHandleFromProcessItem(
                &handle,
                THREAD_QUERY_LIMITED_INFORMATION,
                Info->ProcessId,
                Info->Handle
                )))
            {
                if (NT_SUCCESS(PhGetThreadBasicInformation(handle, &basicInfo)))
                    clientId = basicInfo.ClientId;

                NtClose(handle);
            }
        }

        if (clientId.UniqueProcess)
        {
            targetProcessItem = PhReferenceProcessItem(clientId.UniqueProcess);

            if (targetProcessItem)
            {
                propContext = PhCreateProcessPropContext(NULL, targetProcessItem);
                PhDereferenceObject(targetProcessItem);
                PhSetSelectThreadIdProcessPropContext(propContext, clientId.UniqueThread);
                ProcessHacker_Invoke(PhMainWndHandle, PhpShowProcessPropContext, propContext);
            }
            else
            {
                PhShowError(hWnd, L"The process does not exist.");
            }
        }
    }
}
void
Test_PageFileSection(void)
{
    NTSTATUS Status;
    HANDLE SectionHandle;
    LARGE_INTEGER MaximumSize, SectionOffset;
    PVOID BaseAddress;
    SIZE_T ViewSize;

    /* Create a page file backed section */
    MaximumSize.QuadPart = 0x20000;
    Status = NtCreateSection(&SectionHandle,
                             SECTION_ALL_ACCESS,
                             NULL,
                             &MaximumSize,
                             PAGE_READWRITE,
                             SEC_COMMIT,
                             NULL);
    ok(NT_SUCCESS(Status), "NtCreateSection failed with Status %lx\n", Status);
    if (!NT_SUCCESS(Status))
        return;

    /* Try to map a page at an address that is not 64k aligned */
    BaseAddress = (PVOID)0x30001000;
    SectionOffset.QuadPart = 0;
    ViewSize = 0x1000;
    Status = NtMapViewOfSection(SectionHandle,
                                NtCurrentProcess(),
                                &BaseAddress,
                                0,
                                0,
                                &SectionOffset,
                                &ViewSize,
                                ViewShare,
                                0,
                                PAGE_READWRITE);
    ok(Status == STATUS_MAPPED_ALIGNMENT,
       "NtMapViewOfSection returned wrong Status %lx\n", Status);

    /* Try to map a page with execute rights */
    BaseAddress = (PVOID)0x30000000;
    SectionOffset.QuadPart = 0;
    ViewSize = 0x1000;
    Status = NtMapViewOfSection(SectionHandle,
                                NtCurrentProcess(),
                                &BaseAddress,
                                0,
                                0,
                                &SectionOffset,
                                &ViewSize,
                                ViewShare,
                                0,
                                PAGE_EXECUTE_READWRITE);
    ok(Status == STATUS_SECTION_PROTECTION,
       "NtMapViewOfSection returned wrong Status %lx\n", Status);

    /* Map 2 pages, not comitting them */
    BaseAddress = (PVOID)0x30000000;
    SectionOffset.QuadPart = 0;
    ViewSize = 0x2000;
    Status = NtMapViewOfSection(SectionHandle,
                                NtCurrentProcess(),
                                &BaseAddress,
                                0,
                                0,
                                &SectionOffset,
                                &ViewSize,
                                ViewShare,
                                0,
                                PAGE_READWRITE);
    ok(NT_SUCCESS(Status), "NtMapViewOfSection failed with Status %lx\n", Status);
    if (!NT_SUCCESS(Status))
        return;

    /* Commit a page in the section */
    BaseAddress = (PVOID)0x30000000;
    ViewSize = 0x1000;
    Status = NtAllocateVirtualMemory(NtCurrentProcess(),
                                     &BaseAddress,
                                     0,
                                     &ViewSize,
                                     MEM_COMMIT,
                                     PAGE_READWRITE);
    ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status);
    Status = NtFreeVirtualMemory(NtCurrentProcess(),
                                 &BaseAddress,
                                 &ViewSize,
                                 MEM_DECOMMIT);
    ok(Status == STATUS_UNABLE_TO_DELETE_SECTION, "NtFreeVirtualMemory returned wrong Status %lx\n", Status);
    /* Try to commit a range larger than the section */
    BaseAddress = (PVOID)0x30000000;
    ViewSize = 0x3000;
    Status = NtAllocateVirtualMemory(NtCurrentProcess(),
                                     &BaseAddress,
                                     0,
                                     &ViewSize,
                                     MEM_COMMIT,
                                     PAGE_READWRITE);
    ok(Status == STATUS_CONFLICTING_ADDRESSES,
       "NtAllocateVirtualMemory failed with wrong Status %lx\n", Status);

    /* Try to commit a page after the section */
    BaseAddress = (PVOID)0x30002000;
    ViewSize = 0x1000;
    Status = NtAllocateVirtualMemory(NtCurrentProcess(),
                                     &BaseAddress,
                                     0,
                                     &ViewSize,
                                     MEM_COMMIT,
                                     PAGE_READWRITE);
    ok(!NT_SUCCESS(Status), "NtAllocateVirtualMemory Should fail\n");

    /* Try to allocate a page after the section */
    BaseAddress = (PVOID)0x30002000;
    ViewSize = 0x1000;
    Status = NtAllocateVirtualMemory(NtCurrentProcess(),
                                     &BaseAddress,
                                     0,
                                     &ViewSize,
                                     MEM_RESERVE | MEM_COMMIT,
                                     PAGE_READWRITE);
    ok(!NT_SUCCESS(Status), "NtAllocateVirtualMemory should fail\n");

    /* Need to go to next 64k boundary */
    BaseAddress = (PVOID)0x30010000;
    ViewSize = 0x1000;
    Status = NtAllocateVirtualMemory(NtCurrentProcess(),
                                     &BaseAddress,
                                     0,
                                     &ViewSize,
                                     MEM_RESERVE | MEM_COMMIT,
                                     PAGE_READWRITE);
    ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status);
    if (!NT_SUCCESS(Status))
        return;

    /* Free the allocation */
    BaseAddress = (PVOID)0x30010000;
    ViewSize = 0x1000;
    Status = NtFreeVirtualMemory(NtCurrentProcess(),
                                 &BaseAddress,
                                 &ViewSize,
                                 MEM_RELEASE);
    ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed with Status %lx\n", Status);

    /* Free the section mapping */
    BaseAddress = (PVOID)0x30000000;
    ViewSize = 0x1000;
    Status = NtFreeVirtualMemory(NtCurrentProcess(),
                                 &BaseAddress,
                                 &ViewSize,
                                 MEM_RELEASE);
    ok(Status == STATUS_UNABLE_TO_DELETE_SECTION,
       "NtFreeVirtualMemory failed with wrong Status %lx\n", Status);

    /* Commit a page in the section */
    BaseAddress = (PVOID)0x30001000;
    ViewSize = 0x1000;
    Status = NtAllocateVirtualMemory(NtCurrentProcess(),
                                     &BaseAddress,
                                     0,
                                     &ViewSize,
                                     MEM_COMMIT,
                                     PAGE_READWRITE);
    ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status);

    /* Try to decommit the page */
    BaseAddress = (PVOID)0x30001000;
    ViewSize = 0x1000;
    Status = NtFreeVirtualMemory(NtCurrentProcess(),
                                 &BaseAddress,
                                 &ViewSize,
                                 MEM_DECOMMIT);
    ok(Status == STATUS_UNABLE_TO_DELETE_SECTION,
       "NtFreeVirtualMemory failed with wrong Status %lx\n", Status);

    BaseAddress = UlongToPtr(0x40000000);
    SectionOffset.QuadPart = 0;
    ViewSize = 0x1000;
    Status = NtMapViewOfSection(SectionHandle,
                                NtCurrentProcess(),
                                &BaseAddress,
                                0,
                                0,
                                &SectionOffset,
                                &ViewSize,
                                ViewShare,
                                0,
                                PAGE_READWRITE);
    ok(NT_SUCCESS(Status), "NtMapViewOfSection failed with Status %lx\n", Status);
    if (!NT_SUCCESS(Status))
        return;

    ok(BaseAddress == UlongToPtr(0x40000000), "Invalid BaseAddress: %p", BaseAddress);

    BaseAddress = (PVOID)0x40080000;
    SectionOffset.QuadPart = 0x10000;
    ViewSize = 0x1000;
    Status = NtMapViewOfSection(SectionHandle,
                                NtCurrentProcess(),
                                &BaseAddress,
                                0,
                                0,
                                &SectionOffset,
                                &ViewSize,
                                ViewShare,
                                0,
                                PAGE_READWRITE);
    ok(NT_SUCCESS(Status), "NtMapViewOfSection failed with Status %lx\n", Status);
    if (!NT_SUCCESS(Status))
        return;

    ok(BaseAddress == (PVOID)0x40080000, "Invalid BaseAddress: %p", BaseAddress);

    /* Commit a page in the section */
    BaseAddress = (PVOID)0x40000000;
    Status = NtAllocateVirtualMemory(NtCurrentProcess(),
                                     &BaseAddress,
                                     0,
                                     &ViewSize,
                                     MEM_COMMIT,
                                     PAGE_READWRITE);
    ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed with Status %lx\n", Status);
    if (!NT_SUCCESS(Status))
        return;

}
Example #3
0
NTSTATUS
RtlpCreateStack(
    IN HANDLE Process,
    IN SIZE_T MaximumStackSize OPTIONAL,
    IN SIZE_T CommittedStackSize OPTIONAL,
    IN ULONG ZeroBits OPTIONAL,
    OUT PINITIAL_TEB InitialTeb
    )
{
    NTSTATUS Status;
    PCH Stack;
    SYSTEM_BASIC_INFORMATION SysInfo;
    BOOLEAN GuardPage;
    SIZE_T RegionSize;
    ULONG OldProtect;

    Status = ZwQuerySystemInformation( SystemBasicInformation,
                                       (PVOID)&SysInfo,
                                       sizeof( SysInfo ),
                                       NULL
                                     );
    if ( !NT_SUCCESS( Status ) ) {
        return( Status );
        }

    //
    // if stack is in the current process, then default to
    // the parameters from the image
    //

    if ( Process == NtCurrentProcess() ) {
        PPEB Peb;
        PIMAGE_NT_HEADERS NtHeaders;


        Peb = NtCurrentPeb();
        NtHeaders = RtlImageNtHeader(Peb->ImageBaseAddress);

        if (!NtHeaders) {
            return STATUS_INVALID_IMAGE_FORMAT;
        }


        if (!MaximumStackSize) {
            MaximumStackSize = NtHeaders->OptionalHeader.SizeOfStackReserve;
            }

        if (!CommittedStackSize) {
            CommittedStackSize = NtHeaders->OptionalHeader.SizeOfStackCommit;
            }

        }
    else {

        if (!CommittedStackSize) {
            CommittedStackSize = SysInfo.PageSize;
            }

        if (!MaximumStackSize) {
            MaximumStackSize = SysInfo.AllocationGranularity;
            }

        }

    //
    // Enforce a minimal stack commit if there is a PEB setting
    // for this.
    //

    if ( CommittedStackSize >= MaximumStackSize ) {
        MaximumStackSize = ROUND_UP(CommittedStackSize, (1024*1024));
        }


    CommittedStackSize = ROUND_UP( CommittedStackSize, SysInfo.PageSize );
    MaximumStackSize = ROUND_UP( MaximumStackSize,
                                 SysInfo.AllocationGranularity
                               );

    Stack = NULL;


    Status = ZwAllocateVirtualMemory( Process,
                                      (PVOID *)&Stack,
                                      ZeroBits,
                                      &MaximumStackSize,
                                      MEM_RESERVE,
                                      PAGE_READWRITE
                                    );

    if ( !NT_SUCCESS( Status ) ) {
#if DBG
        DbgPrint( "NTRTL: RtlpCreateStack( %lx ) failed.  Stack Reservation Status == %X\n",
                  Process,
                  Status
                );
#endif // DBG
        return( Status );
        }

    InitialTeb->OldInitialTeb.OldStackBase = NULL;
    InitialTeb->OldInitialTeb.OldStackLimit = NULL;
    InitialTeb->StackAllocationBase = Stack;
    InitialTeb->StackBase = Stack + MaximumStackSize;

    Stack += MaximumStackSize - CommittedStackSize;
    if (MaximumStackSize > CommittedStackSize) {
        Stack -= SysInfo.PageSize;
        CommittedStackSize += SysInfo.PageSize;
        GuardPage = TRUE;
        }
    else {
        GuardPage = FALSE;
        }
    Status = ZwAllocateVirtualMemory( Process,
                                      (PVOID *)&Stack,
                                      0,
                                      &CommittedStackSize,
                                      MEM_COMMIT,
                                      PAGE_READWRITE
                                    );
    InitialTeb->StackLimit = Stack;

    if ( !NT_SUCCESS( Status ) ) {
#if DBG
        DbgPrint( "NTRTL: RtlpCreateStack( %lx ) failed.  Stack Commit Status == %X\n",
                  Process,
                  Status
                );
#endif // DBG
        return( Status );
        }

    //
    // if we have space, create a guard page.
    //

    if (GuardPage) {
        RegionSize =  SysInfo.PageSize;
        Status = ZwProtectVirtualMemory( Process,
                                         (PVOID *)&Stack,
                                         &RegionSize,
                                         PAGE_GUARD | PAGE_READWRITE,
                                         &OldProtect);


        if ( !NT_SUCCESS( Status ) ) {
#if DBG
            DbgPrint( "NTRTL: RtlpCreateStack( %lx ) failed.  Guard Page Creation Status == %X\n",
                      Process,
                      Status
                    );
#endif // DBG
            return( Status );
            }
        InitialTeb->StackLimit = (PVOID)((PUCHAR)InitialTeb->StackLimit + RegionSize);
        }

    return( STATUS_SUCCESS );
}
Example #4
0
VOID
PropertiesUpdate(
    IN PCONSOLE_INFORMATION Console,
    IN HANDLE hClientSection
    )

/*++

    Updates the console state from information sent by the properties
    dialog box.

--*/

{
    HANDLE hSection;
    ULONG ulViewSize;
    NTSTATUS Status;
    PCONSOLE_STATE_INFO pStateInfo;
    PCONSOLE_PROCESS_HANDLE ProcessHandleRecord;
    PSCREEN_INFORMATION ScreenInfo;
    ULONG FontIndex;
    WINDOWPLACEMENT wp;
    COORD NewSize;

    /*
     * Map the shared memory block handle into our address space.
     */
    ProcessHandleRecord = CONTAINING_RECORD(Console->ProcessHandleList.Blink,
                                            CONSOLE_PROCESS_HANDLE,
                                            ListLink);
    Status = NtDuplicateObject(ProcessHandleRecord->ProcessHandle,
                               hClientSection,
                               NtCurrentProcess(),
                               &hSection,
                               0,
                               0,
                               DUPLICATE_SAME_ACCESS);
    if (!NT_SUCCESS(Status)) {
        KdPrint(("CONSRV: error %x mapping client handle\n", Status));
        return;
    }

    /*
     * Get a pointer to the shared memory block.
     */
    pStateInfo = NULL;
    ulViewSize = 0;
    Status = NtMapViewOfSection(hSection,
                                NtCurrentProcess(),
                                &pStateInfo,
                                0,
                                0,
                                NULL,
                                &ulViewSize,
                                ViewUnmap,
                                0,
                                PAGE_READONLY);
    if (!NT_SUCCESS(Status)) {
        KdPrint(("CONSRV: error %x mapping view of file\n", Status));
        NtClose(hSection);
        return;
    }

    /*
     * Verify the size of the shared memory block.
     */
    if (ulViewSize < sizeof(CONSOLE_STATE_INFO)) {
        KdPrint(("CONSRV: sizeof(hSection) < sizeof(CONSOLE_STATE_INFO)\n"));
        NtUnmapViewOfSection(NtCurrentProcess(), pStateInfo);
        NtClose(hSection);
        return;
    }

    /*
     * Update the console state from the supplied values.
     */
    ScreenInfo = Console->CurrentScreenBuffer;
    if (!(Console->Flags & CONSOLE_VDM_REGISTERED) &&
        (pStateInfo->ScreenBufferSize.X != ScreenInfo->ScreenBufferSize.X ||
         pStateInfo->ScreenBufferSize.Y != ScreenInfo->ScreenBufferSize.Y)) {
        ResizeScreenBuffer(ScreenInfo,
                           pStateInfo->ScreenBufferSize,
                           TRUE);
    }
    FontIndex = FindCreateFont(pStateInfo->FontFamily,
                               pStateInfo->FaceName,
                               pStateInfo->FontSize,
                               pStateInfo->FontWeight);
    SetScreenBufferFont(ScreenInfo, FontIndex);
    SetCursorInformation(ScreenInfo,
                         pStateInfo->CursorSize,
                         ScreenInfo->BufferInfo.TextInfo.CursorVisible);

    NewSize.X = min(pStateInfo->WindowSize.X, ScreenInfo->MaximumWindowSize.X);
    NewSize.Y = min(pStateInfo->WindowSize.Y, ScreenInfo->MaximumWindowSize.Y);
    if (NewSize.X != CONSOLE_WINDOW_SIZE_X(ScreenInfo) ||
        NewSize.Y != CONSOLE_WINDOW_SIZE_Y(ScreenInfo)) {
        wp.length = sizeof(wp);
        GetWindowPlacement(Console->hWnd, &wp);
        wp.rcNormalPosition.right += (NewSize.X - CONSOLE_WINDOW_SIZE_X(ScreenInfo)) *
                            SCR_FONTSIZE(ScreenInfo).X;
        wp.rcNormalPosition.bottom += (NewSize.Y - CONSOLE_WINDOW_SIZE_Y(ScreenInfo)) *
                             SCR_FONTSIZE(ScreenInfo).Y;
        SetWindowPlacement(Console->hWnd, &wp);
    }

#ifdef _X86_
    if (FullScreenInitialized) {
        if (pStateInfo->FullScreen == FALSE) {
            if (Console->FullScreenFlags & CONSOLE_FULLSCREEN) {
                ConvertToWindowed(Console);
                ASSERT(!(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE));
                Console->FullScreenFlags = 0;

                ChangeDispSettings(Console, Console->hWnd, 0);
            }
        } else {
            if (Console->FullScreenFlags == 0) {
                ConvertToFullScreen(Console);
                Console->FullScreenFlags |= CONSOLE_FULLSCREEN;

                ChangeDispSettings(Console, Console->hWnd, CDS_FULLSCREEN);
            }
        }
    }
#endif
    if (pStateInfo->QuickEdit) {
        Console->Flags |= CONSOLE_QUICK_EDIT_MODE;
    } else {
        Console->Flags &= ~CONSOLE_QUICK_EDIT_MODE;
    }
    if (pStateInfo->AutoPosition) {
        Console->Flags |= CONSOLE_AUTO_POSITION;
    } else {
        Console->Flags &= ~CONSOLE_AUTO_POSITION;
        SetWindowPos(Console->hWnd, NULL,
                        pStateInfo->WindowPosX,
                        pStateInfo->WindowPosY,
                        0, 0, SWP_NOZORDER | SWP_NOSIZE);
    }
    if (Console->InsertMode != pStateInfo->InsertMode) {
        SetCursorMode(ScreenInfo, FALSE);
        Console->InsertMode = pStateInfo->InsertMode;
    }

    RtlCopyMemory(Console->ColorTable,
                  pStateInfo->ColorTable,
                  sizeof(Console->ColorTable));
    SetScreenColors(ScreenInfo,
                    pStateInfo->ScreenAttributes,
                    pStateInfo->PopupAttributes,
                    TRUE);

    Console->CommandHistorySize = pStateInfo->HistoryBufferSize;
    Console->MaxCommandHistories = pStateInfo->NumberOfHistoryBuffers;
    if (pStateInfo->HistoryNoDup) {
        Console->Flags |= CONSOLE_HISTORY_NODUP;
    } else {
        Console->Flags &= ~CONSOLE_HISTORY_NODUP;
    }

    NtUnmapViewOfSection(NtCurrentProcess(), pStateInfo);
    NtClose(hSection);

    return;
}
Example #5
0
INT_PTR CALLBACK PhpJobPageProc(
    _In_ HWND hwndDlg,
    _In_ UINT uMsg,
    _In_ WPARAM wParam,
    _In_ LPARAM lParam
    )
{
    PJOB_PAGE_CONTEXT jobPageContext;

    jobPageContext = PhpJobPageHeader(hwndDlg, uMsg, wParam, lParam);

    if (!jobPageContext)
        return FALSE;

    if (jobPageContext->HookProc)
    {
        if (jobPageContext->HookProc(hwndDlg, uMsg, wParam, lParam))
            return TRUE;
    }

    switch (uMsg)
    {
    case WM_INITDIALOG:
        {
            HANDLE jobHandle;
            HWND processesLv;
            HWND limitsLv;

            processesLv = GetDlgItem(hwndDlg, IDC_PROCESSES);
            limitsLv = GetDlgItem(hwndDlg, IDC_LIMITS);
            PhSetListViewStyle(processesLv, FALSE, TRUE);
            PhSetListViewStyle(limitsLv, FALSE, TRUE);
            PhSetControlTheme(processesLv, L"explorer");
            PhSetControlTheme(limitsLv, L"explorer");

            PhAddListViewColumn(processesLv, 0, 0, 0, LVCFMT_LEFT, 240, L"Name");

            PhAddListViewColumn(limitsLv, 0, 0, 0, LVCFMT_LEFT, 120, L"Name");
            PhAddListViewColumn(limitsLv, 1, 1, 1, LVCFMT_LEFT, 160, L"Value");
            PhLoadListViewColumnsFromSetting(L"JobListViewColumns", limitsLv);

            SetDlgItemText(hwndDlg, IDC_NAME, L"Unknown");

            if (NT_SUCCESS(jobPageContext->OpenObject(
                &jobHandle,
                JOB_OBJECT_QUERY,
                jobPageContext->Context
                )))
            {
                PPH_STRING jobObjectName = NULL;
                JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedLimits;
                JOBOBJECT_BASIC_UI_RESTRICTIONS basicUiRestrictions;

                // Name

                PhGetHandleInformation(
                    NtCurrentProcess(),
                    jobHandle,
                    -1,
                    NULL,
                    NULL,
                    NULL,
                    &jobObjectName
                    );
                PH_AUTO(jobObjectName);

                if (jobObjectName && jobObjectName->Length == 0)
                    jobObjectName = NULL;

                SetDlgItemText(hwndDlg, IDC_NAME, PhGetStringOrDefault(jobObjectName, L"(unnamed job)"));

                // Processes
                PhpAddJobProcesses(hwndDlg, jobHandle);

                // Limits

                if (NT_SUCCESS(PhGetJobExtendedLimits(jobHandle, &extendedLimits)))
                {
                    ULONG flags = extendedLimits.BasicLimitInformation.LimitFlags;

                    if (flags & JOB_OBJECT_LIMIT_ACTIVE_PROCESS)
                    {
                        WCHAR value[PH_INT32_STR_LEN_1];
                        PhPrintUInt32(value, extendedLimits.BasicLimitInformation.ActiveProcessLimit);
                        PhpAddLimit(limitsLv, L"Active processes", value);
                    }

                    if (flags & JOB_OBJECT_LIMIT_AFFINITY)
                    {
                        WCHAR value[PH_PTR_STR_LEN_1];
                        PhPrintPointer(value, (PVOID)extendedLimits.BasicLimitInformation.Affinity);
                        PhpAddLimit(limitsLv, L"Affinity", value);
                    }

                    if (flags & JOB_OBJECT_LIMIT_BREAKAWAY_OK)
                    {
                        PhpAddLimit(limitsLv, L"Breakaway OK", L"Enabled");
                    }

                    if (flags & JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION)
                    {
                        PhpAddLimit(limitsLv, L"Die on unhandled exception", L"Enabled");
                    }

                    if (flags & JOB_OBJECT_LIMIT_JOB_MEMORY)
                    {
                        PPH_STRING value = PhaFormatSize(extendedLimits.JobMemoryLimit, -1);
                        PhpAddLimit(limitsLv, L"Job memory", value->Buffer);
                    }

                    if (flags & JOB_OBJECT_LIMIT_JOB_TIME)
                    {
                        WCHAR value[PH_TIMESPAN_STR_LEN_1];
                        PhPrintTimeSpan(value, extendedLimits.BasicLimitInformation.PerJobUserTimeLimit.QuadPart,
                            PH_TIMESPAN_DHMS);
                        PhpAddLimit(limitsLv, L"Job time", value);
                    }

                    if (flags & JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE)
                    {
                        PhpAddLimit(limitsLv, L"Kill on job close", L"Enabled");
                    }

                    if (flags & JOB_OBJECT_LIMIT_PRIORITY_CLASS)
                    {
                        PhpAddLimit(limitsLv, L"Priority class",
                            PhGetProcessPriorityClassString(extendedLimits.BasicLimitInformation.PriorityClass));
                    }

                    if (flags & JOB_OBJECT_LIMIT_PROCESS_MEMORY)
                    {
                        PPH_STRING value = PhaFormatSize(extendedLimits.ProcessMemoryLimit, -1);
                        PhpAddLimit(limitsLv, L"Process memory", value->Buffer);
                    }

                    if (flags & JOB_OBJECT_LIMIT_PROCESS_TIME)
                    {
                        WCHAR value[PH_TIMESPAN_STR_LEN_1];
                        PhPrintTimeSpan(value, extendedLimits.BasicLimitInformation.PerProcessUserTimeLimit.QuadPart,
                            PH_TIMESPAN_DHMS);
                        PhpAddLimit(limitsLv, L"Process time", value);
                    }

                    if (flags & JOB_OBJECT_LIMIT_SCHEDULING_CLASS)
                    {
                        WCHAR value[PH_INT32_STR_LEN_1];
                        PhPrintUInt32(value, extendedLimits.BasicLimitInformation.SchedulingClass);
                        PhpAddLimit(limitsLv, L"Scheduling class", value);
                    }

                    if (flags & JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)
                    {
                        PhpAddLimit(limitsLv, L"Silent breakaway OK", L"Enabled");
                    }

                    if (flags & JOB_OBJECT_LIMIT_WORKINGSET)
                    {
                        PPH_STRING value;

                        value = PhaFormatSize(extendedLimits.BasicLimitInformation.MinimumWorkingSetSize, -1);
                        PhpAddLimit(limitsLv, L"Working set minimum", value->Buffer);

                        value = PhaFormatSize(extendedLimits.BasicLimitInformation.MaximumWorkingSetSize, -1);
                        PhpAddLimit(limitsLv, L"Working set maximum", value->Buffer);
                    }
                }

                if (NT_SUCCESS(PhGetJobBasicUiRestrictions(jobHandle, &basicUiRestrictions)))
                {
                    ULONG flags = basicUiRestrictions.UIRestrictionsClass;

                    if (flags & JOB_OBJECT_UILIMIT_DESKTOP)
                        PhpAddLimit(limitsLv, L"Desktop", L"Limited");
                    if (flags & JOB_OBJECT_UILIMIT_DISPLAYSETTINGS)
                        PhpAddLimit(limitsLv, L"Display settings", L"Limited");
                    if (flags & JOB_OBJECT_UILIMIT_EXITWINDOWS)
                        PhpAddLimit(limitsLv, L"Exit windows", L"Limited");
                    if (flags & JOB_OBJECT_UILIMIT_GLOBALATOMS)
                        PhpAddLimit(limitsLv, L"Global atoms", L"Limited");
                    if (flags & JOB_OBJECT_UILIMIT_HANDLES)
                        PhpAddLimit(limitsLv, L"Handles", L"Limited");
                    if (flags & JOB_OBJECT_UILIMIT_READCLIPBOARD)
                        PhpAddLimit(limitsLv, L"Read clipboard", L"Limited");
                    if (flags & JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS)
                        PhpAddLimit(limitsLv, L"System parameters", L"Limited");
                    if (flags & JOB_OBJECT_UILIMIT_WRITECLIPBOARD)
                        PhpAddLimit(limitsLv, L"Write clipboard", L"Limited");
                }

                NtClose(jobHandle);
            }
        }
        break;
    case WM_DESTROY:
        PhSaveListViewColumnsToSetting(L"JobListViewColumns", GetDlgItem(hwndDlg, IDC_LIMITS));
        break;
    case WM_COMMAND:
        {
            switch (GET_WM_COMMAND_ID(wParam, lParam))
            {
            case IDC_TERMINATE:
                {
                    if (PhShowConfirmMessage(
                        hwndDlg,
                        L"terminate",
                        L"the job",
                        L"Terminating a job will terminate all processes assigned to it.",
                        TRUE
                        ))
                    {
                        NTSTATUS status;
                        HANDLE jobHandle;

                        if (NT_SUCCESS(status = jobPageContext->OpenObject(
                            &jobHandle,
                            JOB_OBJECT_TERMINATE,
                            jobPageContext->Context
                            )))
                        {
                            status = NtTerminateJobObject(jobHandle, STATUS_SUCCESS);
                            NtClose(jobHandle);
                        }

                        if (!NT_SUCCESS(status))
                            PhShowStatus(hwndDlg, L"Unable to terminate the job", status, 0);
                    }
                }
                break;
            case IDC_ADD:
                {
                    NTSTATUS status;
                    HANDLE processId;
                    HANDLE processHandle;
                    HANDLE jobHandle;

                    while (PhShowChooseProcessDialog(
                        hwndDlg,
                        L"Select a process to add to the job permanently.",
                        &processId
                        ))
                    {
                        if (NT_SUCCESS(status = PhOpenProcess(
                            &processHandle,
                            PROCESS_TERMINATE | PROCESS_SET_QUOTA,
                            processId
                            )))
                        {
                            if (NT_SUCCESS(status = jobPageContext->OpenObject(
                                &jobHandle,
                                JOB_OBJECT_ASSIGN_PROCESS | JOB_OBJECT_QUERY,
                                jobPageContext->Context
                                )))
                            {
                                status = NtAssignProcessToJobObject(jobHandle, processHandle);

                                if (NT_SUCCESS(status))
                                {
                                    ListView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_PROCESSES));
                                    PhpAddJobProcesses(hwndDlg, jobHandle);
                                }

                                NtClose(jobHandle);
                            }

                            NtClose(processHandle);
                        }

                        if (NT_SUCCESS(status))
                            break;
                        else
                            PhShowStatus(hwndDlg, L"Unable to add the process to the job", status, 0);
                    }
                }
                break;
            case IDC_ADVANCED:
                {
                    PhpShowJobAdvancedProperties(hwndDlg, jobPageContext);
                }
                break;
            }
        }
        break;
    case WM_NOTIFY:
        {
            PhHandleListViewNotifyBehaviors(lParam, GetDlgItem(hwndDlg, IDC_PROCESSES), PH_LIST_VIEW_DEFAULT_1_BEHAVIORS);
            PhHandleListViewNotifyBehaviors(lParam, GetDlgItem(hwndDlg, IDC_LIMITS), PH_LIST_VIEW_DEFAULT_1_BEHAVIORS);
        }
        break;
    }

    return FALSE;
}
Example #6
0
NTSTATUS PhpGetBestObjectName(
    __in HANDLE ProcessHandle,
    __in HANDLE Handle,
    __in PPH_STRING ObjectName,
    __in PPH_STRING TypeName,
    __out PPH_STRING *BestObjectName
    )
{
    NTSTATUS status;
    PPH_STRING bestObjectName = NULL;
    PPH_GET_CLIENT_ID_NAME handleGetClientIdName;

    if (PhEqualString2(TypeName, L"EtwRegistration", TRUE))
    {
        if (KphIsConnected())
        {
            ETWREG_BASIC_INFORMATION basicInfo;

            status = KphQueryInformationObject(
                ProcessHandle,
                Handle,
                KphObjectEtwRegBasicInformation,
                &basicInfo,
                sizeof(ETWREG_BASIC_INFORMATION),
                NULL
                );

            if (NT_SUCCESS(status))
            {
                static PH_STRINGREF publishersKeyName = PH_STRINGREF_INIT(L"Software\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Publishers\\");

                PPH_STRING guidString;
                PPH_STRING keyName;
                HANDLE keyHandle;
                PPH_STRING publisherName = NULL;

                guidString = PhFormatGuid(&basicInfo.Guid);

                // We should perform a lookup on the GUID to get the publisher name.

                keyName = PhConcatStringRef2(&publishersKeyName, &guidString->sr);

                if (NT_SUCCESS(PhOpenKey(
                    &keyHandle,
                    KEY_READ,
                    PH_KEY_LOCAL_MACHINE,
                    &keyName->sr,
                    0
                    )))
                {
                    publisherName = PhQueryRegistryString(keyHandle, NULL);

                    if (publisherName && publisherName->Length == 0)
                    {
                        PhDereferenceObject(publisherName);
                        publisherName = NULL;
                    }

                    NtClose(keyHandle);
                }

                PhDereferenceObject(keyName);

                if (publisherName)
                {
                    bestObjectName = publisherName;
                    PhDereferenceObject(guidString);
                }
                else
                {
                    bestObjectName = guidString;
                }
            }
        }
    }
    else if (PhEqualString2(TypeName, L"File", TRUE))
    {
        // Convert the file name to a DOS file name.
        bestObjectName = PhResolveDevicePrefix(ObjectName);

        if (!bestObjectName)
        {
            bestObjectName = ObjectName;
            PhReferenceObject(ObjectName);
        }
    }
    else if (PhEqualString2(TypeName, L"Key", TRUE))
    {
        bestObjectName = PhFormatNativeKeyName(ObjectName);
    }
    else if (PhEqualString2(TypeName, L"Process", TRUE))
    {
        CLIENT_ID clientId;

        clientId.UniqueThread = NULL;

        if (KphIsConnected())
        {
            PROCESS_BASIC_INFORMATION basicInfo;

            status = KphQueryInformationObject(
                ProcessHandle,
                Handle,
                KphObjectProcessBasicInformation,
                &basicInfo,
                sizeof(PROCESS_BASIC_INFORMATION),
                NULL
                );

            if (!NT_SUCCESS(status))
                goto CleanupExit;

            clientId.UniqueProcess = basicInfo.UniqueProcessId;
        }
        else
        {
            HANDLE dupHandle;
            PROCESS_BASIC_INFORMATION basicInfo;

            status = NtDuplicateObject(
                ProcessHandle,
                Handle,
                NtCurrentProcess(),
                &dupHandle,
                ProcessQueryAccess,
                0,
                0
                );

            if (!NT_SUCCESS(status))
                goto CleanupExit;

            status = PhGetProcessBasicInformation(dupHandle, &basicInfo);
            NtClose(dupHandle);

            if (!NT_SUCCESS(status))
                goto CleanupExit;

            clientId.UniqueProcess = basicInfo.UniqueProcessId;
        }

        handleGetClientIdName = PhHandleGetClientIdName;

        if (handleGetClientIdName)
            bestObjectName = handleGetClientIdName(&clientId);
    }
    else if (PhEqualString2(TypeName, L"Thread", TRUE))
    {
        CLIENT_ID clientId;

        if (KphIsConnected())
        {
            THREAD_BASIC_INFORMATION basicInfo;

            status = KphQueryInformationObject(
                ProcessHandle,
                Handle,
                KphObjectThreadBasicInformation,
                &basicInfo,
                sizeof(THREAD_BASIC_INFORMATION),
                NULL
                );

            if (!NT_SUCCESS(status))
                goto CleanupExit;

            clientId = basicInfo.ClientId;
        }
        else
        {
            HANDLE dupHandle;
            THREAD_BASIC_INFORMATION basicInfo;

            status = NtDuplicateObject(
                ProcessHandle,
                Handle,
                NtCurrentProcess(),
                &dupHandle,
                ThreadQueryAccess,
                0,
                0
                );

            if (!NT_SUCCESS(status))
                goto CleanupExit;

            status = PhGetThreadBasicInformation(dupHandle, &basicInfo);
            NtClose(dupHandle);

            if (!NT_SUCCESS(status))
                goto CleanupExit;

            clientId = basicInfo.ClientId;
        }

        handleGetClientIdName = PhHandleGetClientIdName;

        if (handleGetClientIdName)
            bestObjectName = handleGetClientIdName(&clientId);
    }
    else if (PhEqualString2(TypeName, L"TmEn", TRUE))
    {
        HANDLE dupHandle;
        ENLISTMENT_BASIC_INFORMATION basicInfo;

        status = NtDuplicateObject(
            ProcessHandle,
            Handle,
            NtCurrentProcess(),
            &dupHandle,
            ENLISTMENT_QUERY_INFORMATION,
            0,
            0
            );

        if (!NT_SUCCESS(status))
            goto CleanupExit;

        status = PhGetEnlistmentBasicInformation(dupHandle, &basicInfo);
        NtClose(dupHandle);

        if (NT_SUCCESS(status))
        {
            bestObjectName = PhFormatGuid(&basicInfo.EnlistmentId);
        }
    }
    else if (PhEqualString2(TypeName, L"TmRm", TRUE))
    {
        HANDLE dupHandle;
        GUID guid;
        PPH_STRING description;

        status = NtDuplicateObject(
            ProcessHandle,
            Handle,
            NtCurrentProcess(),
            &dupHandle,
            RESOURCEMANAGER_QUERY_INFORMATION,
            0,
            0
            );

        if (!NT_SUCCESS(status))
            goto CleanupExit;

        status = PhGetResourceManagerBasicInformation(
            dupHandle,
            &guid,
            &description
            );
        NtClose(dupHandle);

        if (NT_SUCCESS(status))
        {
            if (!PhIsNullOrEmptyString(description))
            {
                bestObjectName = description;
            }
            else
            {
                bestObjectName = PhFormatGuid(&guid);

                if (description)
                    PhDereferenceObject(description);
            }
        }
    }
    else if (PhEqualString2(TypeName, L"TmTm", TRUE))
    {
        HANDLE dupHandle;
        PPH_STRING logFileName = NULL;
        TRANSACTIONMANAGER_BASIC_INFORMATION basicInfo;

        status = NtDuplicateObject(
            ProcessHandle,
            Handle,
            NtCurrentProcess(),
            &dupHandle,
            TRANSACTIONMANAGER_QUERY_INFORMATION,
            0,
            0
            );

        if (!NT_SUCCESS(status))
            goto CleanupExit;

        status = PhGetTransactionManagerLogFileName(
            dupHandle,
            &logFileName
            );

        if (NT_SUCCESS(status) && !PhIsNullOrEmptyString(logFileName))
        {
            bestObjectName = PhGetFileName(logFileName);
            PhDereferenceObject(logFileName);
        }
        else
        {
            if (logFileName)
                PhDereferenceObject(logFileName);

            status = PhGetTransactionManagerBasicInformation(
                dupHandle,
                &basicInfo
                );

            if (NT_SUCCESS(status))
            {
                bestObjectName = PhFormatGuid(&basicInfo.TmIdentity);
            }
        }

        NtClose(dupHandle);
    }
    else if (PhEqualString2(TypeName, L"TmTx", TRUE))
    {
        HANDLE dupHandle;
        PPH_STRING description = NULL;
        TRANSACTION_BASIC_INFORMATION basicInfo;

        status = NtDuplicateObject(
            ProcessHandle,
            Handle,
            NtCurrentProcess(),
            &dupHandle,
            TRANSACTION_QUERY_INFORMATION,
            0,
            0
            );

        if (!NT_SUCCESS(status))
            goto CleanupExit;

        status = PhGetTransactionPropertiesInformation(
            dupHandle,
            NULL,
            NULL,
            &description
            );

        if (NT_SUCCESS(status) && !PhIsNullOrEmptyString(description))
        {
            bestObjectName = description;
        }
        else
        {
            if (description)
                PhDereferenceObject(description);

            status = PhGetTransactionBasicInformation(
                dupHandle,
                &basicInfo
                );

            if (NT_SUCCESS(status))
            {
                bestObjectName = PhFormatGuid(&basicInfo.TransactionId);
            }
        }

        NtClose(dupHandle);
    }
    else if (PhEqualString2(TypeName, L"Token", TRUE))
    {
        HANDLE dupHandle;
        PTOKEN_USER tokenUser = NULL;
        TOKEN_STATISTICS statistics = { 0 };

        status = NtDuplicateObject(
            ProcessHandle,
            Handle,
            NtCurrentProcess(),
            &dupHandle,
            TOKEN_QUERY,
            0,
            0
            );

        if (!NT_SUCCESS(status))
            goto CleanupExit;

        status = PhGetTokenUser(dupHandle, &tokenUser);
        PhGetTokenStatistics(dupHandle, &statistics);

        if (NT_SUCCESS(status))
        {
            PPH_STRING fullName;

            fullName = PhGetSidFullName(tokenUser->User.Sid, TRUE, NULL);

            if (fullName)
            {
                PH_FORMAT format[3];

                PhInitFormatSR(&format[0], fullName->sr);
                PhInitFormatS(&format[1], L": 0x");
                PhInitFormatX(&format[2], statistics.AuthenticationId.LowPart);

                bestObjectName = PhFormat(format, 3, fullName->Length + 8 + 16);
                PhDereferenceObject(fullName);
            }

            PhFree(tokenUser);
        }

        NtClose(dupHandle);
    }

CleanupExit:

    if (!bestObjectName)
    {
        bestObjectName = ObjectName;
        PhReferenceObject(ObjectName);
    }

    *BestObjectName = bestObjectName;

    return STATUS_SUCCESS;
}
Example #7
0
BOOLEAN WepCreateServerObjects(
    VOID
    )
{
    OBJECT_ATTRIBUTES objectAttributes;
    WCHAR buffer[256];
    UNICODE_STRING objectName;
    SECURITY_DESCRIPTOR securityDescriptor;
    UCHAR saclBuffer[sizeof(ACL) + FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE, SidStart) + FIELD_OFFSET(SID, SubAuthority) + sizeof(ULONG)];
    PACL sacl;
    UCHAR mandatoryLabelAceBuffer[FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE, SidStart) + FIELD_OFFSET(SID, SubAuthority) + sizeof(ULONG)];
    PSYSTEM_MANDATORY_LABEL_ACE mandatoryLabelAce;
    PSID sid;

    if (!WeServerSharedSection)
    {
        LARGE_INTEGER maximumSize;

        WeFormatLocalObjectName(WE_SERVER_SHARED_SECTION_NAME, buffer, &objectName);
        InitializeObjectAttributes(&objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL);
        maximumSize.QuadPart = sizeof(WE_HOOK_SHARED_DATA);

        if (!NT_SUCCESS(NtCreateSection(
            &WeServerSharedSection,
            SECTION_ALL_ACCESS,
            &objectAttributes,
            &maximumSize,
            PAGE_READWRITE,
            SEC_COMMIT,
            NULL
            )))
        {
            return FALSE;
        }
    }

    if (!WeServerSharedData)
    {
        PVOID viewBase;
        SIZE_T viewSize;

        viewBase = NULL;
        viewSize = sizeof(WE_HOOK_SHARED_DATA);

        if (!NT_SUCCESS(NtMapViewOfSection(
            WeServerSharedSection,
            NtCurrentProcess(),
            &viewBase,
            0,
            0,
            NULL,
            &viewSize,
            ViewShare,
            0,
            PAGE_READWRITE
            )))
        {
            WepCloseServerObjects();
            return FALSE;
        }

        WeServerSharedData = viewBase;
    }

    if (!WeServerSharedSectionLock)
    {
        WeFormatLocalObjectName(WE_SERVER_SHARED_SECTION_LOCK_NAME, buffer, &objectName);
        InitializeObjectAttributes(&objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL);

        if (!NT_SUCCESS(NtCreateMutant(
            &WeServerSharedSectionLock,
            MUTANT_ALL_ACCESS,
            &objectAttributes,
            FALSE
            )))
        {
            WepCloseServerObjects();
            return FALSE;
        }
    }

    if (!WeServerSharedSectionEvent)
    {
        WeFormatLocalObjectName(WE_SERVER_SHARED_SECTION_EVENT_NAME, buffer, &objectName);
        InitializeObjectAttributes(&objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL);

        if (!NT_SUCCESS(NtCreateEvent(
            &WeServerSharedSectionEvent,
            EVENT_ALL_ACCESS,
            &objectAttributes,
            NotificationEvent,
            FALSE
            )))
        {
            WepCloseServerObjects();
            return FALSE;
        }
    }

    // If mandatory labels are supported, set it to the lowest possible level.
    if (WE_WindowsVersion >= WINDOWS_VISTA)
    {
        static SID_IDENTIFIER_AUTHORITY mandatoryLabelAuthority = SECURITY_MANDATORY_LABEL_AUTHORITY;

        RtlCreateSecurityDescriptor(&securityDescriptor, SECURITY_DESCRIPTOR_REVISION);

        sacl = (PACL)saclBuffer;
        RtlCreateAcl(sacl, sizeof(saclBuffer), ACL_REVISION);

        mandatoryLabelAce = (PSYSTEM_MANDATORY_LABEL_ACE)mandatoryLabelAceBuffer;
        mandatoryLabelAce->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
        mandatoryLabelAce->Header.AceFlags = 0;
        mandatoryLabelAce->Header.AceSize = sizeof(mandatoryLabelAceBuffer);
        mandatoryLabelAce->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;

        sid = (PSID)&mandatoryLabelAce->SidStart;
        RtlInitializeSid(sid, &mandatoryLabelAuthority, 1);
        *RtlSubAuthoritySid(sid, 0) = SECURITY_MANDATORY_LOW_RID;

        if (NT_SUCCESS(RtlAddAce(sacl, ACL_REVISION, MAXULONG32, mandatoryLabelAce, sizeof(mandatoryLabelAceBuffer))))
        {
            if (NT_SUCCESS(RtlSetSaclSecurityDescriptor(&securityDescriptor, TRUE, sacl, FALSE)))
            {
                NtSetSecurityObject(WeServerSharedSection, LABEL_SECURITY_INFORMATION, &securityDescriptor);
                NtSetSecurityObject(WeServerSharedSectionLock, LABEL_SECURITY_INFORMATION, &securityDescriptor);
                NtSetSecurityObject(WeServerSharedSectionEvent, LABEL_SECURITY_INFORMATION, &securityDescriptor);
            }
        }
    }

    return TRUE;
}
Example #8
0
BOOL
WINAPI
DllMain(HANDLE hDll,
        DWORD dwReason,
        LPVOID lpReserved)
{
    NTSTATUS Status;
    BASESRV_API_CONNECTINFO ConnectInfo;
    ULONG ConnectInfoSize = sizeof(ConnectInfo);
    WCHAR SessionDir[256];

    DPRINT("DllMain(hInst %p, dwReason %lu)\n",
           hDll, dwReason);

    Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;

    /* Cache the PEB and Session ID */
    Peb = NtCurrentPeb();
    SessionId = Peb->SessionId;

    switch (dwReason)
    {
        case DLL_PROCESS_ATTACH:
        {
            /* Set no filter initially */
            GlobalTopLevelExceptionFilter = RtlEncodePointer(NULL);
            
            /* Enable the Rtl thread pool and timer queue to use proper Win32 thread */
            RtlSetThreadPoolStartFunc(BaseCreateThreadPoolThread, BaseExitThreadPoolThread);

            /* Register the manifest prober routine */
            LdrSetDllManifestProber(BasepProbeForDllManifest);

            /* Don't bother us for each thread */
            LdrDisableThreadCalloutsForDll((PVOID)hDll);

            /* Initialize default path to NULL */
            RtlInitUnicodeString(&BaseDefaultPath, NULL);

            /* Setup the Object Directory path */
            if (!SessionId)
            {
                /* Use the raw path */
                wcscpy(SessionDir, WIN_OBJ_DIR);
            }
            else
            {
                /* Use the session path */
                swprintf(SessionDir,
                         L"%ws\\%ld%ws",
                         SESSION_DIR,
                         SessionId,
                         WIN_OBJ_DIR);
            }

            /* Connect to the Base Server */
            Status = CsrClientConnectToServer(SessionDir,
                                              BASESRV_SERVERDLL_INDEX,
                                              &ConnectInfo,
                                              &ConnectInfoSize,
                                              &BaseRunningInServerProcess);
            if (!NT_SUCCESS(Status))
            {
                DPRINT1("Failed to connect to CSR (Status %lx)\n", Status);
                NtTerminateProcess(NtCurrentProcess(), Status);
                return FALSE;
            }

            /* Get the server data */
            ASSERT(Peb->ReadOnlyStaticServerData);
            BaseStaticServerData = Peb->ReadOnlyStaticServerData[BASESRV_SERVERDLL_INDEX];
            ASSERT(BaseStaticServerData);

            /* Check if we are running a CSR Server */
            if (!BaseRunningInServerProcess)
            {
                /* Set the termination port for the thread */
                DPRINT("Creating new thread for CSR\n");
                CsrNewThread();
            }

            /* Initialize heap handle table */
            BaseDllInitializeMemoryManager();

            /* Set HMODULE for our DLL */
            kernel32_handle = hCurrentModule = hDll;

            /* Set the directories */
            BaseWindowsDirectory = BaseStaticServerData->WindowsDirectory;
            BaseWindowsSystemDirectory = BaseStaticServerData->WindowsSystemDirectory;

            /* Construct the default path (using the static buffer) */
            _snwprintf(BaseDefaultPathBuffer,
                       sizeof(BaseDefaultPathBuffer) / sizeof(WCHAR),
                       L".;%wZ;%wZ\\system;%wZ;",
                       &BaseWindowsSystemDirectory,
                       &BaseWindowsDirectory,
                       &BaseWindowsDirectory);

            BaseDefaultPath.Buffer = BaseDefaultPathBuffer;
            BaseDefaultPath.Length = wcslen(BaseDefaultPathBuffer) * sizeof(WCHAR);
            BaseDefaultPath.MaximumLength = sizeof(BaseDefaultPathBuffer);

            /* Use remaining part of the default path buffer for the append path */
            BaseDefaultPathAppend.Buffer = (PWSTR)((ULONG_PTR)BaseDefaultPathBuffer + BaseDefaultPath.Length);
            BaseDefaultPathAppend.Length = 0;
            BaseDefaultPathAppend.MaximumLength = BaseDefaultPath.MaximumLength - BaseDefaultPath.Length;

            /* Initialize command line */
            InitCommandLines();

            /* Initialize the DLL critical section */
            RtlInitializeCriticalSection(&BaseDllDirectoryLock);

            /* Initialize the National Language Support routines */
            if (!NlsInit())
            {
                DPRINT1("NLS Init failed\n");
                return FALSE;
            }

            /* Initialize Console Support */
            if (!ConDllInitialize(dwReason, SessionDir))
            {
                DPRINT1("Failed to set up console\n");
                return FALSE;
            }

            /* Initialize application certification globals */
            InitializeListHead(&BasepAppCertDllsList);
            RtlInitializeCriticalSection(&gcsAppCert);

            /* Insert more dll attach stuff here! */
            DllInitialized = TRUE;
            break;
        }

        case DLL_PROCESS_DETACH:
        {
            if (DllInitialized == TRUE)
            {
                /* Uninitialize console support */
                ConDllInitialize(dwReason, NULL);

                /* Insert more dll detach stuff here! */
                NlsUninit();

                /* Delete DLL critical section */
                RtlDeleteCriticalSection(&BaseDllDirectoryLock);
            }
            break;
        }

        case DLL_THREAD_ATTACH:
        {
            /* ConDllInitialize sets the current console locale for the new thread */
            return ConDllInitialize(dwReason, NULL);
        }

        default:
            break;
    }

    return TRUE;
}
Example #9
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");
}
Example #10
0
/*
 * @implemented
 */
BOOL WINAPI
CheckTokenMembership(IN HANDLE ExistingTokenHandle,
                     IN PSID SidToCheck,
                     OUT PBOOL IsMember)
{
    PISECURITY_DESCRIPTOR SecurityDescriptor = NULL;
    ACCESS_MASK GrantedAccess;
    struct
    {
        PRIVILEGE_SET PrivilegeSet;
        LUID_AND_ATTRIBUTES Privileges[4];
    } PrivBuffer;
    ULONG PrivBufferSize = sizeof(PrivBuffer);
    GENERIC_MAPPING GenericMapping =
    {
        STANDARD_RIGHTS_READ,
        STANDARD_RIGHTS_WRITE,
        STANDARD_RIGHTS_EXECUTE,
        STANDARD_RIGHTS_ALL
    };
    PACL Dacl;
    ULONG SidLen;
    HANDLE hToken = NULL;
    NTSTATUS Status, AccessStatus;

    /* doesn't return gracefully if IsMember is NULL! */
    *IsMember = FALSE;

    SidLen = RtlLengthSid(SidToCheck);

    if (ExistingTokenHandle == NULL)
    {
        Status = NtOpenThreadToken(NtCurrentThread(),
                                   TOKEN_QUERY,
                                   FALSE,
                                   &hToken);

        if (Status == STATUS_NO_TOKEN)
        {
            /* we're not impersonating, open the primary token */
            Status = NtOpenProcessToken(NtCurrentProcess(),
                                        TOKEN_QUERY | TOKEN_DUPLICATE,
                                        &hToken);
            if (NT_SUCCESS(Status))
            {
                HANDLE hNewToken = FALSE;
                BOOL DupRet;

                /* duplicate the primary token to create an impersonation token */
                DupRet = DuplicateTokenEx(hToken,
                                          TOKEN_QUERY | TOKEN_IMPERSONATE,
                                          NULL,
                                          SecurityImpersonation,
                                          TokenImpersonation,
                                          &hNewToken);

                NtClose(hToken);

                if (!DupRet)
                {
                    WARN("Failed to duplicate the primary token!\n");
                    return FALSE;
                }

                hToken = hNewToken;
            }
        }

        if (!NT_SUCCESS(Status))
        {
            goto Cleanup;
        }
    }
    else
    {
        hToken = ExistingTokenHandle;
    }

    /* create a security descriptor */
    SecurityDescriptor = RtlAllocateHeap(RtlGetProcessHeap(),
                                         0,
                                         sizeof(SECURITY_DESCRIPTOR) +
                                             sizeof(ACL) + SidLen +
                                             sizeof(ACCESS_ALLOWED_ACE));
    if (SecurityDescriptor == NULL)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto Cleanup;
    }

    Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
                                         SECURITY_DESCRIPTOR_REVISION);
    if (!NT_SUCCESS(Status))
    {
        goto Cleanup;
    }

    /* set the owner and group */
    Status = RtlSetOwnerSecurityDescriptor(SecurityDescriptor,
                                           SidToCheck,
                                           FALSE);
    if (!NT_SUCCESS(Status))
    {
        goto Cleanup;
    }

    Status = RtlSetGroupSecurityDescriptor(SecurityDescriptor,
                                           SidToCheck,
                                           FALSE);
    if (!NT_SUCCESS(Status))
    {
        goto Cleanup;
    }

    /* create the DACL */
    Dacl = (PACL)(SecurityDescriptor + 1);
    Status = RtlCreateAcl(Dacl,
                          sizeof(ACL) + SidLen + sizeof(ACCESS_ALLOWED_ACE),
                          ACL_REVISION);
    if (!NT_SUCCESS(Status))
    {
        goto Cleanup;
    }

    Status = RtlAddAccessAllowedAce(Dacl,
                                    ACL_REVISION,
                                    0x1,
                                    SidToCheck);
    if (!NT_SUCCESS(Status))
    {
        goto Cleanup;
    }

    /* assign the DACL to the security descriptor */
    Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
                                          TRUE,
                                          Dacl,
                                          FALSE);
    if (!NT_SUCCESS(Status))
    {
        goto Cleanup;
    }

    /* it's time to perform the access check. Just use _some_ desired access right
       (same as for the ACE) and see if we're getting it granted. This indicates
       our SID is a member of the token. We however can't use a generic access
       right as those aren't mapped and return an error (STATUS_GENERIC_NOT_MAPPED). */
    Status = NtAccessCheck(SecurityDescriptor,
                           hToken,
                           0x1,
                           &GenericMapping,
                           &PrivBuffer.PrivilegeSet,
                           &PrivBufferSize,
                           &GrantedAccess,
                           &AccessStatus);
    if (NT_SUCCESS(Status) && NT_SUCCESS(AccessStatus) && (GrantedAccess == 0x1))
    {
        *IsMember = TRUE;
    }

Cleanup:
    if (hToken != NULL && hToken != ExistingTokenHandle)
    {
        NtClose(hToken);
    }

    if (SecurityDescriptor != NULL)
    {
        RtlFreeHeap(RtlGetProcessHeap(),
                    0,
                    SecurityDescriptor);
    }

    if (!NT_SUCCESS(Status))
    {
        SetLastError(RtlNtStatusToDosError(Status));
        return FALSE;
    }

    return TRUE;
}
Example #11
0
NTSTATUS
NTAPI
SmpCreateVolumeDescriptors(VOID)
{
    NTSTATUS Status;
    UNICODE_STRING VolumePath;
    BOOLEAN BootVolumeFound = FALSE;
    WCHAR StartChar, Drive, DriveDiff;
    HANDLE VolumeHandle;
    OBJECT_ATTRIBUTES ObjectAttributes;
    IO_STATUS_BLOCK IoStatusBlock;
    PROCESS_DEVICEMAP_INFORMATION ProcessInformation;
    FILE_FS_DEVICE_INFORMATION DeviceInfo;
    FILE_FS_SIZE_INFORMATION SizeInfo;
    PSMP_VOLUME_DESCRIPTOR Volume;
    LARGE_INTEGER FreeSpace, FinalFreeSpace;
    WCHAR Buffer[32];

    /* We should be starting with an empty list */
    ASSERT(IsListEmpty(&SmpVolumeDescriptorList));

    /* Query the device map so we can get the drive letters */
    Status = NtQueryInformationProcess(NtCurrentProcess(),
                                       ProcessDeviceMap,
                                       &ProcessInformation,
                                       sizeof(ProcessInformation),
                                       NULL);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("SMSS:PFILE: Query(ProcessDeviceMap) failed with status %X \n",
                Status);
        return Status;
    }

    /* Build the volume string, starting with A: (we'll edit this in place) */
    wcscpy(Buffer, L"\\??\\A:\\");
    RtlInitUnicodeString(&VolumePath, Buffer);

    /* Start with the C drive except on weird Japanese NECs... */
    StartChar = SharedUserData->AlternativeArchitecture ? L'A' : L'C';
    for (Drive = StartChar, DriveDiff = StartChar - L'A'; Drive <= L'Z'; Drive++, DriveDiff++)
    {
        /* Skip the disk if it's not in the drive map */
        if (!((1 << DriveDiff) & ProcessInformation.Query.DriveMap)) continue;

        /* Write the drive letter and try to open the volume */
        VolumePath.Buffer[STANDARD_DRIVE_LETTER_OFFSET] = Drive;
        InitializeObjectAttributes(&ObjectAttributes,
                                   &VolumePath,
                                   OBJ_CASE_INSENSITIVE,
                                   NULL,
                                   NULL);
        Status = NtOpenFile(&VolumeHandle,
                            FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
                            &ObjectAttributes,
                            &IoStatusBlock,
                            FILE_SHARE_READ | FILE_SHARE_WRITE,
                            FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);
        if (!NT_SUCCESS(Status))
        {
            /* Skip the volume if we failed */
            DPRINT1("SMSS:PFILE: Open volume `%wZ' failed with status %X \n",
                    &VolumePath, Status);
            continue;
        }

        /* Now query device information on the volume */
        Status = NtQueryVolumeInformationFile(VolumeHandle,
                                              &IoStatusBlock,
                                              &DeviceInfo,
                                              sizeof(DeviceInfo),
                                              FileFsDeviceInformation);
        if (!NT_SUCCESS(Status))
        {
            /* Move to the next volume if we failed */
            DPRINT1("SMSS:PFILE: Query volume `%wZ' (handle %p) for device info"
                    " failed with status %X \n",
                    &VolumePath,
                    VolumeHandle,
                    Status);
            NtClose(VolumeHandle);
            continue;
        }

        /* Check if this is a fixed disk */
        if (DeviceInfo.Characteristics & (FILE_FLOPPY_DISKETTE |
                                          FILE_READ_ONLY_DEVICE |
                                          FILE_REMOTE_DEVICE |
                                          FILE_REMOVABLE_MEDIA))
        {
            /* It isn't, so skip it */
            DPRINT1("SMSS:PFILE: Volume `%wZ' (%X) cannot store a paging file \n",
                    &VolumePath,
                    DeviceInfo.Characteristics);
            NtClose(VolumeHandle);
            continue;
        }

        /* We found a fixed volume, allocate a descriptor for it */
        Volume = RtlAllocateHeap(RtlGetProcessHeap(),
                                 HEAP_ZERO_MEMORY,
                                 sizeof(SMP_VOLUME_DESCRIPTOR));
        if (!Volume)
        {
            /* Failed to allocate memory, try the next disk */
            DPRINT1("SMSS:PFILE: Failed to allocate a volume descriptor (%u bytes) \n",
                    sizeof(SMP_VOLUME_DESCRIPTOR));
            NtClose(VolumeHandle);
            continue;
        }

        /* Save the drive letter and device information */
        Volume->DriveLetter = Drive;
        Volume->DeviceInfo = DeviceInfo;

        /* Check if this is the boot volume */
        if (RtlUpcaseUnicodeChar(Drive) ==
                RtlUpcaseUnicodeChar(SharedUserData->NtSystemRoot[0]))
        {
            /* Save it */
            ASSERT(BootVolumeFound == FALSE);
            Volume->Flags |= SMP_VOLUME_IS_BOOT;
            BootVolumeFound = TRUE;
        }

        /* Now get size information on the volume */
        Status = NtQueryVolumeInformationFile(VolumeHandle,
                                              &IoStatusBlock,
                                              &SizeInfo,
                                              sizeof(SizeInfo),
                                              FileFsSizeInformation);
        if (!NT_SUCCESS(Status))
        {
            /* We failed -- keep going */
            DPRINT1("SMSS:PFILE: Query volume `%wZ' (handle %p) for size failed"
                    " with status %X \n",
                    &VolumePath,
                    VolumeHandle,
                    Status);
            RtlFreeHeap(RtlGetProcessHeap(), 0, Volume);
            NtClose(VolumeHandle);
            continue;
        }

        /* Done querying volume information, close the handle */
        NtClose(VolumeHandle);

        /* Compute how much free space we have */
        FreeSpace.QuadPart = SizeInfo.AvailableAllocationUnits.QuadPart *
                             SizeInfo.SectorsPerAllocationUnit;
        FinalFreeSpace.QuadPart = FreeSpace.QuadPart * SizeInfo.BytesPerSector;

        /* Check if there's less than 32MB free so we don't starve the disk */
        if (FinalFreeSpace.QuadPart <= MINIMUM_TO_KEEP_FREE)
        {
            /* In this case, act as if there's no free space  */
            Volume->FreeSpace.QuadPart = 0;
        }
        else
        {
            /* Trim off 32MB to give the disk a bit of breathing room */
            Volume->FreeSpace.QuadPart = FinalFreeSpace.QuadPart -
                                         MINIMUM_TO_KEEP_FREE;
        }

        /* All done, add this volume to our descriptor list */
        InsertTailList(&SmpVolumeDescriptorList, &Volume->Entry);
        Volume->Flags |= SMP_VOLUME_INSERTED;
        DPRINT("SMSS:PFILE: Created volume descriptor for`%wZ' \n", &VolumePath);
    }

    /* We must've found at least the boot volume */
    ASSERT(BootVolumeFound == TRUE);
    ASSERT(!IsListEmpty(&SmpVolumeDescriptorList));
    if (!IsListEmpty(&SmpVolumeDescriptorList)) return STATUS_SUCCESS;

    /* Something is really messed up if we found no disks at all */
    return STATUS_UNEXPECTED_IO_ERROR;
}
Example #12
0
/*
 * @implemented
 */
LPVOID
NTAPI
MapViewOfFileEx(HANDLE hFileMappingObject,
                DWORD dwDesiredAccess,
                DWORD dwFileOffsetHigh,
                DWORD dwFileOffsetLow,
                SIZE_T dwNumberOfBytesToMap,
                LPVOID lpBaseAddress)
{
    NTSTATUS Status;
    LARGE_INTEGER SectionOffset;
    SIZE_T ViewSize;
    ULONG Protect;
    LPVOID ViewBase;

    /* Convert the offset */
    SectionOffset.LowPart = dwFileOffsetLow;
    SectionOffset.HighPart = dwFileOffsetHigh;

    /* Save the size and base */
    ViewBase = lpBaseAddress;
    ViewSize = dwNumberOfBytesToMap;

    /* Convert flags to NT Protection Attributes */
    if (dwDesiredAccess == FILE_MAP_COPY)
    {
        Protect = PAGE_WRITECOPY;
    }
    else if (dwDesiredAccess & FILE_MAP_WRITE)
    {
        Protect = (dwDesiredAccess & FILE_MAP_EXECUTE) ?
                   PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
    }
    else if (dwDesiredAccess & FILE_MAP_READ)
    {
        Protect = (dwDesiredAccess & FILE_MAP_EXECUTE) ?
                   PAGE_EXECUTE_READ : PAGE_READONLY;
    }
    else
    {
        Protect = PAGE_NOACCESS;
    }

    /* Map the section */
    Status = NtMapViewOfSection(hFileMappingObject,
                                NtCurrentProcess(),
                                &ViewBase,
                                0,
                                0,
                                &SectionOffset,
                                &ViewSize,
                                ViewShare,
                                0,
                                Protect);
    if (!NT_SUCCESS(Status))
    {
        /* We failed */
        BaseSetLastNTError(Status);
        return NULL;
    }

    /* Return the base */
    return ViewBase;
}
Example #13
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;
}
Example #14
0
/*++
 * @name CsrApiHandleConnectionRequest
 *
 * The CsrApiHandleConnectionRequest routine handles and accepts a new
 * connection request to the CSR API LPC Port.
 *
 * @param ApiMessage
 *        Pointer to the incoming CSR API Message which contains the
 *        connection request.
 *
 * @return STATUS_SUCCESS in case of success, or status code which caused
 *         the routine to error.
 *
 * @remarks This routine is responsible for attaching the Shared Section to
 *          new clients connecting to CSR.
 *
 *--*/
NTSTATUS
NTAPI
CsrApiHandleConnectionRequest(IN PCSR_API_MESSAGE ApiMessage)
{
    PCSR_THREAD CsrThread = NULL;
    PCSR_PROCESS CsrProcess = NULL;
    NTSTATUS Status = STATUS_SUCCESS;
    PCSR_API_CONNECTINFO ConnectInfo = &ApiMessage->ConnectionInfo;
    BOOLEAN AllowConnection = FALSE;
    REMOTE_PORT_VIEW RemotePortView;
    HANDLE ServerPort;

    /* Acquire the Process Lock */
    CsrAcquireProcessLock();

    /* Lookup the CSR Thread */
    CsrThread = CsrLocateThreadByClientId(NULL, &ApiMessage->Header.ClientId);

    /* Check if we have a thread */
    if (CsrThread)
    {
        /* Get the Process */
        CsrProcess = CsrThread->Process;

        /* Make sure we have a Process as well */
        if (CsrProcess)
        {
            /* Reference the Process */
            CsrLockedReferenceProcess(CsrProcess);

            /* Release the lock */
            CsrReleaseProcessLock();

            /* Duplicate the Object Directory */
            Status = NtDuplicateObject(NtCurrentProcess(),
                                       CsrObjectDirectory,
                                       CsrProcess->ProcessHandle,
                                       &ConnectInfo->ObjectDirectory,
                                       0,
                                       0,
                                       DUPLICATE_SAME_ACCESS |
                                       DUPLICATE_SAME_ATTRIBUTES);

            /* Acquire the lock */
            CsrAcquireProcessLock();

            /* Check for success */
            if (NT_SUCCESS(Status))
            {
                /* Attach the Shared Section */
                Status = CsrSrvAttachSharedSection(CsrProcess, ConnectInfo);

                /* Check how this went */
                if (NT_SUCCESS(Status))
                {
                    /* Allow the connection, and return debugging flag */
                    ConnectInfo->DebugFlags = CsrDebug;
                    AllowConnection = TRUE;
                }
            }

            /* Dereference the project */
            CsrLockedDereferenceProcess(CsrProcess);
        }
    }

    /* Release the lock */
    CsrReleaseProcessLock();

    /* Setup the Port View Structure */
    RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
    RemotePortView.ViewSize = 0;
    RemotePortView.ViewBase = NULL;

    /* Save the Process ID */
    ConnectInfo->ServerProcessId = NtCurrentTeb()->ClientId.UniqueProcess;

    /* Accept the Connection */
    Status = NtAcceptConnectPort(&ServerPort,
                                 AllowConnection ? UlongToPtr(CsrProcess->SequenceNumber) : 0,
                                 &ApiMessage->Header,
                                 AllowConnection,
                                 NULL,
                                 &RemotePortView);
    if (!NT_SUCCESS(Status))
    {
         DPRINT1("CSRSS: NtAcceptConnectPort - failed.  Status == %X\n", Status);
    }
    else if (AllowConnection)
    {
        if (CsrDebug & 2)
        {
            DPRINT1("CSRSS: ClientId: %lx.%lx has ClientView: Base=%p, Size=%lx\n",
                    ApiMessage->Header.ClientId.UniqueProcess,
                    ApiMessage->Header.ClientId.UniqueThread,
                    RemotePortView.ViewBase,
                    RemotePortView.ViewSize);
        }

        /* Set some Port Data in the Process */
        CsrProcess->ClientPort = ServerPort;
        CsrProcess->ClientViewBase = (ULONG_PTR)RemotePortView.ViewBase;
        CsrProcess->ClientViewBounds = (ULONG_PTR)((ULONG_PTR)RemotePortView.ViewBase +
                                                   (ULONG_PTR)RemotePortView.ViewSize);

        /* Complete the connection */
        Status = NtCompleteConnectPort(ServerPort);
        if (!NT_SUCCESS(Status))
        {
            DPRINT1("CSRSS: NtCompleteConnectPort - failed.  Status == %X\n", Status);
        }
    }
    else
    {
        DPRINT1("CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n",
                ApiMessage->Header.ClientId.UniqueProcess,
                ApiMessage->Header.ClientId.UniqueThread);
    }

    /* Return status to caller */
    return Status;
}
Example #15
0
NTSTATUS
NTAPI
SmpExecPgm(IN PSM_API_MSG SmApiMsg,
           IN PSMP_CLIENT_CONTEXT ClientContext,
           IN HANDLE SmApiPort)
{
    HANDLE ProcessHandle;
    NTSTATUS Status;
    PSM_EXEC_PGM_MSG SmExecPgm;
    RTL_USER_PROCESS_INFORMATION ProcessInformation;
    OBJECT_ATTRIBUTES ObjectAttributes;

    /* Open the client process */
    InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
    Status = NtOpenProcess(&ProcessHandle,
                           PROCESS_DUP_HANDLE,
                           &ObjectAttributes,
                           &SmApiMsg->h.ClientId);
    if (!NT_SUCCESS(Status))
    {
        /* Fail */
        DPRINT1("SmExecPgm: NtOpenProcess Failed %lx\n", Status);
        return Status;
    }

    /* Copy the process information out of the message */
    SmExecPgm = &SmApiMsg->u.ExecPgm;
    ProcessInformation = SmExecPgm->ProcessInformation;

    /* Duplicate the process handle */
    Status = NtDuplicateObject(ProcessHandle,
                               SmExecPgm->ProcessInformation.ProcessHandle,
                               NtCurrentProcess(),
                               &ProcessInformation.ProcessHandle,
                               PROCESS_ALL_ACCESS,
                               0,
                               0);
    if (!NT_SUCCESS(Status))
    {
        /* Close the handle and fail */
        NtClose(ProcessHandle);
        DPRINT1("SmExecPgm: NtDuplicateObject (Process) Failed %lx\n", Status);
        return Status;
    }

    /* Duplicate the thread handle */
    Status = NtDuplicateObject(ProcessHandle,
                               SmExecPgm->ProcessInformation.ThreadHandle,
                               NtCurrentProcess(),
                               &ProcessInformation.ThreadHandle,
                               THREAD_ALL_ACCESS,
                               0,
                               0);
    if (!NT_SUCCESS(Status))
    {
        /* Close both handles and fail */
        NtClose(ProcessInformation.ProcessHandle);
        NtClose(ProcessHandle);
        DPRINT1("SmExecPgm: NtDuplicateObject (Thread) Failed %lx\n", Status);
        return Status;
    }

    /* Close the process handle and call the internal client API */
    NtClose(ProcessHandle);
    return SmpSbCreateSession(NULL,
                              NULL,
                              &ProcessInformation,
                              0,
                              SmExecPgm->DebugFlag ? &SmApiMsg->h.ClientId : NULL);
}
Example #16
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");

}
Example #17
0
/**
 * Gets information for a handle.
 *
 * \param ProcessHandle A handle to the process in which the
 * handle resides.
 * \param Handle The handle value.
 * \param ObjectTypeNumber The object type number of the handle.
 * You can specify -1 for this parameter if the object type number
 * is not known.
 * \param Flags Reserved.
 * \param SubStatus A variable which receives the NTSTATUS value of
 * the last component that fails. If all operations succeed, the
 * value will be STATUS_SUCCESS. If the function returns an error
 * status, this variable is not set.
 * \param BasicInformation A variable which receives basic
 * information about the object.
 * \param TypeName A variable which receives the object type name.
 * \param ObjectName A variable which receives the object name.
 * \param BestObjectName A variable which receives the formatted
 * object name.
 * \param ExtraInformation Reserved.
 *
 * \retval STATUS_INVALID_HANDLE The handle specified in
 * \c ProcessHandle or \c Handle is invalid.
 * \retval STATUS_INVALID_PARAMETER_3 The value specified in
 * \c ObjectTypeNumber is invalid.
 *
 * \remarks If \a BasicInformation or \a TypeName are specified,
 * the function will fail if either cannot be queried. \a ObjectName,
 * \a BestObjectName and \a ExtraInformation will return NULL if they
 * cannot be queried.
 */
NTSTATUS PhGetHandleInformationEx(
    __in HANDLE ProcessHandle,
    __in HANDLE Handle,
    __in ULONG ObjectTypeNumber,
    __reserved ULONG Flags,
    __out_opt PNTSTATUS SubStatus,
    __out_opt POBJECT_BASIC_INFORMATION BasicInformation,
    __out_opt PPH_STRING *TypeName,
    __out_opt PPH_STRING *ObjectName,
    __out_opt PPH_STRING *BestObjectName,
    __reserved PVOID *ExtraInformation
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    NTSTATUS subStatus = STATUS_SUCCESS;
    HANDLE dupHandle = NULL;
    PPH_STRING typeName = NULL;
    PPH_STRING objectName = NULL;
    PPH_STRING bestObjectName = NULL;

    if (Handle == NULL || Handle == NtCurrentProcess() || Handle == NtCurrentThread())
        return STATUS_INVALID_HANDLE;
    if (ObjectTypeNumber != -1 && ObjectTypeNumber >= MAX_OBJECT_TYPE_NUMBER)
        return STATUS_INVALID_PARAMETER_3;

    // Duplicate the handle if we're not using KPH.
    if (!KphIsConnected())
    {
        // However, we obviously don't need to duplicate it
        // if the handle is in the current process.
        if (ProcessHandle != NtCurrentProcess())
        {
            status = NtDuplicateObject(
                ProcessHandle,
                Handle,
                NtCurrentProcess(),
                &dupHandle,
                0,
                0,
                0
                );

            if (!NT_SUCCESS(status))
                return status;
        }
        else
        {
            dupHandle = Handle;
        }
    }

    // Get basic information.
    if (BasicInformation)
    {
        status = PhpGetObjectBasicInformation(
            ProcessHandle,
            KphIsConnected() ? Handle : dupHandle,
            BasicInformation
            );

        if (!NT_SUCCESS(status))
            goto CleanupExit;
    }

    // Exit early if we don't need to get any other information.
    if (!TypeName && !ObjectName && !BestObjectName)
        goto CleanupExit;

    // Get the type name.
    status = PhpGetObjectTypeName(
        ProcessHandle,
        KphIsConnected() ? Handle : dupHandle,
        ObjectTypeNumber,
        &typeName
        );

    if (!NT_SUCCESS(status))
        goto CleanupExit;

    // Exit early if we don't need to get the object name.
    if (!ObjectName && !BestObjectName)
        goto CleanupExit;

    // Get the object name.
    // If we're dealing with a file handle we must take
    // special precautions so we don't hang.
    if (PhEqualString2(typeName, L"File", TRUE) && !KphIsConnected())
    {
        // 0: Query normally.
        // 1: Hack.
        // 2: Fail.
        ULONG hackLevel = 1;

        // We can't use the hack on XP because hanging threads
        // can't even be terminated!
        if (WindowsVersion <= WINDOWS_XP)
            hackLevel = 2;

        if (hackLevel == 0)
        {
            status = PhpGetObjectName(
                ProcessHandle,
                KphIsConnected() ? Handle : dupHandle,
                &objectName
                );
        }
        else if (hackLevel == 1)
        {
            POBJECT_NAME_INFORMATION buffer;

            buffer = PhAllocate(0x800);

            status = PhQueryObjectNameHack(
                dupHandle,
                buffer,
                0x800,
                NULL
                );

            if (NT_SUCCESS(status))
                objectName = PhCreateStringEx(buffer->Name.Buffer, buffer->Name.Length);

            PhFree(buffer);
        }
        else
        {
            // Pretend the file object has no name.
            objectName = PhReferenceEmptyString();
            status = STATUS_SUCCESS;
        }
    }
    else
    {
        // Query the object normally.
        status = PhpGetObjectName(
            ProcessHandle,
            KphIsConnected() ? Handle : dupHandle,
            &objectName
            );
    }

    if (!NT_SUCCESS(status))
    {
        subStatus = status;
        status = STATUS_SUCCESS;
        goto CleanupExit;
    }

    // Exit early if we don't need to get the best object name.
    if (!BestObjectName)
        goto CleanupExit;

    status = PhpGetBestObjectName(
        ProcessHandle,
        Handle,
        objectName,
        typeName,
        &bestObjectName
        );

    if (!NT_SUCCESS(status))
    {
        subStatus = status;
        status = STATUS_SUCCESS;
        goto CleanupExit;
    }

CleanupExit:

    if (NT_SUCCESS(status))
    {
        if (SubStatus)
        {
            *SubStatus = subStatus;
        }

        if (TypeName && typeName)
        {
            *TypeName = typeName;
            PhReferenceObject(typeName);
        }

        if (ObjectName && objectName)
        {
            *ObjectName = objectName;
            PhReferenceObject(objectName);
        }

        if (BestObjectName && bestObjectName)
        {
            *BestObjectName = bestObjectName;
            PhReferenceObject(bestObjectName);
        }
    }

    if (dupHandle && ProcessHandle != NtCurrentProcess())
        NtClose(dupHandle);
    if (typeName)
        PhDereferenceObject(typeName);
    if (objectName)
        PhDereferenceObject(objectName);
    if (bestObjectName)
        PhDereferenceObject(bestObjectName);

    return status;
}
Example #18
0
void console_init()
{
	log_info("Initializing console shared memory region.\n");
	/* TODO: mm_mmap() does not support MAP_SHARED yet */
	HANDLE section;
	LARGE_INTEGER section_size;
	section_size.QuadPart = sizeof(struct console_data);
	OBJECT_ATTRIBUTES obj_attr;
	obj_attr.Length = sizeof(OBJECT_ATTRIBUTES);
	obj_attr.RootDirectory = NULL;
	obj_attr.ObjectName = NULL;
	obj_attr.Attributes = OBJ_INHERIT;
	obj_attr.SecurityDescriptor = NULL;
	obj_attr.SecurityQualityOfService = NULL;
	NTSTATUS status;
	status = NtCreateSection(&section, SECTION_MAP_READ | SECTION_MAP_WRITE, &obj_attr, &section_size, PAGE_READWRITE, SEC_COMMIT, NULL);
	if (!NT_SUCCESS(status))
	{
		log_error("NtCreateSection() failed, status: %x\n", status);
		return;
	}
	PVOID base_addr = NULL;
	SIZE_T view_size = sizeof(struct console_data);
	status = NtMapViewOfSection(section, NtCurrentProcess(), &base_addr, 0, sizeof(struct console_data), NULL, &view_size, ViewUnmap, MEM_TOP_DOWN, PAGE_READWRITE);
	if (!NT_SUCCESS(status))
	{
		log_error("NtMapViewOfSection() failed, status: %x\n", status);
		return;
	}
	console = (struct console_data *)base_addr;

	SECURITY_ATTRIBUTES attr;
	attr.nLength = sizeof(SECURITY_ATTRIBUTES);
	attr.lpSecurityDescriptor = NULL;
	attr.bInheritHandle = TRUE;

	HANDLE mutex = CreateMutexW(&attr, FALSE, NULL);
	if (mutex == NULL)
	{
		log_error("CreateMutexW() failed, error code: %d\n", GetLastError());
		return;
	}

	HANDLE in = CreateFileA("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &attr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (in == INVALID_HANDLE_VALUE)
	{
		log_error("CreateFile(\"CONIN$\") failed, error code: %d\n", GetLastError());
		return;
	}
	HANDLE out = CreateFileA("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &attr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (out == INVALID_HANDLE_VALUE)
	{
		log_error("CreateFile(\"CONOUT$\") failed, error code: %d\n", GetLastError());
		return;
	}
	console->section = section;
	console->mutex = mutex;
	console->in = in;
	console->out = out;
	console->normal_buffer = out;
	console->alternate_buffer = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &attr, CONSOLE_TEXTMODE_BUFFER, NULL);
	console->termios.c_iflag = INLCR | ICRNL;
	console->termios.c_oflag = ONLCR | OPOST;
	console->termios.c_cflag = CREAD | CSIZE | B38400;
	console->termios.c_lflag = ICANON | ECHO | ECHOCTL;
	memset(console->termios.c_cc, 0, sizeof(console->termios.c_cc));
	console->termios.c_cc[VINTR] = 3;
	console->termios.c_cc[VERASE] = 8;
	console->termios.c_cc[VEOF] = 4;
	console->termios.c_cc[VSUSP] = 26;

	console->bright = 0;
	console->reverse = 0;
	console->foreground = 7;
	console->background = 0;
	console->g0_charset = console->g1_charset = default_charset;
	console->charset = 0;
	console->insert_mode = 0;
	console->cursor_key_mode = 0;
	console->origin_mode = 0;
	console->wraparound_mode = 1;

	/* Only essential values are initialized here, others are automatically set to the correct value in console_retrieve_state() */
	console->at_right_margin = 0;
	console->top = 0;
	console->scroll_full_screen = 1;
	console->utf8_buf_size = 0;

	save_cursor();

	console->input_buffer_head = console->input_buffer_tail = 0;
	console->processor = NULL;

	SetConsoleMode(in, ENABLE_PROCESSED_INPUT | ENABLE_WINDOW_INPUT);
	SetConsoleMode(out, ENABLE_PROCESSED_OUTPUT);
	SetConsoleCtrlHandler(console_ctrlc_handler, TRUE);

	log_info("Console shared memory region successfully initialized.\n");
}
Example #19
0
BOOLEAN WepOpenServerObjects(
    VOID
    )
{
    OBJECT_ATTRIBUTES objectAttributes;
    WCHAR buffer[256];
    UNICODE_STRING objectName;

    if (!WeServerSharedSection)
    {
        WeFormatLocalObjectName(WE_SERVER_SHARED_SECTION_NAME, buffer, &objectName);
        InitializeObjectAttributes(&objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL);

        if (!NT_SUCCESS(NtOpenSection(
            &WeServerSharedSection,
            SECTION_ALL_ACCESS,
            &objectAttributes
            )))
        {
            return FALSE;
        }
    }

    if (!WeServerSharedData)
    {
        PVOID viewBase;
        SIZE_T viewSize;

        viewBase = NULL;
        viewSize = sizeof(WE_HOOK_SHARED_DATA);

        if (!NT_SUCCESS(NtMapViewOfSection(
            WeServerSharedSection,
            NtCurrentProcess(),
            &viewBase,
            0,
            0,
            NULL,
            &viewSize,
            ViewShare,
            0,
            PAGE_READWRITE
            )))
        {
            WepCloseServerObjects();
            return FALSE;
        }

        WeServerSharedData = viewBase;
    }

    if (!WeServerSharedSectionLock)
    {
        WeFormatLocalObjectName(WE_SERVER_SHARED_SECTION_LOCK_NAME, buffer, &objectName);
        InitializeObjectAttributes(&objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL);

        if (!NT_SUCCESS(NtOpenMutant(
            &WeServerSharedSectionLock,
            MUTANT_ALL_ACCESS,
            &objectAttributes
            )))
        {
            WepCloseServerObjects();
            return FALSE;
        }
    }

    if (!WeServerSharedSectionEvent)
    {
        WeFormatLocalObjectName(WE_SERVER_SHARED_SECTION_EVENT_NAME, buffer, &objectName);
        InitializeObjectAttributes(&objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL);

        if (!NT_SUCCESS(NtOpenEvent(
            &WeServerSharedSectionEvent,
            EVENT_ALL_ACCESS,
            &objectAttributes
            )))
        {
            WepCloseServerObjects();
            return FALSE;
        }
    }

    return TRUE;
}
Example #20
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 );
}
Example #21
0
VOID
PropertiesDlgShow(
    IN PCONSOLE_INFORMATION Console
    )

/*++

    Displays the properties dialog and updates the window state,
    if necessary.

--*/

{
    HANDLE hSection = NULL;
    HANDLE hClientSection = NULL;
    HANDLE hThread;
    ULONG ulViewSize;
    LARGE_INTEGER li;
    NTSTATUS Status;
    PCONSOLE_STATE_INFO pStateInfo;
    PCONSOLE_PROCESS_HANDLE ProcessHandleRecord;
    PSCREEN_INFORMATION ScreenInfo;
    LPTHREAD_START_ROUTINE MyPropRoutine;

    /*
     * Create a shared memory block.
     */
    li.QuadPart = sizeof(CONSOLE_STATE_INFO) + Console->OriginalTitleLength;
    Status = NtCreateSection(&hSection,
                             SECTION_ALL_ACCESS,
                             NULL,
                             &li,
                             PAGE_READWRITE,
                             SEC_COMMIT,
                             NULL);
    if (!NT_SUCCESS(Status)) {
        KdPrint(("CONSRV: error %x creating file mapping\n", Status));
        return;
    }

    /*
     * Get a pointer to the shared memory block.
     */
    pStateInfo = NULL;
    ulViewSize = 0;
    Status = NtMapViewOfSection(hSection,
                                NtCurrentProcess(),
                                &pStateInfo,
                                0,
                                0,
                                NULL,
                                &ulViewSize,
                                ViewUnmap,
                                0,
                                PAGE_READWRITE);
    if (!NT_SUCCESS(Status)) {
        KdPrint(("CONSRV: error %x mapping view of file\n", Status));
        NtClose(hSection);
        return;
    }

    /*
     * Fill in the shared memory block with the current values.
     */
    ScreenInfo = Console->CurrentScreenBuffer;
    pStateInfo->Length = li.LowPart;
    pStateInfo->ScreenBufferSize = ScreenInfo->ScreenBufferSize;
    pStateInfo->WindowSize.X = CONSOLE_WINDOW_SIZE_X(ScreenInfo);
    pStateInfo->WindowSize.Y = CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
    pStateInfo->WindowPosX = Console->WindowRect.left;
    pStateInfo->WindowPosY = Console->WindowRect.top;
    if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
        pStateInfo->FontSize = SCR_FONTSIZE(ScreenInfo);
        pStateInfo->FontFamily = SCR_FAMILY(ScreenInfo);
        pStateInfo->FontWeight = SCR_FONTWEIGHT(ScreenInfo);
        wcscpy(pStateInfo->FaceName, SCR_FACENAME(ScreenInfo));
        pStateInfo->CursorSize = ScreenInfo->BufferInfo.TextInfo.CursorSize;
    }
    pStateInfo->FullScreen = Console->FullScreenFlags & CONSOLE_FULLSCREEN;
    pStateInfo->QuickEdit = Console->Flags & CONSOLE_QUICK_EDIT_MODE;
    pStateInfo->AutoPosition = Console->Flags & CONSOLE_AUTO_POSITION;
    pStateInfo->InsertMode = Console->InsertMode;
    pStateInfo->ScreenAttributes = ScreenInfo->Attributes;
    pStateInfo->PopupAttributes = ScreenInfo->PopupAttributes;
    pStateInfo->HistoryBufferSize = Console->CommandHistorySize;
    pStateInfo->NumberOfHistoryBuffers = Console->MaxCommandHistories;
    pStateInfo->HistoryNoDup = Console->Flags & CONSOLE_HISTORY_NODUP;
    RtlCopyMemory(pStateInfo->ColorTable,
                  Console->ColorTable,
                  sizeof(Console->ColorTable));
    pStateInfo->hWnd = Console->hWnd;
    wcscpy(pStateInfo->ConsoleTitle, Console->OriginalTitle);
    NtUnmapViewOfSection(NtCurrentProcess(), pStateInfo);

    /*
     * Map the shared memory block handle into the client side process's
     * address space.
     */
    ProcessHandleRecord = CONTAINING_RECORD(Console->ProcessHandleList.Blink,
                                            CONSOLE_PROCESS_HANDLE,
                                            ListLink);
    Status = NtDuplicateObject(NtCurrentProcess(),
                               hSection,
                               ProcessHandleRecord->ProcessHandle,
                               &hClientSection,
                               0,
                               0,
                               DUPLICATE_SAME_ACCESS);
    if (!NT_SUCCESS(Status)) {
        KdPrint(("CONSRV: error %x mapping handle to client\n", Status));
        NtClose(hSection);
        return;
    }

    /*
     * Get a pointer to the client-side properties routine.
     */
    if (ProcessHandleRecord->PropRoutine) {
        MyPropRoutine = ProcessHandleRecord->PropRoutine;
    } else {
        MyPropRoutine = PropRoutine;
    }

    /*
     * Call back into the client process to spawn the properties dialog.
     */
    UnlockConsole(Console);
    hThread = InternalCreateCallbackThread(ProcessHandleRecord->ProcessHandle,
                                           (DWORD)MyPropRoutine,
                                           (DWORD)hClientSection);
    if (!hThread) {
        KdPrint(("CONSRV: CreateRemoteThread failed %d\n", GetLastError()));
    }
    LockConsole(Console);

    /*
     * Close any open handles and free allocated memory.
     */
    if (hThread)
        NtClose(hThread);
    if (hSection)
        NtClose(hSection);

    return;
}
Example #22
0
ULONG
BaseSrvDebugProcess(
    IN OUT PCSR_API_MSG m,
    IN OUT PCSR_REPLY_STATUS ReplyStatus
    )
{
    NTSTATUS Status;
    PBASE_DEBUGPROCESS_MSG a = (PBASE_DEBUGPROCESS_MSG)&m->u.ApiMessageData;
    HANDLE Thread,ProcessHandle,Token;
    PCSR_PROCESS Process;
    DWORD ThreadId;
    PTOKEN_DEFAULT_DACL lpDefaultDacl;
    TOKEN_DEFAULT_DACL DefaultDacl;
    ULONG DaclLength;
    SECURITY_ATTRIBUTES ThreadAttributes;
    SECURITY_DESCRIPTOR SecurityDescriptor;
    UNICODE_STRING ModuleNameString_U;
    PVOID ModuleHandle;
    STRING ProcedureNameString;
    PCREATE_REMOTE_THREAD CreateRemoteThreadRoutine;


    if (a->dwProcessId == -1 && a->AttachCompleteRoutine == NULL) {
        HANDLE DebugPort;

        DebugPort = (HANDLE)NULL;
        Status = NtQueryInformationProcess(
                    NtCurrentProcess(),
                    ProcessDebugPort,
                    (PVOID)&DebugPort,
                    sizeof(DebugPort),
                    NULL
                    );

        if ( NT_SUCCESS(Status) && DebugPort ) {
            return (ULONG)STATUS_ACCESS_DENIED;
            }

        return STATUS_SUCCESS;
        }
#if DEVL
    if (a->dwProcessId != -1) {
#endif // DEVL
        if ( a->AttachCompleteRoutine == NULL ) {
            Status = CsrLockProcessByClientId((HANDLE)a->dwProcessId,&Process);
            if ( NT_SUCCESS(Status) ) {

                ProcessHandle = Process->ProcessHandle;
                Status = NtOpenProcessToken(ProcessHandle,
                                            TOKEN_QUERY,
                                            &Token
                                           );
                if ( !NT_SUCCESS(Status) ) {
                    CsrUnlockProcess(Process);
                    return Status;
                    }
                lpDefaultDacl = &DefaultDacl;
                Status = NtQueryInformationToken(Token,
                                                 TokenDefaultDacl,
                                                 lpDefaultDacl,
                                                 sizeof(DefaultDacl),
                                                 &DaclLength
                                                );
                if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) {
                    Status = STATUS_ACCESS_DENIED;
                    }
                else {
                    Status = STATUS_SUCCESS;
                    }

                if ( Process->DebugUserInterface.UniqueProcess ||
                     Process->DebugUserInterface.UniqueThread ) {
                    Status = STATUS_ACCESS_DENIED;
                    }

                NtClose(Token);
                CsrUnlockProcess(Process);
                }
                return (ULONG)Status;
            }

        //
        // Can't call base, but I know it is there
        //

        RtlInitUnicodeString( &ModuleNameString_U, L"kernel32" );
        Status = LdrLoadDll( UNICODE_NULL, NULL, &ModuleNameString_U, &ModuleHandle );
        if ( !NT_SUCCESS(Status) ) {
            return (ULONG)Status;
            }
        RtlInitString( &ProcedureNameString, "CreateRemoteThread" );
        Status = LdrGetProcedureAddress( ModuleHandle,
                                         &ProcedureNameString,
                                         (ULONG) NULL,
                                         (PVOID *) &CreateRemoteThreadRoutine
                                       );
        if ( !NT_SUCCESS(Status) ) {
            LdrUnloadDll( ModuleHandle );
            return (ULONG)Status;
            }

        Status = CsrLockProcessByClientId((HANDLE)a->dwProcessId,&Process);
        if ( NT_SUCCESS(Status) ) {

            ProcessHandle = Process->ProcessHandle;
            Status = NtOpenProcessToken(ProcessHandle,
                                        TOKEN_QUERY,
                                        &Token
                                       );
            if (!NT_SUCCESS(Status)) {
                CsrUnlockProcess(Process);
                LdrUnloadDll( ModuleHandle );
                return (ULONG)Status;
                }

            lpDefaultDacl = &DefaultDacl;
            Status = NtQueryInformationToken(Token,
                                             TokenDefaultDacl,
                                             lpDefaultDacl,
                                             sizeof(DefaultDacl),
                                             &DaclLength
                                            );
            if (!NT_SUCCESS(Status)) {
                lpDefaultDacl = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), DaclLength);
                if (lpDefaultDacl) {
                    Status = NtQueryInformationToken(Token,
                                                     TokenDefaultDacl,
                                                     lpDefaultDacl,
                                                     DaclLength,
                                                     &DaclLength
                                                    );
                    }
                else {
                    Status = STATUS_NO_MEMORY;
                    }
                NtClose(Token);
                if (!NT_SUCCESS(Status)) {
                    CsrUnlockProcess(Process);
                    LdrUnloadDll( ModuleHandle );
                    return (ULONG)Status;
                    }
                }
            else {
                NtClose(Token);
                }

            ThreadAttributes.nLength = sizeof(ThreadAttributes);
            RtlCreateSecurityDescriptor(&SecurityDescriptor,SECURITY_DESCRIPTOR_REVISION1);
            ThreadAttributes.lpSecurityDescriptor = &SecurityDescriptor;
            SecurityDescriptor.Control = SE_DACL_PRESENT;
            SecurityDescriptor.Dacl = lpDefaultDacl->DefaultDacl;
            ThreadAttributes.bInheritHandle = FALSE;

            CsrUnlockProcess(Process);
            }
#if DEVL
        }
#endif // DEVL

    //
    // Set up the specified user-interface as the debugger of the
    // target process. Whip through the target process and
    // suspend all threads. Then Send CreateProcess, LoadModule, and
    // CreateThread Messages. Finally send the attach complete
    // exception.
    //

    Status = CsrDebugProcess(
                a->dwProcessId,
                &a->DebuggerClientId,
                (PCSR_ATTACH_COMPLETE_ROUTINE)a->AttachCompleteRoutine
                );
#if DEVL
    if (a->dwProcessId != -1) {
#endif // DEVL
        if ( NT_SUCCESS(Status) ) {
            Thread = (PVOID)(CreateRemoteThreadRoutine)(ProcessHandle,
                                        &ThreadAttributes,
                                        0L,
                                        (LPTHREAD_START_ROUTINE)a->AttachCompleteRoutine,
                                        0,
                                        0,
                                        &ThreadId
                                        );
            LdrUnloadDll( ModuleHandle );
            if ( lpDefaultDacl != &DefaultDacl ) {
                RtlFreeHeap(RtlProcessHeap(), 0,lpDefaultDacl);
                }
            if ( !Thread ) {
                return (ULONG)STATUS_UNSUCCESSFUL;
                }
            NtClose(Thread);
            }
#if DEVL
        }
#endif // DEVL
    return (ULONG) Status;
}
Example #23
0
/**************************************************************************
 *	RtlpAllocateSomeHandles   (internal)
 *
 * Reserves memory for the handles if not previously done and commits memory
 * for a batch of handles if none are free and adds them to the free list.
 *
 * PARAMS
 *  HandleTable    [I/O] The handle table.
 *
 * RETURNS
 *  NTSTATUS code.
 */
static NTSTATUS RtlpAllocateSomeHandles(RTL_HANDLE_TABLE * HandleTable)
{
    NTSTATUS status;
    if (!HandleTable->FirstHandle)
    {
        PVOID FirstHandleAddr = NULL;
        SIZE_T MaxSize = HandleTable->MaxHandleCount * HandleTable->HandleSize;

        /* reserve memory for the handles, but don't commit it yet because we
         * probably won't use most of it and it will use up physical memory */
        status = NtAllocateVirtualMemory(
            NtCurrentProcess(),
            &FirstHandleAddr,
            0,
            &MaxSize,
            MEM_RESERVE,
            PAGE_READWRITE);
        if (status != STATUS_SUCCESS)
            return status;
        HandleTable->FirstHandle = FirstHandleAddr;
        HandleTable->ReservedMemory = HandleTable->FirstHandle;
        HandleTable->MaxHandle = (char *)HandleTable->FirstHandle + MaxSize;
    }
    if (!HandleTable->NextFree)
    {
        SIZE_T Offset, CommitSize = 4096; /* one page */
        RTL_HANDLE * FreeHandle = NULL;
        PVOID NextAvailAddr = HandleTable->ReservedMemory;

        if (HandleTable->ReservedMemory >= HandleTable->MaxHandle)
            return STATUS_NO_MEMORY; /* the handle table is completely full */

        status = NtAllocateVirtualMemory(
            NtCurrentProcess(),
            &NextAvailAddr,
            0,
            &CommitSize,
            MEM_COMMIT,
            PAGE_READWRITE);
        if (status != STATUS_SUCCESS)
            return status;

        for (Offset = 0; Offset < CommitSize; Offset += HandleTable->HandleSize)
        {
            /* make sure we don't go over handle limit, even if we can
             * because of rounding of the table size up to the next page
             * boundary */
            if ((char *)HandleTable->ReservedMemory + Offset >= (char *)HandleTable->MaxHandle)
                break;

            FreeHandle = (RTL_HANDLE *)((char *)HandleTable->ReservedMemory + Offset);

            FreeHandle->Next = (RTL_HANDLE *)((char *)HandleTable->ReservedMemory + 
                Offset + HandleTable->HandleSize);
        }

        /* shouldn't happen because we already test for this above, but
         * handle it just in case */
        if (!FreeHandle)
            return STATUS_NO_MEMORY;

        /* set the last handle's Next pointer to NULL so that when we run
         * out of free handles we trigger another commit of memory and
         * initialize the free pointers */
        FreeHandle->Next = NULL;

        HandleTable->NextFree = HandleTable->ReservedMemory;

        HandleTable->ReservedMemory = (char *)HandleTable->ReservedMemory + CommitSize;
    }
    return STATUS_SUCCESS;
}
Example #24
0
static NTSTATUS NTAPI TerminatorM1(
    _In_ HANDLE ProcessId
    )
{
    NTSTATUS status;
    HANDLE processHandle;

    if (NT_SUCCESS(status = PhOpenProcess(
        &processHandle,
        PROCESS_QUERY_INFORMATION | PROCESS_VM_WRITE,
        ProcessId
        )))
    {
        PVOID pageOfGarbage;
        SIZE_T pageSize;
        PVOID baseAddress;
        MEMORY_BASIC_INFORMATION basicInfo;

        pageOfGarbage = NULL;
        pageSize = PAGE_SIZE;

        if (!NT_SUCCESS(NtAllocateVirtualMemory(
            NtCurrentProcess(),
            &pageOfGarbage,
            0,
            &pageSize,
            MEM_COMMIT,
            PAGE_READONLY
            )))
        {
            NtClose(processHandle);
            return STATUS_NO_MEMORY;
        }

        baseAddress = (PVOID)0;

        while (NT_SUCCESS(NtQueryVirtualMemory(
            processHandle,
            baseAddress,
            MemoryBasicInformation,
            &basicInfo,
            sizeof(MEMORY_BASIC_INFORMATION),
            NULL
            )))
        {
            ULONG i;

            // Make sure we don't write to views of mapped files. That
            // could possibly corrupt files!
            if (basicInfo.Type == MEM_PRIVATE)
            {
                for (i = 0; i < basicInfo.RegionSize; i += PAGE_SIZE)
                {
                    PhWriteVirtualMemory(
                        processHandle,
                        PTR_ADD_OFFSET(baseAddress, i),
                        pageOfGarbage,
                        PAGE_SIZE,
                        NULL
                        );
                }
            }

            baseAddress = PTR_ADD_OFFSET(baseAddress, basicInfo.RegionSize);
        }

        // Size needs to be zero if we're freeing.
        pageSize = 0;
        NtFreeVirtualMemory(
            NtCurrentProcess(),
            &pageOfGarbage,
            &pageSize,
            MEM_RELEASE
            );

        NtClose(processHandle);
    }

    return status;
}
Example #25
0
NTSTATUS
NtFreeVirtualMemory(
    __in HANDLE ProcessHandle,
    __inout PVOID *BaseAddress,
    __inout PSIZE_T RegionSize,
    __in ULONG FreeType
)

/*++

Routine Description:

    This function deletes a region of pages within the virtual address
    space of a subject process.

Arguments:

    ProcessHandle - An open handle to a process object.

    BaseAddress - The base address of the region of pages
                  to be freed. This value is rounded down to the
                  next host page address boundary.

    RegionSize - A pointer to a variable that will receive
                 the actual size in bytes of the freed region of
                 pages. The initial value of this argument is
                 rounded up to the next host page size boundary.

    FreeType - A set of flags that describe the type of
               free that is to be performed for the specified
               region of pages.

       FreeType Flags

        MEM_DECOMMIT - The specified region of pages is to be decommitted.

        MEM_RELEASE - The specified region of pages is to be released.

Return Value:

    NTSTATUS.

--*/

{
    KAPC_STATE ApcState;
    PMMVAD_SHORT Vad;
    PMMVAD_SHORT NewVad;
    PMMVAD PreviousVad;
    PMMVAD NextVad;
    PMMVAD ChargedVad;
    PEPROCESS Process;
    KPROCESSOR_MODE PreviousMode;
    PVOID StartingAddress;
    PVOID EndingAddress;
    NTSTATUS Status;
    LOGICAL Attached;
    SIZE_T CapturedRegionSize;
    PVOID CapturedBase;
    PMMPTE StartingPte;
    PMMPTE EndingPte;
    SIZE_T OldQuota;
    SIZE_T QuotaCharge;
    SIZE_T CommitReduction;
    LOGICAL UserPhysicalPages;
    PETHREAD CurrentThread;
    PEPROCESS CurrentProcess;

    PAGED_CODE();

    //
    // Check to make sure FreeType is good.
    //

    if ((FreeType & ~(MEM_DECOMMIT | MEM_RELEASE)) != 0) {
        return STATUS_INVALID_PARAMETER_4;
    }

    //
    // One of MEM_DECOMMIT or MEM_RELEASE must be specified, but not both.
    //

    if (((FreeType & (MEM_DECOMMIT | MEM_RELEASE)) == 0) ||
            ((FreeType & (MEM_DECOMMIT | MEM_RELEASE)) ==
             (MEM_DECOMMIT | MEM_RELEASE))) {
        return STATUS_INVALID_PARAMETER_4;
    }
    CurrentThread = PsGetCurrentThread ();

    CurrentProcess = PsGetCurrentProcessByThread (CurrentThread);

    PreviousMode = KeGetPreviousModeByThread(&CurrentThread->Tcb);

    //
    // Establish an exception handler, probe the specified addresses
    // for write access and capture the initial values.
    //

    try {

        if (PreviousMode != KernelMode) {

            ProbeForWritePointer (BaseAddress);
            ProbeForWriteUlong_ptr (RegionSize);
        }

        //
        // Capture the base address.
        //

        CapturedBase = *BaseAddress;

        //
        // Capture the region size.
        //

        CapturedRegionSize = *RegionSize;

    }
    except (ExSystemExceptionFilter ()) {

        //
        // If an exception occurs during the probe or capture
        // of the initial values, then handle the exception and
        // return the exception code as the status value.
        //

        return GetExceptionCode ();
    }

    //
    // Make sure the specified starting and ending addresses are
    // within the user part of the virtual address space.
    //

    if (CapturedBase > MM_HIGHEST_USER_ADDRESS) {

        //
        // Invalid base address.
        //

        return STATUS_INVALID_PARAMETER_2;
    }

    if ((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (ULONG_PTR)CapturedBase <
            CapturedRegionSize) {

        //
        // Invalid region size;
        //

        return STATUS_INVALID_PARAMETER_3;

    }

    EndingAddress = (PVOID)(((LONG_PTR)CapturedBase + CapturedRegionSize - 1) |
                            (PAGE_SIZE - 1));

    StartingAddress = PAGE_ALIGN(CapturedBase);

    Attached = FALSE;

    if (ProcessHandle == NtCurrentProcess()) {
        Process = CurrentProcess;
    }
    else {

        //
        // Reference the specified process handle for VM_OPERATION access.
        //

        Status = ObReferenceObjectByHandle (ProcessHandle,
                                            PROCESS_VM_OPERATION,
                                            PsProcessType,
                                            PreviousMode,
                                            (PVOID *)&Process,
                                            NULL);

        if (!NT_SUCCESS(Status)) {
            return Status;
        }

        //
        // If the specified process is not the current process, attach
        // to the specified process.
        //

        if (CurrentProcess != Process) {
            KeStackAttachProcess (&Process->Pcb, &ApcState);
            Attached = TRUE;
        }
    }

    CommitReduction = 0;

    //
    // Get the address creation mutex to block multiple threads from
    // creating or deleting address space at the same time and
    // get the working set mutex so virtual address descriptors can
    // be inserted and walked.  Block APCs to prevent page faults while
    // we own the working set mutex.
    //

    LOCK_ADDRESS_SPACE (Process);

    //
    // Make sure the address space was not deleted.
    //

    if (Process->Flags & PS_PROCESS_FLAGS_VM_DELETED) {
        Status = STATUS_PROCESS_IS_TERMINATING;
        goto ErrorReturn;
    }

    Vad = (PMMVAD_SHORT) MiLocateAddress (StartingAddress);

    if (Vad == NULL) {

        //
        // No Virtual Address Descriptor located for Base Address.
        //

        Status = STATUS_MEMORY_NOT_ALLOCATED;
        goto ErrorReturn;
    }

    //
    // Found the associated Virtual Address Descriptor.
    //

    if (Vad->EndingVpn < MI_VA_TO_VPN (EndingAddress)) {

        //
        // The entire range to delete is not contained within a single
        // virtual address descriptor.  Return an error.
        //

        Status = STATUS_UNABLE_TO_FREE_VM;
        goto ErrorReturn;
    }

    //
    // Check to ensure this Vad is deletable.  Delete is required
    // for both decommit and release.
    //

    if (((Vad->u.VadFlags.PrivateMemory == 0) &&
            (Vad->u.VadFlags.VadType != VadRotatePhysical))
            ||
            (Vad->u.VadFlags.VadType == VadDevicePhysicalMemory)) {

        Status = STATUS_UNABLE_TO_DELETE_SECTION;
        goto ErrorReturn;
    }

    if (Vad->u.VadFlags.NoChange == 1) {

        //
        // An attempt is being made to delete a secured VAD, check
        // to see if this deletion is allowed.
        //

        if (FreeType & MEM_RELEASE) {

            //
            // Specify the whole range, this solves the problem with
            // splitting the VAD and trying to decide where the various
            // secure ranges need to go.
            //

            Status = MiCheckSecuredVad ((PMMVAD)Vad,
                                        MI_VPN_TO_VA (Vad->StartingVpn),
                                        ((Vad->EndingVpn - Vad->StartingVpn) << PAGE_SHIFT) +
                                        PAGE_SIZE,
                                        MM_SECURE_DELETE_CHECK);

        }
        else {
            Status = MiCheckSecuredVad ((PMMVAD)Vad,
                                        CapturedBase,
                                        CapturedRegionSize,
                                        MM_SECURE_DELETE_CHECK);
        }
        if (!NT_SUCCESS (Status)) {
            goto ErrorReturn;
        }
    }

    UserPhysicalPages = FALSE;
    ChargedVad = NULL;

    PreviousVad = MiGetPreviousVad (Vad);
    NextVad = MiGetNextVad (Vad);

    if (FreeType & MEM_RELEASE) {

        //
        // *****************************************************************
        // MEM_RELEASE was specified.
        // *****************************************************************
        //

        //
        // The descriptor for the address range is deletable.  Remove or split
        // the descriptor.
        //

        //
        // If the region size is zero, remove the whole VAD.
        //

        if (CapturedRegionSize == 0) {

            //
            // If the region size is specified as 0, the base address
            // must be the starting address for the region.
            //

            if (MI_VA_TO_VPN (CapturedBase) != Vad->StartingVpn) {
                Status = STATUS_FREE_VM_NOT_AT_BASE;
                goto ErrorReturn;
            }

            //
            // This Virtual Address Descriptor has been deleted.
            //

            StartingAddress = MI_VPN_TO_VA (Vad->StartingVpn);
            EndingAddress = MI_VPN_TO_VA_ENDING (Vad->EndingVpn);

            if (Vad->u.VadFlags.VadType == VadRotatePhysical) {
                Status = MiUnmapViewOfSection (Process,
                                               CapturedBase,
                                               UNMAP_ADDRESS_SPACE_HELD | UNMAP_ROTATE_PHYSICAL_OK);
                ASSERT (CommitReduction == 0);
                Vad = NULL;
                CapturedRegionSize = 1 + (PCHAR)EndingAddress - (PCHAR)StartingAddress;
                goto AllDone;
            }

            //
            // Free all the physical pages that this VAD might be mapping.
            //

            if (Vad->u.VadFlags.VadType == VadLargePages) {

                MiAweViewRemover (Process, (PMMVAD)Vad);

                MiReleasePhysicalCharges (Vad->EndingVpn - Vad->StartingVpn + 1,
                                          Process);

                LOCK_WS_UNSAFE (CurrentThread, Process);

                MiFreeLargePages (MI_VPN_TO_VA (Vad->StartingVpn),
                                  MI_VPN_TO_VA_ENDING (Vad->EndingVpn),
                                  FALSE);
            }
            else if (Vad->u.VadFlags.VadType == VadAwe) {
                MiAweViewRemover (Process, (PMMVAD)Vad);
                MiRemoveUserPhysicalPagesVad (Vad);
                UserPhysicalPages = TRUE;
                LOCK_WS_UNSAFE (CurrentThread, Process);
            }
            else if (Vad->u.VadFlags.VadType == VadWriteWatch) {
                LOCK_WS_UNSAFE (CurrentThread, Process);
                MiPhysicalViewRemover (Process, (PMMVAD)Vad);
            }
            else {
                LOCK_WS_UNSAFE (CurrentThread, Process);
            }

            ChargedVad = (PMMVAD)Vad;

            MiRemoveVad ((PMMVAD)Vad, Process);

            //
            // Free the VAD pool and release quota after releasing our mutexes
            // to reduce contention.
            //
        }
        else {

            //
            // Region's size was not specified as zero, delete the
            // whole VAD or split the VAD.
            //

            if (MI_VA_TO_VPN (StartingAddress) == Vad->StartingVpn) {
                if (MI_VA_TO_VPN (EndingAddress) == Vad->EndingVpn) {

                    //
                    // This Virtual Address Descriptor has been deleted.
                    //
                    // Free all the physical pages that this VAD might be
                    // mapping.
                    //

                    if (Vad->u.VadFlags.VadType == VadRotatePhysical) {
                        Status = MiUnmapViewOfSection (Process,
                                                       CapturedBase,
                                                       UNMAP_ADDRESS_SPACE_HELD | UNMAP_ROTATE_PHYSICAL_OK);
                        ASSERT (CommitReduction == 0);
                        Vad = NULL;
                        CapturedRegionSize = 1 + (PCHAR)EndingAddress - (PCHAR)StartingAddress;
                        goto AllDone;
                    }

                    if (Vad->u.VadFlags.VadType == VadLargePages) {

                        MiAweViewRemover (Process, (PMMVAD)Vad);

                        MiReleasePhysicalCharges (Vad->EndingVpn - Vad->StartingVpn + 1,
                                                  Process);

                        LOCK_WS_UNSAFE (CurrentThread, Process);

                        MiFreeLargePages (MI_VPN_TO_VA (Vad->StartingVpn),
                                          MI_VPN_TO_VA_ENDING (Vad->EndingVpn),
                                          FALSE);
                    }
                    else if (Vad->u.VadFlags.VadType == VadAwe) {
                        MiAweViewRemover (Process, (PMMVAD)Vad);
                        MiRemoveUserPhysicalPagesVad (Vad);
                        UserPhysicalPages = TRUE;
                        LOCK_WS_UNSAFE (CurrentThread, Process);
                    }
                    else if (Vad->u.VadFlags.VadType == VadWriteWatch) {
                        LOCK_WS_UNSAFE (CurrentThread, Process);
                        MiPhysicalViewRemover (Process, (PMMVAD)Vad);
                    }
                    else {
                        LOCK_WS_UNSAFE (CurrentThread, Process);
                    }

                    ChargedVad = (PMMVAD)Vad;

                    MiRemoveVad ((PMMVAD)Vad, Process);

                    //
                    // Free the VAD pool after releasing our mutexes
                    // to reduce contention.
                    //
                }
                else {

                    if ((Vad->u.VadFlags.VadType == VadAwe) ||
                            (Vad->u.VadFlags.VadType == VadLargePages) ||
                            (Vad->u.VadFlags.VadType == VadRotatePhysical) ||
                            (Vad->u.VadFlags.VadType == VadWriteWatch)) {

                        //
                        // Splitting or chopping a physical VAD, large page VAD
                        // or a write-watch VAD is not allowed.
                        //

                        Status = STATUS_FREE_VM_NOT_AT_BASE;
                        goto ErrorReturn;
                    }

                    LOCK_WS_UNSAFE (CurrentThread, Process);

                    //
                    // This Virtual Address Descriptor has a new starting
                    // address.
                    //

                    CommitReduction = MiCalculatePageCommitment (
                                          StartingAddress,
                                          EndingAddress,
                                          (PMMVAD)Vad,
                                          Process);

                    Vad->StartingVpn = MI_VA_TO_VPN ((PCHAR)EndingAddress + 1);
                    Vad->u.VadFlags.CommitCharge -= CommitReduction;
                    ASSERT ((SSIZE_T)Vad->u.VadFlags.CommitCharge >= 0);
                    NextVad = (PMMVAD)Vad;
                    Vad = NULL;
                }
            }
            else {

                if ((Vad->u.VadFlags.VadType == VadAwe) ||
                        (Vad->u.VadFlags.VadType == VadLargePages) ||
                        (Vad->u.VadFlags.VadType == VadRotatePhysical) ||
                        (Vad->u.VadFlags.VadType == VadWriteWatch)) {

                    //
                    // Splitting or chopping a physical VAD, large page VAD
                    // or a write-watch VAD is not allowed.
                    //

                    Status = STATUS_FREE_VM_NOT_AT_BASE;
                    goto ErrorReturn;
                }

                //
                // Starting address is greater than start of VAD.
                //

                if (MI_VA_TO_VPN (EndingAddress) == Vad->EndingVpn) {

                    //
                    // Change the ending address of the VAD.
                    //

                    LOCK_WS_UNSAFE (CurrentThread, Process);

                    CommitReduction = MiCalculatePageCommitment (
                                          StartingAddress,
                                          EndingAddress,
                                          (PMMVAD)Vad,
                                          Process);

                    Vad->u.VadFlags.CommitCharge -= CommitReduction;

                    Vad->EndingVpn = MI_VA_TO_VPN ((PCHAR)StartingAddress - 1);
                    PreviousVad = (PMMVAD)Vad;
                }
                else {

                    //
                    // Split this VAD as the address range is within the VAD.
                    //

                    NewVad = ExAllocatePoolWithTag (NonPagedPool,
                                                    sizeof(MMVAD_SHORT),
                                                    'FdaV');

                    if (NewVad == NULL) {
                        Status = STATUS_INSUFFICIENT_RESOURCES;
                        goto ErrorReturn;
                    }

                    *NewVad = *Vad;

                    NewVad->StartingVpn = MI_VA_TO_VPN ((PCHAR)EndingAddress + 1);
                    //
                    // Set the commit charge to zero so MiInsertVad will
                    // not charge commitment for splitting the VAD.
                    //

                    NewVad->u.VadFlags.CommitCharge = 0;

                    //
                    // Insert the VAD, this could fail due to quota charges.
                    //

                    Status = MiInsertVadCharges ((PMMVAD)NewVad, Process);

                    if (!NT_SUCCESS(Status)) {

                        //
                        // The quota charging failed, free the new VAD
                        // and return an error.
                        //

                        UNLOCK_ADDRESS_SPACE (Process);
                        ExFreePool (NewVad);
                        goto ErrorReturn2;
                    }

                    LOCK_WS_UNSAFE (CurrentThread, Process);

                    CommitReduction = MiCalculatePageCommitment (
                                          StartingAddress,
                                          EndingAddress,
                                          (PMMVAD)Vad,
                                          Process);

                    OldQuota = Vad->u.VadFlags.CommitCharge - CommitReduction;

                    Vad->EndingVpn = MI_VA_TO_VPN ((PCHAR)StartingAddress - 1);

                    MiInsertVad ((PMMVAD)NewVad, Process);

                    //
                    // As we have split the original VAD into 2 separate VADs
                    // there is no way of knowing what the commit charge
                    // is for each VAD.  Calculate the charge and reset
                    // each VAD.  Note that we also use the previous value
                    // to make sure the books stay balanced.
                    //

                    QuotaCharge = MiCalculatePageCommitment (MI_VPN_TO_VA (Vad->StartingVpn),
                                  (PCHAR)StartingAddress - 1,
                                  (PMMVAD)Vad,
                                  Process);

                    Vad->u.VadFlags.CommitCharge = QuotaCharge;

                    //
                    // Give the remaining charge to the new VAD.
                    //

                    NewVad->u.VadFlags.CommitCharge = OldQuota - QuotaCharge;
                    PreviousVad = (PMMVAD)Vad;
                    NextVad = (PMMVAD)NewVad;
                }
                Vad = NULL;
            }
        }

        if (UserPhysicalPages == TRUE) {
            MiDeletePageTablesForPhysicalRange (StartingAddress, EndingAddress);
        }
        else {

            MiDeleteVirtualAddresses (StartingAddress,
                                      EndingAddress,
                                      NULL);
        }

        UNLOCK_WS_UNSAFE (CurrentThread, Process);

        //
        // Return commitment for page table pages if possible.
        //

        MiReturnPageTablePageCommitment (StartingAddress,
                                         EndingAddress,
                                         Process,
                                         PreviousVad,
                                         NextVad);

        if (ChargedVad != NULL) {
            MiRemoveVadCharges (ChargedVad, Process);
        }

        CapturedRegionSize = 1 + (PCHAR)EndingAddress - (PCHAR)StartingAddress;

        //
        // Update the virtual size in the process header.
        //

        Process->VirtualSize -= CapturedRegionSize;

        Process->CommitCharge -= CommitReduction;
        Status = STATUS_SUCCESS;

AllDone:
        UNLOCK_ADDRESS_SPACE (Process);

        if (CommitReduction != 0) {

            MI_INCREMENT_TOTAL_PROCESS_COMMIT (0 - CommitReduction);

            ASSERT (Vad == NULL);
            PsReturnProcessPageFileQuota (Process, CommitReduction);
            MiReturnCommitment (CommitReduction);

            if (Process->JobStatus & PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
                PsChangeJobMemoryUsage (PS_JOB_STATUS_REPORT_COMMIT_CHANGES, -(SSIZE_T)CommitReduction);
            }

            MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_NTFREEVM1, CommitReduction);
        }
        else if (Vad != NULL) {
            ExFreePool (Vad);
        }

        if (Attached == TRUE) {
            KeUnstackDetachProcess (&ApcState);
        }

        if (ProcessHandle != NtCurrentProcess ()) {
            ObDereferenceObject (Process);
        }
        //
        // Establish an exception handler and write the size and base
        // address.
        //

        try {

            *RegionSize = CapturedRegionSize;
            *BaseAddress = StartingAddress;

        }
        except (EXCEPTION_EXECUTE_HANDLER) {

            //
            // An exception occurred, don't take any action (just handle
            // the exception and return success.

        }

        return Status;
    }

    //
    // **************************************************************
    //
    // MEM_DECOMMIT was specified.
    //
    // **************************************************************
    //

    if (Vad->u.VadFlags.VadType == VadAwe) {

        //
        // Pages from a physical VAD must be released via
        // NtFreeUserPhysicalPages, not this routine.
        //

        Status = STATUS_MEMORY_NOT_ALLOCATED;
        goto ErrorReturn;
    }

    if ((Vad->u.VadFlags.VadType == VadLargePages) ||
            (Vad->u.VadFlags.VadType == VadRotatePhysical)) {

        //
        // Pages from a large page or rotate physical VAD must be released -
        // they cannot be merely decommitted.
        //

        Status = STATUS_MEMORY_NOT_ALLOCATED;
        goto ErrorReturn;
    }

    //
    // Check to ensure the complete range of pages is already committed.
    //

    if (CapturedRegionSize == 0) {

        if (MI_VA_TO_VPN (CapturedBase) != Vad->StartingVpn) {
            Status = STATUS_FREE_VM_NOT_AT_BASE;
            goto ErrorReturn;
        }
        EndingAddress = MI_VPN_TO_VA_ENDING (Vad->EndingVpn);
    }

    //
    // The address range is entirely committed, decommit it now.
    //

    //
    // Calculate the initial quotas and commit charges for this VAD.
    //

    StartingPte = MiGetPteAddress (StartingAddress);
    EndingPte = MiGetPteAddress (EndingAddress);

    CommitReduction = 1 + EndingPte - StartingPte;

    //
    // Check to see if the entire range can be decommitted by
    // just updating the virtual address descriptor.
    //

    CommitReduction -= MiDecommitPages (StartingAddress,
                                        EndingPte,
                                        Process,
                                        Vad);

    //
    // Adjust the quota charges.
    //

    ASSERT ((LONG)CommitReduction >= 0);

    Vad->u.VadFlags.CommitCharge -= CommitReduction;
    ASSERT ((LONG)Vad->u.VadFlags.CommitCharge >= 0);
    Vad = NULL;

    Process->CommitCharge -= CommitReduction;

    UNLOCK_ADDRESS_SPACE (Process);

    if (CommitReduction != 0) {

        MI_INCREMENT_TOTAL_PROCESS_COMMIT (0 - CommitReduction);

        PsReturnProcessPageFileQuota (Process, CommitReduction);
        MiReturnCommitment (CommitReduction);

        if (Process->JobStatus & PS_JOB_STATUS_REPORT_COMMIT_CHANGES) {
            PsChangeJobMemoryUsage (PS_JOB_STATUS_REPORT_COMMIT_CHANGES, -(SSIZE_T)CommitReduction);
        }

        MM_TRACK_COMMIT (MM_DBG_COMMIT_RETURN_NTFREEVM2, CommitReduction);
    }
    else if (Vad != NULL) {
        ExFreePool (Vad);
    }

    if (Attached == TRUE) {
        KeUnstackDetachProcess (&ApcState);
    }

    if (ProcessHandle != NtCurrentProcess()) {
        ObDereferenceObject (Process);
    }

    //
    // Establish an exception handler and write the size and base address.
    //

    try {

        *RegionSize = 1 + (PCHAR)EndingAddress - (PCHAR)StartingAddress;
        *BaseAddress = StartingAddress;

    }
    except (EXCEPTION_EXECUTE_HANDLER) {
        NOTHING;
    }

    return STATUS_SUCCESS;

ErrorReturn:
    UNLOCK_ADDRESS_SPACE (Process);

ErrorReturn2:
    if (Attached == TRUE) {
        KeUnstackDetachProcess (&ApcState);
    }

    if (ProcessHandle != NtCurrentProcess()) {
        ObDereferenceObject (Process);
    }
    return Status;
}
Example #26
0
/*
 * @implemented
 */
LPVOID
WINAPI
CreateFiberEx(SIZE_T dwStackCommitSize,
              SIZE_T dwStackReserveSize,
              DWORD dwFlags,
              LPFIBER_START_ROUTINE lpStartAddress,
              LPVOID lpParameter)
{
    PFIBER Fiber;
    NTSTATUS Status;
    INITIAL_TEB InitialTeb;
    PVOID ActivationContextStack = NULL;
    DPRINT("Creating Fiber\n");

    /* Check for invalid flags */
    if (dwFlags &~ FIBER_FLAG_FLOAT_SWITCH)
    {
        /* Fail */
        SetLastError(ERROR_INVALID_PARAMETER);
        return NULL;
    }

    /* Allocate the Activation Context Stack */
    Status = RtlAllocateActivationContextStack(&ActivationContextStack);
    if (!NT_SUCCESS(Status))
    {
        /* Fail */
        BaseSetLastNTError(Status);
        return NULL;
    }

    /* Allocate the fiber */
    Fiber = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(FIBER));
    if (!Fiber)
    {
        /* Fail */
        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
        return NULL;
    }

    /* Create the stack for the fiber */
    Status = BasepCreateStack(NtCurrentProcess(),
                              dwStackCommitSize,
                              dwStackReserveSize,
                              &InitialTeb);
    if (!NT_SUCCESS(Status))
    {
        /* Free the fiber */
        RtlFreeHeap(GetProcessHeap(), 0, Fiber);

        /* Free the activation context */
        DPRINT1("Leaking activation stack because nobody implemented free");
        //RtlFreeActivationContextStack(&ActivationContextStack);

        /* Failure */
        BaseSetLastNTError(Status);
        return NULL;
    }

    /* Clear the context */
    RtlZeroMemory(&Fiber->Context, sizeof(CONTEXT));

    /* Copy the data into the fiber */
    Fiber->StackBase = InitialTeb.StackBase;
    Fiber->StackLimit = InitialTeb.StackLimit;
    Fiber->DeallocationStack = InitialTeb.AllocatedStackBase;
    Fiber->Parameter = lpParameter;
    Fiber->ExceptionList = EXCEPTION_CHAIN_END;
    Fiber->GuaranteedStackBytes = 0;
    Fiber->FlsData = NULL;
    Fiber->ActivationContextStack = ActivationContextStack;
    Fiber->Context.ContextFlags = CONTEXT_FULL;

    /* Save FPU State if requested */
    Fiber->Context.ContextFlags = (dwFlags & FIBER_FLAG_FLOAT_SWITCH) ? CONTEXT_FLOATING_POINT : 0;

    /* initialize the context for the fiber */
    BasepInitializeContext(&Fiber->Context,
                           lpParameter,
                           lpStartAddress,
                           InitialTeb.StackBase,
                           2);

    /* Return the Fiber */
    return Fiber;
}
void
Test_ImageSection(void)
{
    UNICODE_STRING FileName;
    NTSTATUS Status;
    OBJECT_ATTRIBUTES FileObjectAttributes;
    IO_STATUS_BLOCK IoStatusBlock;
    HANDLE FileHandle, DataSectionHandle, ImageSectionHandle;
    PVOID DataBase, ImageBase;
    SIZE_T ViewSize;

    if (!RtlDosPathNameToNtPathName_U(L"testdata\\test.dll",
                                      &FileName,
                                      NULL,
                                      NULL))
    {
        ok(0, "RtlDosPathNameToNtPathName_U failed\n");
        return;
    }

    InitializeObjectAttributes(&FileObjectAttributes,
                               &FileName,
                               0,
                               NULL,
                               NULL);

    Status = NtOpenFile(&FileHandle,
                        GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
                        &FileObjectAttributes,
                        &IoStatusBlock,
                        FILE_SHARE_READ,
                        FILE_SYNCHRONOUS_IO_NONALERT);
    ok(Status == STATUS_SUCCESS, "NtOpenFile failed, Status 0x%lx\n", Status);

    /* Create a data section with write access */
    Status = NtCreateSection(&DataSectionHandle,
                             SECTION_ALL_ACCESS, // DesiredAccess
                             NULL, // ObjectAttributes
                             NULL, // MaximumSize
                             PAGE_READWRITE, // SectionPageProtection
                             SEC_COMMIT, // AllocationAttributes
                             FileHandle);
    ok(Status == STATUS_SUCCESS, "NtCreateSection failed, Status 0x%lx\n", Status);

    /* Map the data section */
    DataBase = NULL;
    ViewSize = 0;
    Status = NtMapViewOfSection(DataSectionHandle,
                                NtCurrentProcess(),
                                &DataBase,
                                0,
                                0,
                                NULL,
                                &ViewSize,
                                ViewShare,
                                0,
                                PAGE_READWRITE);
    ok(Status == STATUS_SUCCESS, "NtMapViewOfSection failed, Status 0x%lx\n", Status);

    /* Check the original data */
    ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");

    /* Modify the PE header (but do not flush!) */
    *(ULONG*)DataBase = 0xdeadbabe;
    ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n");

    /* Modify data in the .data section (but do not flush!) */
    ok(*(ULONG*)((PUCHAR)DataBase + 0x800) == 0x12345678,
       "Data in .data section invalid: 0x%lx!\n", *(ULONG*)((PUCHAR)DataBase + 0x800));
    *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x87654321;

    /* Now try to create an image section (should fail) */
    Status = NtCreateSection(&ImageSectionHandle,
                             SECTION_ALL_ACCESS, // DesiredAccess
                             NULL, // ObjectAttributes
                             NULL, // MaximumSize
                             PAGE_READWRITE, // SectionPageProtection
                             SEC_IMAGE, // AllocationAttributes
                             FileHandle);
    ok(Status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection failed, Status 0x%lx\n", Status);

    /* Restore the original header */
    *(ULONG*)DataBase = 0x00905a4d;

    /* Modify data in the .data section (but do not flush!) */
    ok_hex(*(ULONG*)((PUCHAR)DataBase + 0x800), 0x87654321);
    *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xdeadbabe;

    /* Try to create an image section again */
    Status = NtCreateSection(&ImageSectionHandle,
                             SECTION_ALL_ACCESS, // DesiredAccess
                             NULL, // ObjectAttributes
                             NULL, // MaximumSize
                             PAGE_READWRITE, // SectionPageProtection
                             SEC_IMAGE, // AllocationAttributes
                             FileHandle);
    ok(Status == STATUS_SUCCESS, "NtCreateSection failed, Status 0x%lx\n", Status);

    /* Map the image section */
    ImageBase = NULL;
    ViewSize = 0;
    Status = NtMapViewOfSection(ImageSectionHandle,
                                NtCurrentProcess(),
                                &ImageBase,
                                0,
                                0,
                                NULL,
                                &ViewSize,
                                ViewShare,
                                0,
                                PAGE_READONLY);
#ifdef _M_IX86
    ok(Status == STATUS_SUCCESS, "NtMapViewOfSection failed, Status 0x%lx\n", Status);
#else
    ok(Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH, "NtMapViewOfSection failed, Status 0x%lx\n", Status);
#endif

    /* Check the header */
    ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");
    ok(*(ULONG*)ImageBase == 0x00905a4d, "Header not ok\n");

    /* Check the data section. Either of these can be present! */
    ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
       (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
       "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));

    /* Now modify the data again */
    *(ULONG*)DataBase = 0xdeadbabe;
    *(ULONG*)((PUCHAR)DataBase + 0x800) = 0xf00dada;

    /* Check the data */
    ok(*(ULONG*)DataBase == 0xdeadbabe, "Header not ok\n");
    ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n");
    ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
       (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
       "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));

    /* Flush the view */
    ViewSize = 0x1000;
    Status = NtFlushVirtualMemory(NtCurrentProcess(),
                                  &DataBase,
                                  &ViewSize,
                                  &IoStatusBlock);
    ok(Status == STATUS_SUCCESS, "NtFlushVirtualMemory failed, Status 0x%lx\n", Status);

    /* Check the data again */
    ok(*(ULONG*)ImageBase == 0x00905a4d, "Data should not be synced!\n");
    ok((*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x87654321) ||
       (*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0x12345678),
       "Wrong value in data section: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));

    /* Restore the original header */
    *(ULONG*)DataBase = 0x00905a4d;
    ok(*(ULONG*)DataBase == 0x00905a4d, "Header not ok\n");

    /* Close the image mapping */
    NtUnmapViewOfSection(NtCurrentProcess(), ImageBase);
    NtClose(ImageSectionHandle);

    /* Create an image section again */
    Status = NtCreateSection(&ImageSectionHandle,
                             SECTION_ALL_ACCESS, // DesiredAccess
                             NULL, // ObjectAttributes
                             NULL, // MaximumSize
                             PAGE_READWRITE, // SectionPageProtection
                             SEC_IMAGE, // AllocationAttributes
                             FileHandle);
    ok(Status == STATUS_SUCCESS, "NtCreateSection failed, Status 0x%lx\n", Status);

    /* Map the image section again */
    ImageBase = NULL;
    ViewSize = 0;
    Status = NtMapViewOfSection(ImageSectionHandle,
                                NtCurrentProcess(),
                                &ImageBase,
                                0,
                                0,
                                NULL,
                                &ViewSize,
                                ViewShare,
                                0,
                                PAGE_READONLY);
#ifdef _M_IX86
    ok(Status == STATUS_SUCCESS, "NtMapViewOfSection failed, Status 0x%lx\n", Status);
#else
    ok(Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH, "NtMapViewOfSection failed, Status 0x%lx\n", Status);
#endif

    /* Check the .data section again */
    ok(*(ULONG*)((PUCHAR)ImageBase + 0x80000) == 0xf00dada,
       "Data should be synced: 0x%lx!\n", *(ULONG*)((PUCHAR)ImageBase + 0x80000));

    /* Restore the original data */
    *(ULONG*)((PUCHAR)DataBase + 0x800) = 0x12345678;

    /* Close the data mapping */
    NtUnmapViewOfSection(NtCurrentProcess(), DataBase);

    NtClose(DataSectionHandle);

    /* Try to allocate memory inside the image mapping */
    DataBase = (PUCHAR)ImageBase + 0x20000;
    ViewSize = 0x1000;
    Status = NtAllocateVirtualMemory(NtCurrentProcess(), &DataBase, 0, &ViewSize, MEM_RESERVE, PAGE_NOACCESS);
    ok(Status ==  STATUS_CONFLICTING_ADDRESSES, "Wrong Status: 0x%lx\n", Status);

    /* Cleanup */
    NtClose(FileHandle);
    NtClose(ImageSectionHandle);
    NtUnmapViewOfSection(NtCurrentProcess(), ImageBase);
}
Example #28
0
ULONG
NTAPI
SmpApiLoop(IN PVOID Parameter)
{
    HANDLE SmApiPort = (HANDLE)Parameter;
    NTSTATUS Status;
    PSMP_CLIENT_CONTEXT ClientContext;
    PSM_API_MSG ReplyMsg = NULL;
    SM_API_MSG RequestMsg;
    PROCESS_BASIC_INFORMATION ProcessInformation;
    LARGE_INTEGER Timeout;

    /* Increase the number of API threads for throttling code for later */
    _InterlockedExchangeAdd(&SmTotalApiThreads, 1);

    /* Mark us critical */
    RtlSetThreadIsCritical(TRUE, NULL, TRUE);

    /* Set the PID of the SM process itself for later checking */
    NtQueryInformationProcess(NtCurrentProcess(),
                              ProcessBasicInformation,
                              &ProcessInformation,
                              sizeof(ProcessInformation),
                              NULL);
    SmUniqueProcessId = (HANDLE)ProcessInformation.UniqueProcessId;

    /* Now process incoming messages */
    while (TRUE)
    {
        /* Begin waiting on a request */
        Status = NtReplyWaitReceivePort(SmApiPort,
                                        (PVOID*)&ClientContext,
                                        &ReplyMsg->h,
                                        &RequestMsg.h);
        if (Status == STATUS_NO_MEMORY)
        {
            /* Ran out of memory, so do a little timeout and try again */
            if (ReplyMsg) DPRINT1("SMSS: Failed to reply to calling thread, retrying.\n");
            Timeout.QuadPart = -50000000;
            NtDelayExecution(FALSE, &Timeout);
            continue;
        }

        /* Check what kind of request we received */
        switch (RequestMsg.h.u2.s2.Type)
        {
            /* A new connection */
            case LPC_CONNECTION_REQUEST:
                /* Create the right structures for it */
                SmpHandleConnectionRequest(SmApiPort, (PSB_API_MSG)&RequestMsg);
                ReplyMsg = NULL;
                break;

            /* A closed connection */
            case LPC_PORT_CLOSED:
                /* Destroy any state we had for this client */
                DPRINT1("Port closed\n");
                //if (ClientContext) SmpPushDeferredClientContext(ClientContext);
                ReplyMsg = NULL;
                break;

            /* An actual API message */
            default:
                if (!ClientContext)
                {
                    ReplyMsg = NULL;
                    break;
                }

                RequestMsg.ReturnValue = STATUS_PENDING;

                /* Check if the API is valid */
                if (RequestMsg.ApiNumber >= SmpMaxApiNumber)
                {
                    /* It isn't, fail */
                    DPRINT1("Invalid API: %lx\n", RequestMsg.ApiNumber);
                    Status = STATUS_NOT_IMPLEMENTED;
                }
                else if ((RequestMsg.ApiNumber <= SmpTerminateForeignSessionApi) &&
                         !(ClientContext->Subsystem))
                {
                    /* It's valid, but doesn't have a subsystem with it */
                    DPRINT1("Invalid session API\n");
                    Status = STATUS_INVALID_PARAMETER;
                }
                else
                {
                    /* It's totally okay, so call the dispatcher for it */
                    Status = SmpApiDispatch[RequestMsg.ApiNumber](&RequestMsg,
                                                                  ClientContext,
                                                                  SmApiPort);
                }

                /* Write the result value and return the message back */
                RequestMsg.ReturnValue = Status;
                ReplyMsg = &RequestMsg;
                break;
        }
    }
    return STATUS_SUCCESS;
}
Example #29
0
NTSTATUS
RtlCreateUserProcess(
    IN PUNICODE_STRING NtImagePathName,
    IN ULONG Attributes,
    IN PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
    IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL,
    IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL,
    IN HANDLE ParentProcess OPTIONAL,
    IN BOOLEAN InheritHandles,
    IN HANDLE DebugPort OPTIONAL,
    IN HANDLE ExceptionPort OPTIONAL,
    OUT PRTL_USER_PROCESS_INFORMATION ProcessInformation
    )

/*++

Routine Description:

    This function creates a user mode process with a single thread with
    a suspend count of one.  The address space of the new process is
    initialized with the contents of specified image file.  The caller
    can specify the Access Control List for the new process and thread.
    The caller can also specify the parent process to inherit process
    priority and processor affinity from.  The default is to inherit
    these from the current process.  Finally the caller can specify
    whether the new process is to inherit any of the object handles
    from the specified parent process or not.

    Information about the new process and thread is returned via
    the ProcessInformation parameter.

Arguments:

    NtImagePathName - A required pointer that points to the NT Path string
        that identifies the image file that is to be loaded into the
        child process.

    ProcessParameters - A required pointer that points to parameters that
        are to passed to the child process.

    ProcessSecurityDescriptor - An optional pointer to the Security Descriptor
        give to the new process.

    ThreadSecurityDescriptor - An optional pointer to the Security Descriptor
        give to the new thread.

    ParentProcess - An optional process handle that will used to inherit
        certain properties from.

    InheritHandles - A boolean value.  TRUE specifies that object handles
        associated with the specified parent process are to be inherited
        by the new process, provided they have the OBJ_INHERIT attribute.
        FALSE specifies that the new process is to inherit no handles.

    DebugPort - An optional handle to the debug port associated with this
        process.

    ExceptionPort - An optional handle to the exception port associated with this
        process.

    ProcessInformation - A pointer to a variable that receives information
        about the new process and thread.

--*/

{
    NTSTATUS Status;
    HANDLE Section, File;
    OBJECT_ATTRIBUTES ObjectAttributes;
    PRTL_USER_PROCESS_PARAMETERS Parameters;
    SIZE_T ParameterLength;
    PVOID Environment;
    PWCHAR s;
    SIZE_T EnvironmentLength;
    SIZE_T RegionSize;
    PROCESS_BASIC_INFORMATION ProcessInfo;
    PPEB Peb;
    UNICODE_STRING Unicode;

    //
    // Zero output parameter and probe the addresses at the same time
    //

    RtlZeroMemory( ProcessInformation, sizeof( *ProcessInformation ) );
    ProcessInformation->Length = sizeof( *ProcessInformation );

    //
    // Open the specified image file.
    //

    Status = RtlpOpenImageFile( NtImagePathName,
                                Attributes & (OBJ_INHERIT | OBJ_CASE_INSENSITIVE),
                                &File,
                                TRUE
                              );
    if (!NT_SUCCESS( Status )) {
        return( Status );
        }


    //
    // Create a memory section backed by the opened image file
    //

    Status = ZwCreateSection( &Section,
                              SECTION_ALL_ACCESS,
                              NULL,
                              NULL,
                              PAGE_EXECUTE,
                              SEC_IMAGE,
                              File
                            );
    ZwClose( File );
    if ( !NT_SUCCESS( Status ) ) {
        return( Status );
        }


    //
    // Create the user mode process, defaulting the parent process to the
    // current process if one is not specified.  The new process will not
    // have a name nor will the handle be inherited by other processes.
    //

    if (!ARGUMENT_PRESENT( ParentProcess )) {
        ParentProcess = NtCurrentProcess();
        }

    InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL,
                                ProcessSecurityDescriptor );
    if ( RtlGetNtGlobalFlags() & FLG_ENABLE_CSRDEBUG ) {
        if ( wcsstr(NtImagePathName->Buffer,L"csrss") ||
             wcsstr(NtImagePathName->Buffer,L"CSRSS")
           ) {

            //
            // For Hydra we don't name the CSRSS process to avoid name
            // collissions when multiple CSRSS's are started
            //
            if (ISTERMINALSERVER()) {

                InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL,
                                            ProcessSecurityDescriptor );
            } else {

                RtlInitUnicodeString(&Unicode,L"\\WindowsSS");
                InitializeObjectAttributes( &ObjectAttributes, &Unicode, 0, NULL,
                                            ProcessSecurityDescriptor );
            }

            }
        }

    if ( !InheritHandles ) {
        ProcessParameters->CurrentDirectory.Handle = NULL;
        }
    Status = ZwCreateProcess( &ProcessInformation->Process,
                              PROCESS_ALL_ACCESS,
                              &ObjectAttributes,
                              ParentProcess,
                              InheritHandles,
                              Section,
                              DebugPort,
                              ExceptionPort
                            );
    if ( !NT_SUCCESS( Status ) ) {
        ZwClose( Section );
        return( Status );
        }


    //
    // Retrieve the interesting information from the image header
    //

    Status = ZwQuerySection( Section,
                             SectionImageInformation,
                             &ProcessInformation->ImageInformation,
                             sizeof( ProcessInformation->ImageInformation ),
                             NULL
                           );
    if ( !NT_SUCCESS( Status ) ) {
        ZwClose( ProcessInformation->Process );
        ZwClose( Section );
        return( Status );
        }

    Status = ZwQueryInformationProcess( ProcessInformation->Process,
                                        ProcessBasicInformation,
                                        &ProcessInfo,
                                        sizeof( ProcessInfo ),
                                        NULL
                                      );
    if ( !NT_SUCCESS( Status ) ) {
        ZwClose( ProcessInformation->Process );
        ZwClose( Section );
        return( Status );
        }

    Peb = ProcessInfo.PebBaseAddress;

    //
    // Duplicate Native handles into new process if any specified.
    // Note that the duplicated handles will overlay the input values.
    //

    try {
        Status = STATUS_SUCCESS;

        if ( ProcessParameters->StandardInput ) {

            Status = ZwDuplicateObject(
                        ParentProcess,
                        ProcessParameters->StandardInput,
                        ProcessInformation->Process,
                        &ProcessParameters->StandardInput,
                        0L,
                        0L,
                        DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES
                        );
            if ( !NT_SUCCESS(Status) ) {
                __leave;
            }
        }

        if ( ProcessParameters->StandardOutput ) {

            Status = ZwDuplicateObject(
                        ParentProcess,
                        ProcessParameters->StandardOutput,
                        ProcessInformation->Process,
                        &ProcessParameters->StandardOutput,
                        0L,
                        0L,
                        DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES
                        );
            if ( !NT_SUCCESS(Status) ) {
                __leave;
            }
        }

        if ( ProcessParameters->StandardError ) {

            Status = ZwDuplicateObject(
                        ParentProcess,
                        ProcessParameters->StandardError,
                        ProcessInformation->Process,
                        &ProcessParameters->StandardError,
                        0L,
                        0L,
                        DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES
                        );
            if ( !NT_SUCCESS(Status) ) {
                __leave;
            }
        }

    } finally {
        if ( !NT_SUCCESS(Status) ) {
            ZwClose( ProcessInformation->Process );
            ZwClose( Section );
        }
    }

    if ( !NT_SUCCESS(Status) ) {
        return Status;
    }

    //
    // Possibly reserve some address space in the new process
    //

    if (ProcessInformation->ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_NATIVE ) {
        if ( ProcessParameters->Flags & RTL_USER_PROC_RESERVE_1MB ) {

            Environment = (PVOID)(4);
            RegionSize = (1024*1024)-(256);

            Status = ZwAllocateVirtualMemory( ProcessInformation->Process,
                                              (PVOID *)&Environment,
                                              0,
                                              &RegionSize,
                                              MEM_RESERVE,
                                              PAGE_READWRITE
                                            );
            if ( !NT_SUCCESS( Status ) ) {
                ZwClose( ProcessInformation->Process );
                ZwClose( Section );
                return( Status );
                }
            }
        }

    //
    // Allocate virtual memory in the new process and use NtWriteVirtualMemory
    // to write a copy of the process environment block into the address
    // space of the new process.  Save the address of the allocated block in
    // the process parameter block so the new process can access it.
    //

    if (s = (PWCHAR)ProcessParameters->Environment) {
        while (*s++) {
            while (*s++) {
                }
            }
        EnvironmentLength = (SIZE_T)(s - (PWCHAR)ProcessParameters->Environment) * sizeof(WCHAR);

        Environment = NULL;
        RegionSize = EnvironmentLength;
        Status = ZwAllocateVirtualMemory( ProcessInformation->Process,
                                          (PVOID *)&Environment,
                                          0,
                                          &RegionSize,
                                          MEM_COMMIT,
                                          PAGE_READWRITE
                                        );
        if ( !NT_SUCCESS( Status ) ) {
            ZwClose( ProcessInformation->Process );
            ZwClose( Section );
            return( Status );
            }

        Status = ZwWriteVirtualMemory( ProcessInformation->Process,
                                       Environment,
                                       ProcessParameters->Environment,
                                       EnvironmentLength,
                                       NULL
                                     );
        if ( !NT_SUCCESS( Status ) ) {
            ZwClose( ProcessInformation->Process );
            ZwClose( Section );
            return( Status );
            }

        ProcessParameters->Environment = Environment;
        }

    //
    // Allocate virtual memory in the new process and use NtWriteVirtualMemory
    // to write a copy of the process parameters block into the address
    // space of the new process.  Set the initial parameter to the new thread
    // to be the address of the block in the new process's address space.
    //

    Parameters = NULL;
    ParameterLength = ProcessParameters->MaximumLength;
    Status = ZwAllocateVirtualMemory( ProcessInformation->Process,
                                      (PVOID *)&Parameters,
                                      0,
                                      &ParameterLength,
                                      MEM_COMMIT,
                                      PAGE_READWRITE
                                    );
    if ( !NT_SUCCESS( Status ) ) {
        ZwClose( ProcessInformation->Process );
        ZwClose( Section );
        return( Status );
        }

    Status = ZwWriteVirtualMemory( ProcessInformation->Process,
                                   Parameters,
                                   ProcessParameters,
                                   ProcessParameters->Length,
                                   NULL
                                 );
    if ( !NT_SUCCESS( Status ) ) {
            ZwClose( ProcessInformation->Process );
            ZwClose( Section );
            return( Status );
            }

    Status = ZwWriteVirtualMemory( ProcessInformation->Process,
                                   &Peb->ProcessParameters,
                                   &Parameters,
                                   sizeof( Parameters ),
                                   NULL
                                 );
    if ( !NT_SUCCESS( Status ) ) {
        ZwClose( ProcessInformation->Process );
        ZwClose( Section );
        return( Status );
        }

    //
    // Create a suspended thread in the new process.  Specify the size and
    // position of the stack, along with the start address, initial parameter
    // and an SECURITY_DESCRIPTOR.  The new thread will not have a name and its handle will
    // not be inherited by other processes.
    //

    Status = RtlCreateUserThread(
                 ProcessInformation->Process,
                 ThreadSecurityDescriptor,
                 TRUE,
                 ProcessInformation->ImageInformation.ZeroBits,
                 ProcessInformation->ImageInformation.MaximumStackSize,
                 ProcessInformation->ImageInformation.CommittedStackSize,
                 (PUSER_THREAD_START_ROUTINE)
                     ProcessInformation->ImageInformation.TransferAddress,
                 (PVOID)Peb,
                 &ProcessInformation->Thread,
                 &ProcessInformation->ClientId
                 );
    if ( !NT_SUCCESS( Status ) ) {
        ZwClose( ProcessInformation->Process );
        ZwClose( Section );
        return( Status );
        }

    //
    // Now close the section and file handles.  The objects they represent
    // will not actually go away until the process is destroyed.
    //

    ZwClose( Section );

    //
    // Return success status
    //

    return( STATUS_SUCCESS );
}
Example #30
0
NTSTATUS
NtFreeVirtualMemory(
    IN HANDLE ProcessHandle,
    IN OUT PVOID *BaseAddress,
    IN OUT PULONG RegionSize,
    IN ULONG FreeType
     )

/*++

Routine Description:

    This function deletes a region of pages within the virtual address
    space of a subject process.

Arguments:

   ProcessHandle - An open handle to a process object.

   BaseAddress - The base address of the region of pages
        to be freed. This value is rounded down to the
        next host page address boundary.

   RegionSize - A pointer to a variable that will receive
        the actual size in bytes of the freed region of
        pages. The initial value of this argument is
        rounded up to the next host page size boundary.

   FreeType - A set of flags that describe the type of
        free that is to be performed for the specified
        region of pages.


       FreeType Flags


        MEM_DECOMMIT - The specified region of pages is to
             be decommitted.

        MEM_RELEASE - The specified region of pages is to
             be released.


Return Value:

    Returns the status

    TBS


--*/

{
    PMMVAD_SHORT Vad;
    PMMVAD_SHORT NewVad;
    PMMVAD PreviousVad;
    PMMVAD NextVad;
    PEPROCESS Process;
    KPROCESSOR_MODE PreviousMode;
    PVOID StartingAddress;
    PVOID EndingAddress;
    NTSTATUS Status;
    ULONG Attached = FALSE;
    ULONG CapturedRegionSize;
    PVOID CapturedBase;
    PMMPTE StartingPte;
    PMMPTE EndingPte;
    ULONG OldQuota;
    ULONG QuotaCharge;
    ULONG CommitReduction;
    PVOID OldEnd;

    PAGED_CODE();

    //
    // Check to make sure FreeType is good.
    //

    if ((FreeType & ~(MEM_DECOMMIT | MEM_RELEASE)) != 0) {
        return STATUS_INVALID_PARAMETER_4;
    }

    //
    // One of MEM_DECOMMIT or MEM_RELEASE must be specified, but not both.
    //

    if (((FreeType & (MEM_DECOMMIT | MEM_RELEASE)) == 0) ||
        ((FreeType & (MEM_DECOMMIT | MEM_RELEASE)) ==
                            (MEM_DECOMMIT | MEM_RELEASE))) {
        return STATUS_INVALID_PARAMETER_4;
    }

    PreviousMode = KeGetPreviousMode();

    //
    // Establish an exception handler, probe the specified addresses
    // for write access and capture the initial values.
    //

    try {

        if (PreviousMode != KernelMode) {

            ProbeForWriteUlong ((PULONG)BaseAddress);
            ProbeForWriteUlong (RegionSize);
        }

        //
        // Capture the base address.
        //

        CapturedBase = *BaseAddress;

        //
        // Capture the region size.
        //

        CapturedRegionSize = *RegionSize;

    } except (ExSystemExceptionFilter()) {

        //
        // If an exception occurs during the probe or capture
        // of the initial values, then handle the exception and
        // return the exception code as the status value.
        //

        return GetExceptionCode();
    }

#if DBG
    if (MmDebug & MM_DBG_SHOW_NT_CALLS) {
        if ( !MmWatchProcess ) {
            DbgPrint("freevm processhandle %lx base %lx size %lx type %lx\n",
                    ProcessHandle, CapturedBase, CapturedRegionSize, FreeType);
        }
    }
#endif

    //
    // Make sure the specified starting and ending addresses are
    // within the user part of the virtual address space.
    //

    if (CapturedBase > MM_HIGHEST_USER_ADDRESS) {

        //
        // Invalid base address.
        //

        return STATUS_INVALID_PARAMETER_2;
    }

    if ((ULONG)MM_HIGHEST_USER_ADDRESS - (ULONG)CapturedBase <
                                                        CapturedRegionSize) {

        //
        // Invalid region size;
        //

        return STATUS_INVALID_PARAMETER_3;

    }

    EndingAddress = (PVOID)(((ULONG)CapturedBase + CapturedRegionSize - 1) |
                        (PAGE_SIZE - 1));

    StartingAddress = (PVOID)PAGE_ALIGN(CapturedBase);

    if ( ProcessHandle == NtCurrentProcess() ) {
        Process = PsGetCurrentProcess();
    } else {
        //
        // Reference the specified process handle for VM_OPERATION access.
        //

        Status = ObReferenceObjectByHandle ( ProcessHandle,
                                             PROCESS_VM_OPERATION,
                                             PsProcessType,
                                             PreviousMode,
                                             (PVOID *)&Process,
                                             NULL );

        if (!NT_SUCCESS(Status)) {
            return Status;
        }
    }

    //
    // If the specified process is not the current process, attach
    // to the specified process.
    //

    if (PsGetCurrentProcess() != Process) {
        KeAttachProcess (&Process->Pcb);
        Attached = TRUE;
    }

    //
    // Get the address creation mutex to block multiple threads from
    // creating or deleting address space at the same time and
    // get the working set mutex so virtual address descriptors can
    // be inserted and walked.  Block APCs to prevent page faults while
    // we own the working set mutex.
    //

    LOCK_WS_AND_ADDRESS_SPACE (Process);

    //
    // Make sure the address space was not deleted.
    //

    if (Process->AddressSpaceDeleted != 0) {
        Status = STATUS_PROCESS_IS_TERMINATING;
        goto ErrorReturn;
    }

    Vad = (PMMVAD_SHORT)MiLocateAddress (StartingAddress);

    if (Vad == NULL) {

        //
        // No Virtual Address Descriptor located for Base Address.
        //

        Status = STATUS_MEMORY_NOT_ALLOCATED;
        goto ErrorReturn;
    }

    //
    // Found the associated Virtual Address Descriptor.
    //

    if (Vad->EndingVa < EndingAddress) {

        //
        // The entire range to delete is not contained within a single
        // virtual address descriptor.  Return an error.
        //

        Status = STATUS_UNABLE_TO_FREE_VM;
        goto ErrorReturn;
    }

    //
    // Check to ensure this Vad is deletable.  Delete is required
    // for both decommit and release.
    //

    if ((Vad->u.VadFlags.PrivateMemory == 0) ||
        (Vad->u.VadFlags.PhysicalMapping == 1)) {
        Status = STATUS_UNABLE_TO_DELETE_SECTION;
        goto ErrorReturn;
    }

    if (Vad->u.VadFlags.NoChange == 1) {

        //
        // An attempt is being made to delete a secured VAD, check
        // to see if this deletion is allowed.
        //

        if (FreeType & MEM_RELEASE) {

            //
            // Specifiy the whole range, this solves the problem with
            // splitting the VAD and trying to decide where the various
            // secure ranges need to go.
            //

            Status = MiCheckSecuredVad ((PMMVAD)Vad,
                                        Vad->StartingVa,
                                (PCHAR)Vad->EndingVa - (PCHAR)Vad->StartingVa,
                                        MM_SECURE_DELETE_CHECK);

        } else {
            Status = MiCheckSecuredVad ((PMMVAD)Vad,
                                        CapturedBase,
                                        CapturedRegionSize,
                                        MM_SECURE_DELETE_CHECK);
        }
        if (!NT_SUCCESS (Status)) {
            goto ErrorReturn;
        }
    }

    PreviousVad = MiGetPreviousVad (Vad);
    NextVad = MiGetNextVad (Vad);
    if (FreeType & MEM_RELEASE) {

        //
        // *****************************************************************
        // MEM_RELEASE was specified.
        // *****************************************************************
        //

        //
        // The descriptor for the address range is deletable.  Remove or split
        // the descriptor.
        //

        //
        // If the region size is zero, remove the whole VAD.
        //

        if (CapturedRegionSize == 0) {

            //
            // If the region size is specified as 0, the base address
            // must be the starting address for the region.
            //

            if (CapturedBase != Vad->StartingVa) {
                Status = STATUS_FREE_VM_NOT_AT_BASE;
                goto ErrorReturn;
            }

            //
            // This Virtual Address Descriptor has been deleted.
            //

            StartingAddress = Vad->StartingVa;
            EndingAddress = Vad->EndingVa;
            MiRemoveVad ((PMMVAD)Vad);
            ExFreePool (Vad);

        } else {

            //
            // Regions size was not specified as zero, delete the
            // whole VAD or split the VAD.
            //

            if (StartingAddress == Vad->StartingVa) {
                if (EndingAddress == Vad->EndingVa) {

                    //
                    // This Virtual Address Descriptor has been deleted.
                    //

                    MiRemoveVad ((PMMVAD)Vad);
                    ExFreePool (Vad);

                } else {

                    //
                    // This Virtual Address Descriptor has a new starting
                    // address.
                    //

                    CommitReduction = MiCalculatePageCommitment (
                                                            StartingAddress,
                                                            EndingAddress,
                                                            (PMMVAD)Vad,
                                                            Process );

                    Vad->StartingVa = (PVOID)((ULONG)EndingAddress + 1L);
                    Vad->u.VadFlags.CommitCharge -= CommitReduction;
                    ASSERT ((LONG)Vad->u.VadFlags.CommitCharge >= 0);
                    MiReturnPageFileQuota (CommitReduction, Process);
                    MiReturnCommitment (CommitReduction);
                    Process->CommitCharge -= CommitReduction;
                    PreviousVad = (PMMVAD)Vad;
                }

            } else {

                //
                // Starting address is greater than start of VAD.
                //

                if (EndingAddress == Vad->EndingVa) {

                    //
                    // Change the ending address of the VAD.
                    //

                    CommitReduction = MiCalculatePageCommitment (
                                                            StartingAddress,
                                                            EndingAddress,
                                                            (PMMVAD)Vad,
                                                            Process );

                    Vad->u.VadFlags.CommitCharge -= CommitReduction;
                    MiReturnPageFileQuota (CommitReduction, Process);
                    MiReturnCommitment (CommitReduction);
                    Process->CommitCharge -= CommitReduction;

                    Vad->EndingVa = (PVOID)((ULONG)StartingAddress - 1L);
                    PreviousVad = (PMMVAD)Vad;

                } else {

                    //
                    // Split this VAD as the address range is within the VAD.
                    //

                    //
                    // Allocate an new VAD under an exception handler
                    // as there may not be enough quota.
                    //

                    NewVad = ExAllocatePoolWithTag (NonPagedPool,
                                                    sizeof(MMVAD_SHORT),
                                                    'SdaV');
                    if ( NewVad == NULL ) {
                        Status = STATUS_INSUFFICIENT_RESOURCES;
                        goto ErrorReturn;
                    }

                    CommitReduction = MiCalculatePageCommitment (
                                                            StartingAddress,
                                                            EndingAddress,
                                                            (PMMVAD)Vad,
                                                            Process );

                    OldQuota = Vad->u.VadFlags.CommitCharge - CommitReduction;
                    OldEnd = Vad->EndingVa;

                    *NewVad = *Vad;

                    Vad->EndingVa = (PVOID)((ULONG)StartingAddress - 1L);
                    NewVad->StartingVa = (PVOID)((ULONG)EndingAddress + 1L);

                    //
                    // Set the commit charge to zero so MiInsertVad will
                    // not charge committment for splitting the VAD.
                    //

                    NewVad->u.VadFlags.CommitCharge = 0;

                    try {

                        //
                        // Insert the VAD, this could get an exception
                        // on charging quota.
                        //

                        MiInsertVad ((PMMVAD)NewVad);

                    } except (EXCEPTION_EXECUTE_HANDLER) {

                        //
                        // Inserting the Vad failed, reset the original
                        // VAD, free new vad and return an error.
                        //

                        Vad->EndingVa = OldEnd;

                        ExFreePool (NewVad);
                        Status = GetExceptionCode();
                        goto ErrorReturn;
                    }

                    Vad->u.VadFlags.CommitCharge -= CommitReduction;
                    MiReturnPageFileQuota (CommitReduction, Process);
                    MiReturnCommitment (CommitReduction);
                    Process->CommitCharge -= CommitReduction;

                    //
                    // As we have split the original VAD into 2 seperate VADs
                    // there is know way of knowing what the commit charge
                    // is for each VAD.  Calculate the charge and reset
                    // each VAD.  Note that we also use the previous value
                    // to make sure the books stay balanced.
                    //

                    QuotaCharge = MiCalculatePageCommitment (Vad->StartingVa,
                                                             Vad->EndingVa,
                                                             (PMMVAD)Vad,
                                                             Process );

                    Vad->u.VadFlags.CommitCharge = QuotaCharge;

                    //
                    // Give the remaining charge to the new VAD.
                    //

                    NewVad->u.VadFlags.CommitCharge = OldQuota - QuotaCharge;
                    PreviousVad = (PMMVAD)Vad;
                    NextVad = (PMMVAD)NewVad;
                }
            }
        }

        //
        // Return commitment for page table pages if possibible.
        //

        MiReturnPageTablePageCommitment (StartingAddress,
                                         EndingAddress,
                                         Process,
                                         PreviousVad,
                                         NextVad);

        //
        // Get the PFN mutex so the MiDeleteVirtualAddresses can be called.
        //

        MiDeleteFreeVm (StartingAddress, EndingAddress);
        UNLOCK_WS (Process);

        CapturedRegionSize = 1 + (ULONG)EndingAddress - (ULONG)StartingAddress;

        //
        // Update the virtual size in the process header.
        //

        Process->VirtualSize -= CapturedRegionSize;

        UNLOCK_ADDRESS_SPACE (Process);

        if (Attached) {
            KeDetachProcess();
        }

        if ( ProcessHandle != NtCurrentProcess() ) {
            ObDereferenceObject (Process);
        }
        //
        // Establish an exception handler and write the size and base
        // address.
        //

        try {

            *RegionSize = CapturedRegionSize;
            *BaseAddress = StartingAddress;

        } except (EXCEPTION_EXECUTE_HANDLER) {

            //
            // An exception occurred, don't take any action (just handle
            // the exception and return success.

        }

#if DBG
    if (MmDebug & MM_DBG_SHOW_NT_CALLS) {
        if ( MmWatchProcess ) {
            if ( MmWatchProcess == PsGetCurrentProcess() ) {
                DbgPrint("\n--- FREE Type 0x%lx Base %lx Size %lx\n",
                        FreeType, StartingAddress, CapturedRegionSize);
                MmFooBar();
            }
        }
    }
#endif

#if DBG
        if (RtlAreLogging( RTL_EVENT_CLASS_VM )) {
            RtlLogEvent( MiFreeVmEventId,
                         RTL_EVENT_CLASS_VM,
                         StartingAddress,
                         CapturedRegionSize,
                         FreeType
                       );

        }
#endif // DBG

        return STATUS_SUCCESS;
    }

    //
    // **************************************************************
    //
    // MEM_DECOMMIT was specified.
    //
    // **************************************************************
    //

    //
    // Check to ensure the complete range of pages is already committed.
    //

    if (CapturedRegionSize == 0) {

        if (CapturedBase != Vad->StartingVa) {
            Status = STATUS_FREE_VM_NOT_AT_BASE;
            goto ErrorReturn;
        }
        EndingAddress = Vad->EndingVa;
    }

#if 0
    if (FreeType & MEM_CHECK_COMMIT_STATE) {
        if ( !MiIsEntireRangeCommitted(StartingAddress,
                                       EndingAddress,
                                       Vad,
                                       Process)) {

            //
            // The entire range to be decommited is not committed,
            // return an errror.
            //

            Status = STATUS_UNABLE_TO_DECOMMIT_VM;
            goto ErrorReturn;
        }
    }
#endif //0

    //
    // The address range is entirely committed, decommit it now.
    //

    //
    // Calculate the initial quotas and commit charges for this VAD.
    //

    StartingPte = MiGetPteAddress (StartingAddress);
    EndingPte = MiGetPteAddress (EndingAddress);

    CommitReduction = 1 + EndingPte - StartingPte;

    //
    // Check to see if the entire range can be decommitted by
    // just updating the virtual address descriptor.
    //

    CommitReduction -= MiDecommitPages (StartingAddress,
                                        EndingPte,
                                        Process,
                                        Vad);

    //
    // Adjust the quota charges.
    //

    ASSERT ((LONG)CommitReduction >= 0);
    MiReturnPageFileQuota (CommitReduction, Process);
    MiReturnCommitment (CommitReduction);
    Vad->u.VadFlags.CommitCharge -= CommitReduction;
    Process->CommitCharge -= CommitReduction;
    ASSERT ((LONG)Vad->u.VadFlags.CommitCharge >= 0);

    UNLOCK_WS (Process);

    UNLOCK_ADDRESS_SPACE (Process);

    if (Attached) {
        KeDetachProcess();
    }
    if ( ProcessHandle != NtCurrentProcess() ) {
        ObDereferenceObject (Process);
    }

    //
    // Establish an exception handler and write the size and base
    // address.
    //

    try {

        *RegionSize = 1 + (ULONG)EndingAddress - (ULONG)StartingAddress;
        *BaseAddress = StartingAddress;

    } except (EXCEPTION_EXECUTE_HANDLER) {
        NOTHING;
    }

#if DBG
    if (RtlAreLogging( RTL_EVENT_CLASS_VM )) {
        RtlLogEvent( MiFreeVmEventId,
                     RTL_EVENT_CLASS_VM,
                     StartingAddress,
                     1 + (ULONG)EndingAddress - (ULONG)StartingAddress,
                     FreeType
                   );

    }
#endif // DBG

    return STATUS_SUCCESS;

ErrorReturn:
       UNLOCK_WS (Process);
       UNLOCK_ADDRESS_SPACE (Process);

       if (Attached) {
           KeDetachProcess();
       }

       if ( ProcessHandle != NtCurrentProcess() ) {
           ObDereferenceObject (Process);
       }
       return Status;
}