test: flushbuf.c File Reference

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

# flushbuf.c File Reference

`#include "mi.h"`

Go to the source code of this file.

## Functions

NTSTATUS | NtFlushWriteBuffer (VOID)
ULONG | MiFlushRangeFilter (IN PEXCEPTION_POINTERS ExceptionPointers, IN PVOID *BaseAddress, IN PULONG Length, IN PBOOLEAN Retry)
NTSTATUS | NtFlushInstructionCache (IN HANDLE ProcessHandle, IN PVOID BaseAddress OPTIONAL, IN ULONG Length)

## Function Documentation

ULONG MiFlushRangeFilter | ( | IN PEXCEPTION_POINTERS | ExceptionPointers,
|  | IN PVOID * | BaseAddress,
|  | IN PULONG | Length,
|  | IN PBOOLEAN | Retry
| ) |

Definition at line 60 of file flushbuf.c.

References EXCEPTION_EXECUTE_HANDLER, ROUND_TO_PAGES, and TRUE.

Referenced by NtFlushInstructionCache().

    00069                    :
    00070
    00071     This is the exception handler used by NtFlushInstructionCache to protect
    00072     against bad virtual addresses passed to KeSweepIcacheRange.  If an
    00073     access violation occurs, this routine causes NtFlushInstructionCache to
    00074     restart the sweep at the page following the failing page.
    00075
    00076 Arguments:
    00077
    00078     ExceptionPointers - Supplies exception information.
    00079
    00080     BaseAddress - Supplies a pointer to address the base of the region
    00081         being flushed.  If the failing address is not in the last page
    00082         of the region, this routine updates BaseAddress to point to the
    00083         next page of the region.
    00084
    00085     Length - Supplies a pointer the length of the region being flushed.
    00086         If the failing address is not in the last page of the region,
    00087         this routine updates Length to reflect restarting the flush at
    00088         the next page of the region.
    00089
    00090     Retry - Supplies a pointer to a boolean that the caller has initialized
    00091         to FALSE.  This routine sets this boolean to TRUE if an access
    00092         violation occurs in a page before the last page of the flush region.
    00093
    00094 Return Value:
    00095
    00096     EXCEPTION_EXECUTE_HANDLER.
    00097
    00098 --*/
    00099
    00100 {
    00101     PEXCEPTION_RECORD ExceptionRecord;
    00102     ULONG_PTR BadVa;
    00103     ULONG_PTR NextVa;
    00104     ULONG_PTR EndVa;
    00105
    00106     ExceptionRecord = ExceptionPointers->ExceptionRecord;
    00107
    00108     //
    00109     // If the exception was an access violation, skip the current page of the
    00110     // region and move to the next page.
    00111     //
    00112
    00113     if ( ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION ) {
    00114
    00115         //
    00116         // Get the failing address, calculate the base address of the next page,
    00117         // and calculate the address at the end of the region.
    00118         //
    00119
    00120         BadVa = ExceptionRecord->ExceptionInformation[1];
    00121         NextVa = ROUND_TO_PAGES( BadVa + 1 );
    00122         EndVa = *(PULONG_PTR)BaseAddress + *Length;
    00123
    00124         //
    00125         // If the next page didn't wrap, and the next page is below the end of
    00126         // the region, update Length and BaseAddress appropriately and set Retry
    00127         // to TRUE to indicate to NtFlushInstructionCache that it should call
    00128         // KeSweepIcacheRange again.
    00129         //
    00130
    00131         if ( (NextVa > BadVa) && (NextVa < EndVa) ) {
    00132             *Length = (ULONG) (EndVa - NextVa);
    00133             *BaseAddress = (PVOID)NextVa;
    00134             *Retry = TRUE;
    00135         }
    00136     }
    00137
    00138     return EXCEPTION_EXECUTE_HANDLER;
    00139 }

NTSTATUS NtFlushInstructionCache | ( | IN HANDLE | ProcessHandle,
|  | IN PVOID BaseAddress | OPTIONAL,
|  | IN ULONG | Length
| ) |

Definition at line 142 of file flushbuf.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, KeAttachProcess(), KeDetachProcess(), KernelMode, KeSweepIcache(), KeSweepIcacheRange(), KPROCESSOR_MODE, MiFlushRangeFilter(), NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, ProbeForRead, PsProcessType, and Status.

Referenced by LdrpSetProtection(), and LdrpSnapIAT().

    00150                    :
    00151
    00152     This function flushes the instruction cache for the specified process.
    00153
    00154 Arguments:
    00155
    00156     ProcessHandle - Supplies a handle to the process in which the instruction
    00157         cache is to be flushed. Must have PROCESS_VM_WRITE access to the
    00158         specified process.
    00159
    00160     BaseAddress - Supplies an optional pointer to base of the region that
    00161         is flushed.
    00162
    00163     Length - Supplies the length of the region that is flushed if the base
    00164         address is specified.
    00165
    00166 Return Value:
    00167
    00168     STATUS_SUCCESS.
    00169
    00170 --*/
    00171
    00172 {
    00173
    00174     KPROCESSOR_MODE PreviousMode;
    00175     PEPROCESS Process;
    00176     NTSTATUS Status;
    00177     BOOLEAN Retry;
    00178     PVOID RangeBase;
    00179     ULONG RangeLength;
    00180
    00181     PAGED_CODE();
    00182
    00183     PreviousMode = KeGetPreviousMode();
    00184
    00185     //
    00186     // If the base address is not specified, or the base address is specified
    00187     // and the length is not zero, then flush the specified instruction cache
    00188     // range.
    00189     //
    00190
    00191     if ((ARGUMENT_PRESENT(BaseAddress) == FALSE) || (Length != 0)) {
    00192
    00193         //
    00194         // If previous mode is user and the range specified falls in kernel
    00195         // address space, return an error.
    00196         //
    00197
    00198         if ((ARGUMENT_PRESENT(BaseAddress) != FALSE) &&
    00199             (PreviousMode != KernelMode)) {
    00200             try {
    00201                 ProbeForRead(BaseAddress, Length, sizeof(UCHAR));
    00202             } except(EXCEPTION_EXECUTE_HANDLER) {
    00203                 return GetExceptionCode();
    00204             }
    00205         }
    00206
    00207         //
    00208         // If the specified process is not the current process, then
    00209         // the process must be attached to during the flush.
    00210         //
    00211
    00212         if (ProcessHandle != NtCurrentProcess()) {
    00213
    00214             //
    00215             // Reference the specified process checking for PROCESS_VM_WRITE
    00216             // access.
    00217             //
    00218
    00219             Status = ObReferenceObjectByHandle(ProcessHandle,
    00220                                                PROCESS_VM_WRITE,
    00221                                                PsProcessType,
    00222                                                PreviousMode,
    00223                                                (PVOID *)&Process,
    00224                                                NULL);
    00225
    00226             if (!NT_SUCCESS(Status)) {
    00227                 return Status;
    00228             }
    00229
    00230             //
    00231             // Attach to the process.
    00232             //
    00233
    00234             KeAttachProcess(&Process->Pcb);
    00235         }
    00236
    00237         //
    00238         // If the base address is not specified, sweep the entire instruction
    00239         // cache.  If the base address is specified, flush the specified range.
    00240         //
    00241
    00242         if (ARGUMENT_PRESENT(BaseAddress) == FALSE) {
    00243             KeSweepIcache(FALSE);
    00244
    00245         } else {
    00246
    00247             //
    00248             // Parts of the specified range may be invalid.  An exception
    00249             // handler is used to skip over those parts.  Before calling
    00250             // KeSweepIcacheRange, we set Retry to FALSE.  If an access
    00251             // violation occurs in KeSweepIcacheRange, the MiFlushRangeFilter
    00252             // exception filter is called.  It updates RangeBase and
    00253             // RangeLength to skip over the failing page, and sets Retry to
    00254             // TRUE.  As long as Retry is TRUE, we continue to call
    00255             // KeSweepIcacheRange.
    00256             //
    00257
    00258             RangeBase = BaseAddress;
    00259             RangeLength = Length;
    00260
    00261             do {
    00262                 Retry = FALSE;
    00263                 try {
    00264                     KeSweepIcacheRange(FALSE, RangeBase, RangeLength);
    00265                 } except(MiFlushRangeFilter(GetExceptionInformation(),
    00266                                             &RangeBase,
    00267                                             &RangeLength,
    00268                                             &Retry)) {
    00269                     if (GetExceptionCode() != STATUS_ACCESS_VIOLATION) {
    00270                         Status = GetExceptionCode();
    00271                     }
    00272                 }
    00273             } while (Retry != FALSE);
    00274         }
    00275
    00276         //
    00277         // If the specified process is not the current process, then
    00278         // detach from it and dereference it.
    00279         //
    00280
    00281         if (ProcessHandle != NtCurrentProcess()) {
    00282             KeDetachProcess();
    00283             ObDereferenceObject(Process);
    00284         }
    00285     }
    00286
    00287     return STATUS_SUCCESS;
    00288 }

NTSTATUS NtFlushWriteBuffer | ( | VOID |  | ) |

Definition at line 32 of file flushbuf.c.

References KeFlushWriteBuffer(), and PAGED_CODE.

    00038                    :
    00039
    00040     This function flushes the write buffer on the current processor.
    00041
    00042 Arguments:
    00043
    00044     None.
    00045
    00046 Return Value:
    00047
    00048     STATUS_SUCCESS.
    00049
    00050 --*/
    00051
    00052 {
    00053     PAGED_CODE();
    00054
    00055     KeFlushWriteBuffer();
    00056     return STATUS_SUCCESS;
    00057 }