test: readwrt.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# readwrt.c File Reference

`#include "mi.h"`

Go to the source code of this file.

## Defines

#define | MAX_LOCK_SIZE ((ULONG)(14 * PAGE_SIZE))
#define | MAX_MOVE_SIZE (LONG)0x10000
#define | MINIMUM_ALLOCATION (LONG)128
#define | POOL_MOVE_THRESHOLD 511
#define | COPY_STACK_SIZE 64

## Functions

NTSTATUS | MiValidateUserTransfer (IN PVOID BaseAddress, IN PVOID Buffer, IN ULONG BufferSize)
ULONG | MiGetExceptionInfo (IN PEXCEPTION_POINTERS ExceptionPointers, IN PULONG_PTR BadVa1, IN PULONG_PTR BadVa2)
NTSTATUS | MiDoMappedCopy (IN PEPROCESS FromProcess, IN PVOID FromAddress, IN PEPROCESS ToProcess, OUT PVOID ToAddress, IN ULONG BufferSize, IN KPROCESSOR_MODE PreviousMode, OUT PULONG NumberOfBytesRead)
NTSTATUS | MiDoPoolCopy (IN PEPROCESS FromProcess, IN PVOID FromAddress, IN PEPROCESS ToProcess, OUT PVOID ToAddress, IN ULONG BufferSize, IN KPROCESSOR_MODE PreviousMode, OUT PULONG NumberOfBytesRead)
NTSTATUS | NtReadVirtualMemory (IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID Buffer, IN ULONG BufferSize, OUT PULONG NumberOfBytesRead OPTIONAL)
NTSTATUS | NtWriteVirtualMemory (IN HANDLE ProcessHandle, OUT PVOID BaseAddress, IN PVOID Buffer, IN ULONG BufferSize, OUT PULONG NumberOfBytesWritten OPTIONAL)
NTSTATUS | MmCopyVirtualMemory (IN PEPROCESS FromProcess, IN PVOID FromAddress, IN PEPROCESS ToProcess, OUT PVOID ToAddress, IN ULONG BufferSize, IN KPROCESSOR_MODE PreviousMode, OUT PULONG NumberOfBytesCopied)

## Define Documentation

#define COPY_STACK_SIZE 64

| Definition at line 99 of file readwrt.c.

#define MAX_LOCK_SIZE ((ULONG)(14 * PAGE_SIZE))

| Definition at line 30 of file readwrt.c. Referenced by MiDoMappedCopy().

#define MAX_MOVE_SIZE (LONG)0x10000

| Definition at line 36 of file readwrt.c. Referenced by MiDoPoolCopy().

#define MINIMUM_ALLOCATION (LONG)128

| Definition at line 42 of file readwrt.c.

#define POOL_MOVE_THRESHOLD 511

| Definition at line 48 of file readwrt.c. Referenced by MmCopyVirtualMemory().

## Function Documentation

NTSTATUS MiDoMappedCopy | ( | IN PEPROCESS | FromProcess,
|  | IN PVOID | FromAddress,
|  | IN PEPROCESS | ToProcess,
|  | OUT PVOID | ToAddress,
|  | IN ULONG | BufferSize,
|  | IN KPROCESSOR_MODE | PreviousMode,
|  | OUT PULONG | NumberOfBytesRead
| ) |

Definition at line 529 of file readwrt.c.

References BufferSize, CHAR, ExRaiseStatus(), FALSE, HighPagePriority, IoReadAccess, KeAttachProcess(), KeDetachProcess(), KernelMode, MAX_LOCK_SIZE, MiGetExceptionInfo(), MmCached, MmInitializeMdl, MmMapLockedPagesSpecifyCache(), MmProbeAndLockPages(), MmUnlockPages(), MmUnmapLockedPages(), NULL, PAGE_SHIFT, PAGED_CODE, ProbeForRead, ProbeForWrite(), PsGetCurrentProcess, and TRUE.

Referenced by MmCopyVirtualMemory().

    00541                    :
    00542
    00543     This function copies the specified address range from the specified
    00544     process into the specified address range of the current process.
    00545
    00546 Arguments:
    00547
    00548      FromProcess - Supplies an open handle to a process object.
    00549
    00550      FromAddress - Supplies the base address in the specified process
    00551                    to be read.
    00552
    00553      ToProcess - Supplies an open handle to a process object.
    00554
    00555      ToAddress - Supplies the address of a buffer which receives the
    00556                  contents from the specified process address space.
    00557
    00558      BufferSize - Supplies the requested number of bytes to read from
    00559                   the specified process.
    00560
    00561      PreviousMode - Supplies the previous processor mode.
    00562
    00563      NumberOfBytesRead - Receives the actual number of bytes
    00564                          transferred into the specified buffer.
    00565
    00566 Return Value:
    00567
    00568     TBS
    00569
    00570 --*/
    00571
    00572 {
    00573
    00574     ULONG AmountToMove;
    00575     ULONG_PTR BadVa1;
    00576     ULONG_PTR BadVa2;
    00577     PEPROCESS CurrentProcess;
    00578     LOGICAL Moving;
    00579     LOGICAL Probing;
    00580     BOOLEAN LockedMdlPages;
    00581     PVOID InVa;
    00582     ULONG LeftToMove;
    00583     PULONG MappedAddress;
    00584     ULONG MaximumMoved;
    00585     PMDL Mdl;
    00586     PFN_NUMBER MdlHack[(sizeof(MDL)/sizeof(PFN_NUMBER)) + (MAX_LOCK_SIZE >> PAGE_SHIFT) + 1];
    00587     PVOID OutVa;
    00588     LOGICAL MappingFailed;
    00589
    00590     PAGED_CODE();
    00591
    00592     MappingFailed = FALSE;
    00593
    00594     //
    00595     // Get the address of the current process object and initialize copy
    00596     // parameters.
    00597     //
    00598
    00599     CurrentProcess = PsGetCurrentProcess();
    00600
    00601     InVa = FromAddress;
    00602     OutVa = ToAddress;
    00603
    00604     MaximumMoved = MAX_LOCK_SIZE;
    00605     if (BufferSize <= MAX_LOCK_SIZE) {
    00606         MaximumMoved = BufferSize;
    00607     }
    00608
    00609     Mdl = (PMDL)&MdlHack[0];
    00610
    00611     //
    00612     // Map the data into the system part of the address space, then copy it.
    00613     //
    00614
    00615     LeftToMove = BufferSize;
    00616     AmountToMove = MaximumMoved;
    00617     while (LeftToMove > 0) {
    00618
    00619         if (LeftToMove < AmountToMove) {
    00620
    00621             //
    00622             // Set to move the remaining bytes.
    00623             //
    00624
    00625             AmountToMove = LeftToMove;
    00626         }
    00627
    00628         KeDetachProcess();
    00629         KeAttachProcess (&FromProcess->Pcb);
    00630
    00631         //
    00632         // We may be touching a user's memory which could be invalid,
    00633         // declare an exception handler.
    00634         //
    00635
    00636         try {
    00637
    00638             //
    00639             // Probe to make sure that the specified buffer is accessible in
    00640             // the target process.
    00641             //
    00642
    00643             MappedAddress = NULL;
    00644             LockedMdlPages = FALSE;
    00645
    00646             if ((InVa == FromAddress) && (PreviousMode != KernelMode)){
    00647                 Probing = TRUE;
    00648                 ProbeForRead (FromAddress, BufferSize, sizeof(CHAR));
    00649             }
    00650             Probing = FALSE;
    00651
    00652             //
    00653             // Initialize MDL for request.
    00654             //
    00655
    00656             MmInitializeMdl (Mdl, (PVOID)InVa, AmountToMove);
    00657
    00658             Moving = TRUE;
    00659             MmProbeAndLockPages (Mdl, PreviousMode, IoReadAccess);
    00660             Moving = FALSE;
    00661
    00662             LockedMdlPages = TRUE;
    00663
    00664             MappedAddress = MmMapLockedPagesSpecifyCache (Mdl,
    00665                                                           KernelMode,
    00666                                                           MmCached,
    00667                                                           NULL,
    00668                                                           FALSE,
    00669                                                           HighPagePriority);
    00670
    00671             if (MappedAddress == NULL) {
    00672                 MappingFailed = TRUE;
    00673                 ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
    00674             }
    00675
    00676             //
    00677             // Deattach from the FromProcess and attach to the ToProcess.
    00678             //
    00679
    00680             KeDetachProcess();
    00681             KeAttachProcess (&ToProcess->Pcb);
    00682
    00683             //
    00684             // Now operating in the context of the ToProcess.
    00685             //
    00686             if ((InVa == FromAddress) && (PreviousMode != KernelMode)){
    00687                 Probing = TRUE;
    00688                 ProbeForWrite (ToAddress, BufferSize, sizeof(CHAR));
    00689             }
    00690             Probing = FALSE;
    00691
    00692             RtlCopyMemory (OutVa, MappedAddress, AmountToMove);
    00693
    00694         } except (MiGetExceptionInfo (GetExceptionInformation(),
    00695                                       &BadVa1,
    00696                                       &BadVa2)) {
    00697
    00698
    00699             //
    00700             // If an exception occurs during the move operation or probe,
    00701             // return the exception code as the status value.
    00702             //
    00703
    00704             KeDetachProcess();
    00705             if (MappedAddress != NULL) {
    00706                 MmUnmapLockedPages (MappedAddress, Mdl);
    00707             }
    00708             if (LockedMdlPages == TRUE) {
    00709                 MmUnlockPages (Mdl);
    00710             }
    00711
    00712             if (GetExceptionCode() == STATUS_WORKING_SET_QUOTA) {
    00713                 return STATUS_WORKING_SET_QUOTA;
    00714             }
    00715
    00716             if ((Probing == TRUE) || (MappingFailed == TRUE)) {
    00717                 return GetExceptionCode();
    00718
    00719             } else {
    00720
    00721                 //
    00722                 // The failure occurred during the move operation, determine
    00723                 // which move failed, and calculate the number of bytes
    00724                 // actually moved.
    00725                 //
    00726
    00727                 if (Moving == TRUE) {
    00728                     if (BadVa1 != 0xFFFFFFFF) {
    00729                         *NumberOfBytesRead = (ULONG)((ULONG_PTR)BadVa2 - (ULONG_PTR)FromAddress);
    00730                     }
    00731
    00732                 } else {
    00733                     *NumberOfBytesRead = BufferSize - LeftToMove;
    00734                 }
    00735             }
    00736
    00737             return STATUS_PARTIAL_COPY;
    00738         }
    00739         MmUnmapLockedPages (MappedAddress, Mdl);
    00740         MmUnlockPages (Mdl);
    00741
    00742         LeftToMove -= AmountToMove;
    00743         InVa = (PVOID)((ULONG_PTR)InVa + AmountToMove);
    00744         OutVa = (PVOID)((ULONG_PTR)OutVa + AmountToMove);
    00745     }
    00746
    00747     KeDetachProcess();
    00748
    00749     //
    00750     // Set number of bytes moved.
    00751     //
    00752
    00753     *NumberOfBytesRead = BufferSize;
    00754     return STATUS_SUCCESS;
    00755 }

NTSTATUS MiDoPoolCopy | ( | IN PEPROCESS | FromProcess,
|  | IN PVOID | FromAddress,
|  | IN PEPROCESS | ToProcess,
|  | OUT PVOID | ToAddress,
|  | IN ULONG | BufferSize,
|  | IN KPROCESSOR_MODE | PreviousMode,
|  | OUT PULONG | NumberOfBytesRead
| ) |

Definition at line 758 of file readwrt.c.

References ASSERT, BufferSize, CHAR, COPY_STACK_SIZE, ExAllocatePoolWithTag, ExFreePool(), FALSE, KeAttachProcess(), KeDetachProcess(), KernelMode, MAX_MOVE_SIZE, MiGetExceptionInfo(), NonPagedPool, NULL, PAGED_CODE, ProbeForRead, ProbeForWrite(), PsGetCurrentProcess, and TRUE.

Referenced by MmCopyVirtualMemory().

    00770                    :
    00771
    00772     This function copies the specified address range from the specified
    00773     process into the specified address range of the current process.
    00774
    00775 Arguments:
    00776
    00777      ProcessHandle - Supplies an open handle to a process object.
    00778
    00779      BaseAddress - Supplies the base address in the specified process
    00780                    to be read.
    00781
    00782      Buffer - Supplies the address of a buffer which receives the
    00783               contents from the specified process address space.
    00784
    00785      BufferSize - Supplies the requested number of bytes to read from
    00786                   the specified process.
    00787
    00788      PreviousMode - Supplies the previous processor mode.
    00789
    00790      NumberOfBytesRead - Receives the actual number of bytes
    00791                          transferred into the specified buffer.
    00792
    00793 Return Value:
    00794
    00795     TBS
    00796
    00797 --*/
    00798
    00799 {
    00800
    00801     ULONG AmountToMove;
    00802     ULONG_PTR BadVa1;
    00803     ULONG_PTR BadVa2;
    00804     PEPROCESS CurrentProcess;
    00805     LOGICAL Moving;
    00806     LOGICAL Probing;
    00807     PVOID InVa;
    00808     ULONG LeftToMove;
    00809     ULONG MaximumMoved;
    00810     PVOID OutVa;
    00811     PVOID PoolArea;
    00812     LONGLONG StackArray[COPY_STACK_SIZE];
    00813     ULONG FreePool;
    00814
    00815     PAGED_CODE();
    00816
    00817     ASSERT (BufferSize != 0);
    00818
    00819     //
    00820     // Get the address of the current process object and initialize copy
    00821     // parameters.
    00822     //
    00823
    00824     CurrentProcess = PsGetCurrentProcess();
    00825
    00826     InVa = FromAddress;
    00827     OutVa = ToAddress;
    00828
    00829     //
    00830     // Allocate non-paged memory to copy in and out of.
    00831     //
    00832
    00833     MaximumMoved = MAX_MOVE_SIZE;
    00834     if (BufferSize <= MAX_MOVE_SIZE) {
    00835         MaximumMoved = BufferSize;
    00836     }
    00837
    00838     FreePool = FALSE;
    00839     if (BufferSize <= sizeof(StackArray)) {
    00840         PoolArea = (PULONG)&StackArray[0];
    00841     } else {
    00842         do {
    00843             PoolArea = ExAllocatePoolWithTag (NonPagedPool, MaximumMoved, 'wRmM');
    00844             if (PoolArea != NULL) {
    00845                 FreePool = TRUE;
    00846                 break;
    00847             }
    00848
    00849             MaximumMoved = MaximumMoved >> 1;
    00850             if (MaximumMoved <= sizeof(StackArray)) {
    00851                 PoolArea = (PULONG)&StackArray[0];
    00852                 break;
    00853             }
    00854         } while (TRUE);
    00855     }
    00856
    00857     //
    00858     // Copy the data into pool, then copy back into the ToProcess.
    00859     //
    00860
    00861     LeftToMove = BufferSize;
    00862     AmountToMove = MaximumMoved;
    00863     while (LeftToMove > 0) {
    00864
    00865         if (LeftToMove < AmountToMove) {
    00866
    00867             //
    00868             // Set to move the remaining bytes.
    00869             //
    00870
    00871             AmountToMove = LeftToMove;
    00872         }
    00873
    00874         KeDetachProcess();
    00875         KeAttachProcess (&FromProcess->Pcb);
    00876
    00877         //
    00878         // We may be touching a user's memory which could be invalid,
    00879         // declare an exception handler.
    00880         //
    00881
    00882         try {
    00883
    00884             //
    00885             // Probe to make sure that the specified buffer is accessible in
    00886             // the target process.
    00887             //
    00888
    00889             if ((InVa == FromAddress) && (PreviousMode != KernelMode)){
    00890                 Probing = TRUE;
    00891                 ProbeForRead (FromAddress, BufferSize, sizeof(CHAR));
    00892             }
    00893
    00894             Probing = FALSE;
    00895
    00896             Moving = TRUE;
    00897
    00898             RtlCopyMemory (PoolArea, InVa, AmountToMove);
    00899
    00900             Moving = FALSE;
    00901
    00902             KeDetachProcess();
    00903             KeAttachProcess (&ToProcess->Pcb);
    00904
    00905             //
    00906             // Now operating in the context of the ToProcess.
    00907             //
    00908
    00909             if ((InVa == FromAddress) && (PreviousMode != KernelMode)){
    00910                 Probing = TRUE;
    00911                 ProbeForWrite (ToAddress, BufferSize, sizeof(CHAR));
    00912             }
    00913             Probing = FALSE;
    00914
    00915             RtlCopyMemory (OutVa, PoolArea, AmountToMove);
    00916
    00917         } except (MiGetExceptionInfo (GetExceptionInformation(),
    00918                                       &BadVa1,
    00919                                       &BadVa2)) {
    00920
    00921             //
    00922             // If an exception occurs during the move operation or probe,
    00923             // return the exception code as the status value.
    00924             //
    00925
    00926             KeDetachProcess();
    00927
    00928             if (FreePool) {
    00929                 ExFreePool (PoolArea);
    00930             }
    00931             if (Probing == TRUE) {
    00932                 return GetExceptionCode();
    00933
    00934             } else {
    00935
    00936                 //
    00937                 // The failure occurred during the move operation, determine
    00938                 // which move failed, and calculate the number of bytes
    00939                 // actually moved.
    00940                 //
    00941
    00942                 if (Moving == TRUE) {
    00943
    00944                     //
    00945                     // The failure occurred getting the data.
    00946                     //
    00947
    00948                     if (BadVa1 != 0xFFFFFFFF) {
    00949                         *NumberOfBytesRead = (ULONG)((ULONG_PTR)(BadVa2 - (ULONG_PTR)FromAddress));
    00950                     }
    00951
    00952                 } else {
    00953
    00954                     //
    00955                     // The failure occurred writing the data.
    00956                     //
    00957
    00958                     *NumberOfBytesRead = BufferSize - LeftToMove;
    00959                 }
    00960             }
    00961
    00962             return STATUS_PARTIAL_COPY;
    00963         }
    00964
    00965         LeftToMove -= AmountToMove;
    00966         InVa = (PVOID)((ULONG_PTR)InVa + AmountToMove);
    00967         OutVa = (PVOID)((ULONG_PTR)OutVa + AmountToMove);
    00968     }
    00969
    00970     if (FreePool) {
    00971         ExFreePool (PoolArea);
    00972     }
    00973     KeDetachProcess();
    00974
    00975     //
    00976     // Set number of bytes moved.
    00977     //
    00978
    00979     *NumberOfBytesRead = BufferSize;
    00980     return STATUS_SUCCESS;
    00981 }

ULONG MiGetExceptionInfo | ( | IN PEXCEPTION_POINTERS | ExceptionPointers,
|  | IN PULONG_PTR | BadVa1,
|  | IN PULONG_PTR | BadVa2
| ) |

Definition at line 464 of file readwrt.c.

References EXCEPTION_EXECUTE_HANDLER, and PAGED_CODE.

Referenced by MiDoMappedCopy(), and MiDoPoolCopy().

    00472                    :
    00473
    00474     This routine examines a exception record and extracts the virtual
    00475     address of an access violation, guard page violation, or in-page error.
    00476
    00477 Arguments:
    00478
    00479     ExceptionPointers - Supplies a pointer to the exception record.
    00480
    00481     BadVa - Receives the virtual address which caused the access violation.
    00482
    00483 Return Value:
    00484
    00485     EXECUTE_EXCEPTION_HANDLER
    00486
    00487 --*/
    00488
    00489 {
    00490     PEXCEPTION_RECORD ExceptionRecord;
    00491
    00492     PAGED_CODE();
    00493
    00494     //
    00495     // If the exception code is an access violation, guard page violation,
    00496     // or an in-page read error, then return the faulting address. Otherwise.
    00497     // return a special address value.
    00498     //
    00499
    00500     *BadVa2 = 0;
    00501     ExceptionRecord = ExceptionPointers->ExceptionRecord;
    00502     if ((ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) ||
    00503         (ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) ||
    00504         (ExceptionRecord->ExceptionCode == STATUS_IN_PAGE_ERROR)) {
    00505
    00506         //
    00507         // The virtual address which caused the exception is the 2nd
    00508         // parameter in the exception information array.
    00509         //
    00510
    00511         *BadVa1 = ExceptionRecord->ExceptionInformation[1];
    00512         if (ExceptionRecord->NumberParameters == 3) {
    00513             *BadVa2 = ExceptionRecord->ExceptionInformation[2];
    00514         }
    00515
    00516     } else {
    00517
    00518         //
    00519         // Unexpected exception - set the number of bytes copied to zero.
    00520         //
    00521
    00522         *BadVa2 = 0xFFFFFFFF;
    00523     }
    00524
    00525     return EXCEPTION_EXECUTE_HANDLER;
    00526 }

NTSTATUS MiValidateUserTransfer | ( | IN PVOID | BaseAddress,
|  | IN PVOID | Buffer,
|  | IN ULONG | BufferSize
| ) |

Definition at line 985 of file readwrt.c.

References Buffer, BufferSize, and PAGED_CODE.

Referenced by NtReadVirtualMemory(), and NtWriteVirtualMemory().

    00993                    :
    00994
    00995     This function checks whether the parameter source and destination address
    00996     ranges lie within the user virtual address space.  This function does NOT
    00997     guarantee that the addresses are in fact mapped or that faults will not
    00998     occur - it just validates the address range.
    00999
    01000 Arguments:
    01001
    01002      BaseAddress - Supplies the base address within a process to be read.
    01003
    01004      Buffer - Supplies the address of a buffer which sends or receives the
    01005               contents from the specified process address space.
    01006
    01007      BufferSize - Supplies the requested number of bytes to read or write from
    01008                   the specified process.
    01009
    01010 Return Value:
    01011
    01012     STATUS_SUCCESS if valid user ranges, error otherwise.
    01013
    01014 Environment:
    01015
    01016     None.
    01017
    01018 --*/
    01019
    01020 {
    01021     ULONG_PTR   BaseAddress;
    01022     ULONG_PTR   Buffer;
    01023
    01024     BaseAddress = (ULONG_PTR)BaseAddressPointer;
    01025     Buffer = (ULONG_PTR)BufferPointer;
    01026
    01027     PAGED_CODE();
    01028
    01029     //
    01030     // check that both the base address and the target buffer qualify
    01031     // as valid user address ranges.  Wrapping is not allowed.
    01032     //
    01033     if (BaseAddress + BufferSize < BaseAddress) {
    01034         return STATUS_ACCESS_VIOLATION;
    01035     }
    01036
    01037     if (((PVOID)BaseAddress > MM_HIGHEST_USER_ADDRESS) ||
    01038         ((PVOID)(BaseAddress + BufferSize) > MM_HIGHEST_USER_ADDRESS)) {
    01039
    01040             return STATUS_ACCESS_VIOLATION;
    01041     }
    01042
    01043     if (Buffer + BufferSize < Buffer) {
    01044         return STATUS_ACCESS_VIOLATION;
    01045     }
    01046
    01047     if (((PVOID)Buffer > MM_HIGHEST_USER_ADDRESS) ||
    01048         ((PVOID)(Buffer + BufferSize) > MM_HIGHEST_USER_ADDRESS)) {
    01049
    01050             return STATUS_ACCESS_VIOLATION;
    01051     }
    01052
    01053     return STATUS_SUCCESS;
    01054 }
    }

NTSTATUS MmCopyVirtualMemory | ( | IN PEPROCESS | FromProcess,
|  | IN PVOID | FromAddress,
|  | IN PEPROCESS | ToProcess,
|  | OUT PVOID | ToAddress,
|  | IN ULONG | BufferSize,
|  | IN KPROCESSOR_MODE | PreviousMode,
|  | OUT PULONG | NumberOfBytesCopied
| ) |

Definition at line 362 of file readwrt.c.

References _EPROCESS::AddressSpaceDeleted, ASSERT, BufferSize, FALSE, KeSetEvent(), MiDoMappedCopy(), MiDoPoolCopy(), MiLockSystemSpace, MiUnlockSystemSpace, NTSTATUS(), NULL, POOL_MOVE_THRESHOLD, PsGetCurrentProcess, Status, _EPROCESS::VmOperation, and _EPROCESS::VmOperationEvent.

Referenced by LpcpCopyRequestData(), NtReadVirtualMemory(), and NtWriteVirtualMemory().

    00371 {
    00372     NTSTATUS Status;
    00373     KIRQL OldIrql;
    00374     PEPROCESS ProcessToLock;
    00375
    00376     if (BufferSize == 0) {
    00377         ASSERT (FALSE);         // No one should call with a zero size.
    00378         return STATUS_SUCCESS;
    00379     }
    00380
    00381     ProcessToLock = FromProcess;
    00382     if (FromProcess == PsGetCurrentProcess()) {
    00383         ProcessToLock = ToProcess;
    00384     }
    00385
    00386     //
    00387     // Make sure the process still has an address space.
    00388     //
    00389
    00390     MiLockSystemSpace(OldIrql);
    00391     if (ProcessToLock->AddressSpaceDeleted != 0) {
    00392         MiUnlockSystemSpace(OldIrql);
    00393         return STATUS_PROCESS_IS_TERMINATING;
    00394     }
    00395     ProcessToLock->VmOperation += 1;
    00396     MiUnlockSystemSpace(OldIrql);
    00397
    00398
    00399     //
    00400     // If the buffer size is greater than the pool move threshold,
    00401     // then attempt to write the memory via direct mapping.
    00402     //
    00403
    00404     if (BufferSize > POOL_MOVE_THRESHOLD) {
    00405         Status = MiDoMappedCopy(FromProcess,
    00406                                 FromAddress,
    00407                                 ToProcess,
    00408                                 ToAddress,
    00409                                 BufferSize,
    00410                                 PreviousMode,
    00411                                 NumberOfBytesCopied);
    00412
    00413         //
    00414         // If the completion status is not a working quota problem,
    00415         // then finish the service. Otherwise, attempt to write the
    00416         // memory through nonpaged pool.
    00417         //
    00418
    00419         if (Status != STATUS_WORKING_SET_QUOTA) {
    00420             goto CompleteService;
    00421         }
    00422
    00423         *NumberOfBytesCopied = 0;
    00424     }
    00425
    00426     //
    00427     // There was not enough working set quota to write the memory via
    00428     // direct mapping or the size of the write was below the pool move
    00429     // threshold. Attempt to write the specified memory through nonpaged
    00430     // pool.
    00431     //
    00432
    00433     Status = MiDoPoolCopy(FromProcess,
    00434                           FromAddress,
    00435                           ToProcess,
    00436                           ToAddress,
    00437                           BufferSize,
    00438                           PreviousMode,
    00439                           NumberOfBytesCopied);
    00440
    00441     //
    00442     // Dereference the target process.
    00443     //
    00444
    00445 CompleteService:
    00446
    00447     //
    00448     // Indicate that the vm operation is complete.
    00449     //
    00450
    00451     MiLockSystemSpace(OldIrql);
    00452     ProcessToLock->VmOperation -= 1;
    00453     if ((ProcessToLock->VmOperation == 0) &&
    00454         (ProcessToLock->VmOperationEvent != NULL)) {
    00455        KeSetEvent (ProcessToLock->VmOperationEvent, 0, FALSE);
    00456     }
    00457     MiUnlockSystemSpace(OldIrql);
    00458
    00459     return Status;
    00460 }

NTSTATUS NtReadVirtualMemory | ( | IN HANDLE | ProcessHandle,
|  | IN PVOID | BaseAddress,
|  | OUT PVOID | Buffer,
|  | IN ULONG | BufferSize,
|  | OUT PULONG NumberOfBytesRead | OPTIONAL
| ) |

Definition at line 102 of file readwrt.c.

References Buffer, BufferSize, EXCEPTION_EXECUTE_HANDLER, KernelMode, KPROCESSOR_MODE, MiValidateUserTransfer(), MmCopyVirtualMemory(), NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, ProbeForWriteUlong, PsGetCurrentProcess, PsProcessType, and Status.

Referenced by ConsoleClientConnectRoutine(), GetHardErrorText(), RtlCheckForOrphanedCriticalSections(), RtlDestroyQueryDebugBuffer(), RtlFreeUserThreadStack(), RtlQueryProcessDebugInformation(), and SrvWriteConsoleOutput().

    00112                    :
    00113
    00114     This function copies the specified address range from the specified
    00115     process into the specified address range of the current process.
    00116
    00117 Arguments:
    00118
    00119      ProcessHandle - Supplies an open handle to a process object.
    00120
    00121      BaseAddress - Supplies the base address in the specified process
    00122           to be read.
    00123
    00124      Buffer - Supplies the address of a buffer which receives the
    00125           contents from the specified process address space.
    00126
    00127      BufferSize - Supplies the requested number of bytes to read from
    00128           the specified process.
    00129
    00130      NumberOfBytesRead - Receives the actual number of bytes
    00131           transferred into the specified buffer.
    00132
    00133 Return Value:
    00134
    00135     TBS
    00136
    00137 --*/
    00138
    00139 {
    00140
    00141     ULONG BytesCopied;
    00142     KPROCESSOR_MODE PreviousMode;
    00143     PEPROCESS Process;
    00144     NTSTATUS Status;
    00145
    00146     PAGED_CODE();
    00147
    00148     //
    00149     // Get the previous mode and probe output argument if necessary.
    00150     //
    00151
    00152     PreviousMode = KeGetPreviousMode();
    00153     if (PreviousMode != KernelMode) {
    00154
    00155         Status = MiValidateUserTransfer(BaseAddress, Buffer, BufferSize);
    00156         if (Status != STATUS_SUCCESS) {
    00157             return Status;
    00158         }
    00159
    00160         if (ARGUMENT_PRESENT(NumberOfBytesRead)) {
    00161             try {
    00162                 ProbeForWriteUlong(NumberOfBytesRead);
    00163
    00164             } except(EXCEPTION_EXECUTE_HANDLER) {
    00165                 return GetExceptionCode();
    00166             }
    00167         }
    00168     }
    00169
    00170     //
    00171     // If the buffer size is not zero, then attempt to read data from the
    00172     // specified process address space into the current process address
    00173     // space.
    00174     //
    00175
    00176     BytesCopied = 0;
    00177     Status = STATUS_SUCCESS;
    00178     if (BufferSize != 0) {
    00179
    00180         //
    00181         // Reference the target process.
    00182         //
    00183
    00184         Status = ObReferenceObjectByHandle(ProcessHandle,
    00185                                            PROCESS_VM_READ,
    00186                                            PsProcessType,
    00187                                            PreviousMode,
    00188                                            (PVOID *)&Process,
    00189                                            NULL);
    00190
    00191         //
    00192         // If the process was successfully referenced, then attempt to
    00193         // read the specified memory either by direct mapping or copying
    00194         // through nonpaged pool.
    00195         //
    00196
    00197         if (Status == STATUS_SUCCESS) {
    00198
    00199             Status = MmCopyVirtualMemory (Process,
    00200                                           BaseAddress,
    00201                                           PsGetCurrentProcess(),
    00202                                           Buffer,
    00203                                           BufferSize,
    00204                                           PreviousMode,
    00205                                           &BytesCopied);
    00206
    00207             //
    00208             // Dereference the target process.
    00209             //
    00210
    00211             ObDereferenceObject(Process);
    00212         }
    00213     }
    00214
    00215     //
    00216     // If requested, return the number of bytes read.
    00217     //
    00218
    00219     if (ARGUMENT_PRESENT(NumberOfBytesRead)) {
    00220         try {
    00221             *NumberOfBytesRead = BytesCopied;
    00222
    00223         } except(EXCEPTION_EXECUTE_HANDLER) {
    00224             NOTHING;
    00225         }
    00226     }
    00227
    00228     return Status;
    00229 }
    NTSTATUS

NTSTATUS NtWriteVirtualMemory | ( | IN HANDLE | ProcessHandle,
|  | OUT PVOID | BaseAddress,
|  | IN PVOID | Buffer,
|  | IN ULONG | BufferSize,
|  | OUT PULONG NumberOfBytesWritten | OPTIONAL
| ) |

Definition at line 231 of file readwrt.c.

References Buffer, BufferSize, EXCEPTION_EXECUTE_HANDLER, KernelMode, KPROCESSOR_MODE, MiValidateUserTransfer(), MmCopyVirtualMemory(), NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, ProbeForWriteUlong, PsGetCurrentProcess, PsProcessType, and Status.

Referenced by RtlRemoteCall().

    00241                    :
    00242
    00243     This function copies the specified address range from the current
    00244     process into the specified address range of the specified process.
    00245
    00246 Arguments:
    00247
    00248      ProcessHandle - Supplies an open handle to a process object.
    00249
    00250      BaseAddress - Supplies the base address to be written to in the
    00251           specified process.
    00252
    00253      Buffer - Supplies the address of a buffer which contains the
    00254           contents to be written into the specified process
    00255           address space.
    00256
    00257      BufferSize - Supplies the requested number of bytes to write
    00258           into the specified process.
    00259
    00260      NumberOfBytesWritten - Receives the actual number of
    00261           bytes transferred into the specified address
    00262           space.
    00263
    00264 Return Value:
    00265
    00266     TBS
    00267
    00268 --*/
    00269
    00270 {
    00271     ULONG BytesCopied;
    00272     KPROCESSOR_MODE PreviousMode;
    00273     PEPROCESS Process;
    00274     NTSTATUS Status;
    00275
    00276     PAGED_CODE();
    00277
    00278     //
    00279     // Get the previous mode and probe output argument if necessary.
    00280     //
    00281
    00282     PreviousMode = KeGetPreviousMode();
    00283     if (PreviousMode != KernelMode) {
    00284
    00285         Status = MiValidateUserTransfer(BaseAddress, Buffer, BufferSize);
    00286         if (Status != STATUS_SUCCESS) {
    00287             return Status;
    00288         }
    00289
    00290         if (ARGUMENT_PRESENT(NumberOfBytesWritten)) {
    00291             try {
    00292                 ProbeForWriteUlong(NumberOfBytesWritten);
    00293
    00294             } except(EXCEPTION_EXECUTE_HANDLER) {
    00295                 return GetExceptionCode();
    00296             }
    00297         }
    00298     }
    00299
    00300     //
    00301     // If the buffer size is not zero, then attempt to write data from the
    00302     // current process address space into the target process address space.
    00303     //
    00304
    00305     BytesCopied = 0;
    00306     Status = STATUS_SUCCESS;
    00307     if (BufferSize != 0) {
    00308
    00309         //
    00310         // Reference the target process.
    00311         //
    00312
    00313         Status = ObReferenceObjectByHandle(ProcessHandle,
    00314                                            PROCESS_VM_WRITE,
    00315                                            PsProcessType,
    00316                                            PreviousMode,
    00317                                            (PVOID *)&Process,
    00318                                            NULL);
    00319
    00320         //
    00321         // If the process was successfully referenced, then attempt to
    00322         // write the specified memory either by direct mapping or copying
    00323         // through nonpaged pool.
    00324         //
    00325
    00326         if (Status == STATUS_SUCCESS) {
    00327
    00328             Status = MmCopyVirtualMemory (PsGetCurrentProcess(),
    00329                                           Buffer,
    00330                                           Process,
    00331                                           BaseAddress,
    00332                                           BufferSize,
    00333                                           PreviousMode,
    00334                                           &BytesCopied);
    00335
    00336             //
    00337             // Dereference the target process.
    00338             //
    00339
    00340             ObDereferenceObject(Process);
    00341         }
    00342     }
    00343
    00344     //
    00345     // If requested, return the number of bytes read.
    00346     //
    00347
    00348     if (ARGUMENT_PRESENT(NumberOfBytesWritten)) {
    00349         try {
    00350             *NumberOfBytesWritten = BytesCopied;
    00351
    00352         } except(EXCEPTION_EXECUTE_HANDLER) {
    00353             NOTHING;
    00354         }
    00355     }
    00356
    00357     return Status;
    00358 }