summaryrefslogtreecommitdiffstats
path: root/private/ntos/ex/i386/probe.c
blob: e65bd0d9a44f4ac371794cd4916ba61229ab8a9a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*++

Copyright (c) 1989-1993  Microsoft Corporation

Module Name:

    probe.c

Abstract:

    This module contains implements the probe for write function.

Author:

    David N. Cutler (davec) 5-May-1989

Environment:

    Any mode.

Revision History:

--*/

#include "exp.h"

#if defined(ALLOC_PRAGMA)
#pragma alloc_text(PAGE, ProbeForWrite)
#endif


VOID
ProbeForWrite (
    IN PVOID Address,
    IN ULONG Length,
    IN ULONG Alignment
    )

/*++

Routine Description:

    This function probes a structure for write accessibility and ensures
    correct alignment of the structure. If the structure is not accessible
    or has incorrect alignment, then an exception is raised.

Arguments:

    Address - Supplies a pointer to the structure to be probed.

    Length - Supplies the length of the structure.

    Alignment - Supplies the required alignment of the structure expressed
        as the number of bytes in the primitive datatype (e.g., 1 for char,
        2 for short, 4 for long, and 8 for quad).

Return Value:

    None.

--*/

{

    ULONG StartAddress;
    ULONG EndAddress;

    //
    // If the structure has zero length, then do not probe the structure for
    // write accessibility or alignment.
    //

    if (Length != 0) {

        //
        // If the structure is not properly aligned, then raise a data
        // misalignment exception.
        //

        ASSERT((Alignment == 1) || (Alignment == 2) ||
               (Alignment == 4) || (Alignment == 8));

        StartAddress = (ULONG)Address;
        if ((StartAddress & (Alignment - 1)) == 0) {

            //
            // Compute the ending address of the structure and probe for
            // write accessibility.
            //

            EndAddress = StartAddress + Length - 1;
            if ((StartAddress <= EndAddress) &
                (EndAddress < MM_USER_PROBE_ADDRESS)) {

                //
                // N.B. Only the contents of the buffer may be probed.
                //      Therefore the starting byte is probed for the
                //       first page, and then the first byte in the page
                //      for each succeeding page.
                //

                EndAddress = (EndAddress & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
                do {
                    *(volatile CHAR *)StartAddress = *(volatile CHAR *)StartAddress;
                    StartAddress = (StartAddress & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
                } while (StartAddress != EndAddress);

                return;

            } else {
                ExRaiseStatus(STATUS_ACCESS_VIOLATION);
            }

        } else {
            ExRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
        }
    }

    return;
}