summaryrefslogtreecommitdiffstats
path: root/private/ntos/mm/querysec.c
blob: 83bd0ddf35288e23882c89d2bc06b5a4b4d1e65c (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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
/*++

Copyright (c) 1989  Microsoft Corporation

Module Name:

   querysec.c

Abstract:

    This module contains the routines which implement the
    NtQuerySection service.

Author:

    Lou Perazzoli (loup) 22-May-1989

Revision History:

--*/


#include "mi.h"

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,NtQuerySection)
#endif


NTSTATUS
NtQuerySection(
    IN HANDLE SectionHandle,
    IN SECTION_INFORMATION_CLASS SectionInformationClass,
    OUT PVOID SectionInformation,
    IN ULONG SectionInformationLength,
    OUT PULONG ReturnLength OPTIONAL
     )

/*++

Routine Description:

    This function returns information about an opened section object.
   This function provides the capability to determine the base address,
   size, granted access, and allocation of an opened section object.

Arguments:

    SectionHandle - Supplies an open handle to a section object.

    SectionInformationClass - The section information class about
        which to retrieve information.

    SectionInformation - A pointer to a buffer that receives the
        specified information.  The format and content of the buffer
        depend on the specified section class.

       SectionInformation Format by Information Class:

       SectionBasicInformation - Data type is PSECTION_BASIC_INFORMATION.

           SECTION_BASIC_INFORMATION Structure

           PVOID BaseAddress - The base virtual address of the
               section if the section is based.

           LARGE_INTEGER MaximumSize - The maximum size of the section in
               bytes.

           ULONG AllocationAttributes - The allocation attributes
               flags.

               AllocationAttributes Flags

               SEC_BASED - The section is a based section.

               SEC_TILE - The section must be allocated in the first
                   512mb of the virtual address space.

               SEC_FILE - The section is backed by a data file.

               SEC_RESERVE - All pages of the section were initially
                   set to the reserved state.

               SEC_COMMIT - All pages of the section were initially
                   to the committed state.

               SEC_IMAGE - The section was mapped as an executable
                   image file.

        SECTION_IMAGE_INFORMATION

    SectionInformationLength - Specifies the length in bytes of the
        section information buffer.

    ReturnLength - An optional pointer which, if specified, receives
        the number of bytes placed in the section information buffer.


Return Value:

    Returns the status

    TBS


--*/

{
    PSECTION Section;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;

    PAGED_CODE();

    //
    // Get previous processor mode and probe output argument if necessary.
    //

    PreviousMode = KeGetPreviousMode();
    if (PreviousMode != KernelMode) {

        //
        // Check arguments.
        //

        try {

            ProbeForWrite(SectionInformation,
                          SectionInformationLength,
                          sizeof(ULONG));

            if (ARGUMENT_PRESENT (ReturnLength)) {
                ProbeForWriteUlong(ReturnLength);
            }

        } except (EXCEPTION_EXECUTE_HANDLER) {

            //
            // 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();
        }
    }

    //
    // Check argument validity.
    //

    if ((SectionInformationClass != SectionBasicInformation) &&
        (SectionInformationClass != SectionImageInformation)) {
        return STATUS_INVALID_INFO_CLASS;
    }

    if (SectionInformationClass == SectionBasicInformation) {
        if (SectionInformationLength < (ULONG)sizeof(SECTION_BASIC_INFORMATION)) {
            return STATUS_INFO_LENGTH_MISMATCH;
        }
    } else {
        if (SectionInformationLength < (ULONG)sizeof(SECTION_IMAGE_INFORMATION)) {
            return STATUS_INFO_LENGTH_MISMATCH;
        }
    }

    //
    // Reference section object by handle for READ access, get the information
    // from the section object, deference the section
    // object, fill in information structure, optionally return the length of
    // the information structure, and return service status.
    //

    Status = ObReferenceObjectByHandle(SectionHandle, SECTION_QUERY,
                                       MmSectionObjectType,
                                       PreviousMode, (PVOID *)&Section, NULL);

    if (NT_SUCCESS(Status)) {

        try {

            if (SectionInformationClass == SectionBasicInformation) {
                ((PSECTION_BASIC_INFORMATION)SectionInformation)->BaseAddress =
                                                  Section->Address.StartingVa;

                ((PSECTION_BASIC_INFORMATION)SectionInformation)->MaximumSize =
                                                 Section->SizeOfSection;

                ((PSECTION_BASIC_INFORMATION)SectionInformation)->AllocationAttributes =
                                                        0;

                if (Section->u.Flags.Image) {
                    ((PSECTION_BASIC_INFORMATION)SectionInformation)->AllocationAttributes =
                                                        SEC_IMAGE;
                }
                if (Section->u.Flags.Based) {
                    ((PSECTION_BASIC_INFORMATION)SectionInformation)->AllocationAttributes |=
                                                        SEC_BASED;
                }
                if (Section->u.Flags.File) {
                    ((PSECTION_BASIC_INFORMATION)SectionInformation)->AllocationAttributes |=
                                                        SEC_FILE;
                }
                if (Section->u.Flags.NoCache) {
                    ((PSECTION_BASIC_INFORMATION)SectionInformation)->AllocationAttributes |=
                                                        SEC_NOCACHE;
                }
                if (Section->u.Flags.Reserve) {
                    ((PSECTION_BASIC_INFORMATION)SectionInformation)->AllocationAttributes |=
                                                        SEC_RESERVE;
                }
                if (Section->u.Flags.Commit) {
                    ((PSECTION_BASIC_INFORMATION)SectionInformation)->AllocationAttributes |=
                                                        SEC_COMMIT;
                }

                if (ARGUMENT_PRESENT(ReturnLength)) {
                    *ReturnLength = sizeof(SECTION_BASIC_INFORMATION);
                }

            } else {

                if (Section->u.Flags.Image == 0) {
                    return STATUS_SECTION_NOT_IMAGE;
                }
                *((PSECTION_IMAGE_INFORMATION)SectionInformation) =
                    Section->Segment->ImageInformation;

                if (ARGUMENT_PRESENT(ReturnLength)) {
                    *ReturnLength = sizeof(SECTION_IMAGE_INFORMATION);
                }
            }

        } except (EXCEPTION_EXECUTE_HANDLER) {

        }

        ObDereferenceObject ((PVOID)Section);
    }
    return Status;
}