source: trunk/src/win32k/dev32/d32CallGate.asm@ 6253

Last change on this file since 6253 was 6217, checked in by bird, 24 years ago

Added new environment fix function.

File size: 13.4 KB
Line 
1; $Id: d32CallGate.asm,v 1.4 2001-07-08 02:54:40 bird Exp $
2;
3; 32-bit CallGate used to communitcate fast between Ring-3 and Ring-0.
4; This module contains all assembly workers for this.
5;
6; Copyright (c) 2001 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
7;
8; Project Odin Software License can be found in LICENSE.TXT
9;
10
11 .386p
12
13;
14; Defined Constants And Macros
15;
16 INCL_ERRORS EQU 1
17
18
19;
20; Header Files
21;
22 include bseerr.inc
23 include devsegdf.inc
24 include devhlp.inc
25 include win32k.inc
26
27
28;
29; Exported symbols
30;
31 public CallGateGDT
32
33 public InitCallGate
34 public Win32kAPIRouter
35
36
37;
38; External symbols
39;
40 extrn _Device_Help:dword
41 extrn pulTKSSBase32:dword
42
43 extrn KMEnterKmodeSEF:near
44 extrn KMExitKmodeSEF8:near
45 extrn _TKFuBuff@16:near
46
47 extrn k32AllocMemEx:near
48 extrn k32QueryOTEs:near
49 extrn k32QueryOptionsStatus:near
50 extrn k32SetOptions:near
51 extrn k32ProcessReadWrite:near
52 extrn k32HandleSystemEvent:near
53 extrn k32QuerySystemMemInfo:near
54 extrn k32QueryCallGate:near
55 extrn k32SetEnvironment:near
56
57
58;
59; Global Variables
60;
61DATA16 segment
62CallGateGDT dw 0 ; GDT used for the 32-bit Ring-3 -> Ring-0 call gate.
63DATA16 ends
64
65DATA32 segment
66GDTR_limit dw ? ; The limit field of the GDTR.
67GDTR_base dd ? ; The base field of the GDTR. (linear flat address)
68
69
70;
71; Structure containing the K32 API parameter packet size.
72;
73; Used for parameter packet validation, and for copying the parameter
74; packet from user address space into system address space (the stack).
75;
76acbK32Params:
77 dd 0 ; Not used - ie. invalid
78 dd SIZE K32ALLOCMEMEX ; K32_ALLOCMEMEX 0x01
79 dd SIZE K32QUERYOTES ; K32_QUERYOTES 0x02
80 dd SIZE K32QUERYOPTIONSSTATUS ; K32_QUERYOPTIONSSTATUS 0x03
81 dd SIZE K32SETOPTIONS ; K32_SETOPTIONS 0x04
82 dd SIZE K32PROCESSREADWRITE ; K32_PROCESSREADWRITE 0x05
83 dd SIZE K32HANDLESYSTEMEVENT ; K32_HANDLESYSTEMEVENT 0x06
84 dd SIZE K32QUERYSYSTEMMEMINFO ; K32_QUERYSYSTEMMEMINFO 0x07
85 dd SIZE K32QUERYCALLGATE ; K32_QUERYCALLGATE 0x08
86 dd SIZE K32SETENVIRONMENT ; K32_SETENVIRONMENT 0x09
87
88;
89; Structure containing the offsets of K32 API worker routines.
90;
91; Used for calling the workers indirectly.
92;
93apfnK32APIs:
94 dd FLAT:k32APIStub ; Not used - ie. invalid
95 dd FLAT:k32AllocMemEx ; K32_ALLOCMEMEX 0x01
96 dd FLAT:k32QueryOTEs ; K32_QUERYOTES 0x02
97 dd FLAT:k32QueryOptionsStatus ; K32_QUERYOPTIONSSTATUS 0x03
98 dd FLAT:k32SetOptions ; K32_SETOPTIONS 0x04
99 dd FLAT:k32ProcessReadWrite ; K32_PROCESSREADWRITE 0x05
100 dd FLAT:k32HandleSystemEvent ; K32_HANDLESYSTEMEVENT 0x06
101 dd FLAT:k32QuerySystemMemInfo ; K32_QUERYSYSTEMMEMINFO 0x07
102 dd FLAT:k32QueryCallGate ; K32_QUERYCALLGATE 0x08
103 dd FLAT:k32SetEnvironment ; K32_SETENVIRONMENT 0x09
104DATA32 ends
105
106
107
108CODE32 segment
109 assume cs:CODE32, ds:FLAT ;, es:nothing, ss:nothing
110
111;;
112; This function initiates the callgate.
113; @cproto extern ULONG _Optlink InitCallGate(void);
114; @returns 0 (NO_ERROR) on success.
115; appropriate error code on error.
116; @uses eax, ecx, edx
117; @sketch
118; @status
119; @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
120; @remark
121InitCallGate proc near
122 push ebp
123 mov ebp, esp
124 push edi
125 push esi
126 push ebx
127 push ds
128 push es
129
130 ;
131 ; Allocate GDT selector for the call gate.
132 ; (URG! This call also allocates 68kb of virtual memory which i don't need!)
133 ;
134 mov di, seg DATA16:CallGateGDT
135 mov es, di
136 mov di, offset DATA16:CallGateGDT
137 mov cx, 1
138 mov dl, DevHlp_AllocGDTSelector
139 jmp far ptr CODE16:Thunk16_AllocGDTSelector
140Thunk32_AllocGDTSelector::
141 jnc ICG_allocok
142 movzx eax, ax ; We failed, zero high word of eax to return proper return code.
143 jmp ICG_end ; bail out.
144
145 ;
146 ; We successfully allocate the callgate GDT.
147 ; How we'll find the descriptor entry for it.
148 ;
149ICG_allocok:
150 ASSUME ds:FLAT
151 sgdt GDTR_limit ; Get the GDTR content.
152 mov ax, GDTR_limit
153 mov ebx, GDTR_base
154 movzx ecx, CallGateGDT
155 and cx, 0fff8h ; clear the dpl bits and descriptor type bit. (paranoia!)
156 cmp cx, ax ; check limit. (paranoia!!!)
157 jl ICG_limitok
158 mov eax, 0ffffffffh ; return failure.
159 jmp ICG_end
160ICG_limitok:
161 add ebx, ecx ; GDTR_base + selector offset -> flat pointer to selector.
162
163 ;
164 ; ebx is pointing to the descriptor table entry for my GDT selector.
165 ; Now we'll have to change it into a callgate.
166 ; This is the layout of a callgate descriptor:
167 ; bits
168 ; 0-15 Segment offset low word
169 ; 16-31 Segment selector
170 ; -------second dword-------
171 ; 0-4 Param Count
172 ; 5-7 Reserved (zero)
173 ; 8-11 Selector type - 1100b
174 ; 12 Reserved (UVirt) zero
175 ; 13-14 Descriptor Privelege Level (DPL)
176 ; 15 Present flag / Gate valid.
177 ; 16-31 Segment offset high word.
178 ;
179 mov eax, offset FLAT:Win32kCallGate
180 mov word ptr [ebx], ax ; set low segment offset word
181 shr eax, 10h
182 mov word ptr [ebx + 6], ax ; set high segment offset word
183
184 mov word ptr [ebx + 4], 1110110000000010b ; set flags and stuff.
185 ; param count: Two (2) - parameter struct and function number
186 ; type: 32-bit call gate
187 ; DPL: Ring-3
188 ; Gate Valid: Yes
189 mov word ptr [ebx + 2], seg FLAT:CODE32 ; Set the selector to FLAT Ring-0 code selector.
190 xor eax, eax ; return successfully.
191
192ICG_end:
193 pop es
194 pop ds
195 pop ebx
196 pop esi
197 pop edi
198 leave
199 ret
200InitCallGate endp
201
202
203
204;;
205; This is the callgate procedure.
206; @cproto none
207; @returns return value of the callgate router.
208; @param fill inn later....
209; @uses eax, ecx, edx
210; @sketch
211; @status
212; @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
213; @remark
214; stack frame - before KMEnterKmodeSEF:
215; --bottom of stack---
216; calling ss 1ch
217; calling esp 18h
218; pParameter (parameter 1) 14h
219; ulFunctionCode (parameter 0) 10h
220; calling cs 0ch
221; calling eip <-- esp points here upon entry. 8h
222; ---top of stack---
223; flags (pushf) 4h
224; parameter size (push 8h) 0h
225;
226; After the call to KMEnterKmodeSEF:
227; --bottom of stack---
228; calling ss 50
229; calling esp 4c
230; pParameter (parameter 1) 48
231; ulFunctionCode (parameter 0) 44
232; sef_cs 40
233; sef_eip 3c
234; sef_eflag 38
235; sef_cbargs 34
236; sef_retaddr 30
237; sef_ds 2c
238; sef_es 28
239; sef_fs 24
240; sef_gs 20
241; sef_eax 1c
242; sef_ecx 18
243; sef_edx 14
244; sef_ebx 10
245; sef_padesp c
246; sef_ebp 8
247; sef_esi 4h
248; sef_edi 0h
249;
250Win32kCallGate proc near
251 ASSUME ds:nothing, ss:nothing
252 pushfd ; Push all flags (eflags)
253 push 8h ; Size of parameters.
254
255 call KMEnterKmodeSEF ; This is an OS2 kernel function which does
256 ; kernel entry housekeeping.
257
258 mov edx, [esp + 48h] ; pParameter (parameter 1)
259 mov eax, [esp + 44h] ; ulFunctionCode (parameter 2)
260 sub esp, 8h ; (Even when using _Oplink we have to reserve space for parameters.)
261 call Win32kAPIRouter ; This is my Ring-0 api router.
262 add esp, 8h
263
264 jmp KMExitKmodeSEF8 ; This a an OS2 kernel function which does
265 ; kernel exist housekeeping.
266Win32kCallGate endp
267
268
269;;
270; Internal function router which calls the correct function.
271; Called from IOCtl worker in d32Win32kIOCtl.c and callgate.
272; @cproto APIRET _Optlink Win32kAPIRouter(ULONG ulFunction, PVOID pvParam);
273; @returns function return code.
274; 0xdeadbeef if invalid function number.
275; @param eax - ulFunction Function number to call.
276; @param edx - pvParam Parameter packet for that function.
277; @uses eax, edx, ecx
278; @sketch Validate function number
279; Fetch the parameter pacted from user mode and place it on the stack.
280; Validate the size field of the parameter packet.
281; Remove the packet header from the stack => we have a callframe for the api.
282; Call the API worker.
283; Return.
284; @status Completely implemented.
285; @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
286Win32kAPIRouter proc near
287 ASSUME ds:FLAT, es:nothing, ss:nothing
288 ;
289 ; Validate function number.
290 ;
291 test eax,eax
292 jnz APIR_notnull ; This code should be faster (though it may look stupid to
293 ; jump around like this). IIRC branch prediction allways
294 ; takes a branch. And btw there are 4 NOPs after this jump!
295 jmp APIR_InvalidFunction
296
297APIR_notnull:
298 cmp eax, K32_LASTIOCTLFUNCTION
299 jle APIR_ValidFunction
300APIR_InvalidFunction:
301 mov eax, 0deadbeefh
302 ret
303
304 ;
305 ; We have a valid function number now.
306 ; Copy the parameter struct on to the stack.
307 ;
308APIR_ValidFunction:
309 push ebp ; Make stack frame
310 mov ebp, esp
311 mov [ebp+8], eax ; Save eax on the stack (reserved by caller according to _Optlink)
312 mov ecx, acbK32Params[eax*4] ; ecx <- size of parameter packet.
313 sub esp, ecx ; Reserve stack space for the parameter packet.
314 mov eax, [pulTKSSBase32] ; Calculate the FLAT address of esp.
315 mov eax, [eax]
316 add eax, esp ; eax <- flat address of ss:esp
317 push ecx ; Save the size.
318 ; TKFuBuff(pv, pvParam, acbParams[ulFunction], TK_FUSU_NONFATAL);
319 push 0 ; TK_FUSU_NOFATAL
320 push ecx ; Size of parameter packet
321 push edx ; Pointer to user memory to fetch
322 push eax ; Pointer to target memory.
323 call _TKFuBuff@16 ; __stdcall (cleanup done by the called function)
324 pop ecx ; Restore size
325 test eax, eax
326 jz APIR_FetchOK
327 jmp APIR_end
328
329 ;
330 ; Parameter packet is now read onto the stack. esp is pointing to it.
331 ; Check the size of the struct as the caller sees it.
332 ;
333APIR_FetchOK:
334 cmp ecx, [esp] ; (esp now point at the parameter struct)
335 je APIR_sizeok
336 mov eax, ERROR_BAD_ARGUMENTS ; return code.
337 jmp APIR_end
338
339 ;
340 ; The size is correct.
341 ; Call the worker and return.
342 ;
343APIR_sizeok:
344 add esp, SIZE K32HDR ; Skip the parameter header.
345 mov eax, [ebp + 8] ; Restore function number.
346 mov eax, apfnK32APIs[eax*4] ; eax <- address of the K32 API worker.
347 call eax ; Call the worker.
348 ; No cleanup needed as leave takes care of that
349 ; We're ready for returning.
350APIR_end:
351 leave
352 ret
353Win32kAPIRouter endp
354
355
356;;
357; This is a stub function which does nothing but returning an error code.
358; @return ERROR_NOT_SUPPORTED
359k32APIStub proc near
360 mov eax, ERROR_NOT_SUPPORTED
361 ret
362k32APIStub endp
363
364CODE32 ends
365
366
367
368
369
370CODE16 segment
371 assume cs:CODE16, ds:FLAT
372
373;
374; Thunker used by the InitCallGate procedure call the AllocGDTSelector devhelper.
375;
376Thunk16_AllocGDTSelector:
377 call [_Device_Help]
378 jmp far ptr FLAT:Thunk32_AllocGDTSelector
379
380CODE16 ends
381
382end
383
Note: See TracBrowser for help on using the repository browser.