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

Last change on this file since 10367 was 6280, checked in by bird, 24 years ago

Kill API coding.

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