source: trunk/src/kernel32/exceptutil.asm

Last change on this file was 21999, checked in by dmik, 13 years ago

kernel32: Make SEH work in OS/2 context.

See #82 for details.

File size: 10.7 KB
RevLine 
[10409]1; $Id: exceptutil.asm,v 1.26 2004-01-20 13:41:11 sandervl Exp $
[620]2
3;/*
4; * Project Odin Software License can be found in LICENSE.TXT
5; * Win32 Exception handling + misc functions for OS/2
6; *
7; * Copyright 1998 Sander van Leeuwen
8; *
9; */
10.386p
11 NAME except
12
[5557]13DATA32 segment dword use32 public 'DATA'
14DATA32 ends
15CONST32_RO segment dword use32 public 'CONST'
16CONST32_RO ends
17BSS32 segment dword use32 public 'BSS'
18BSS32 ends
19DGROUP group BSS32, DATA32
20 assume cs:FLAT, ds:FLAT, ss:FLAT, es:FLAT
21
22DATA32 segment dword use32 public 'DATA'
23
24CONST32_RO segment
25 align 04h
26@CBE8 db "KERNEL32: Calling handle"
27db "r at %p code=%lx flags=%"
28db "lx",0ah,0h
29@CBE9 db "KERNEL32: Handler return"
30db "ed %lx",0ah,0h
31CONST32_RO ends
32DATA32 ends
33
[620]34CODE32 SEGMENT DWORD PUBLIC USE32 'CODE'
[21916]35
36
[3275]37 public _RaiseException@16
[21916]38 extrn _OS2RaiseException : near
[620]39
[3275]40_RaiseException@16 proc near
[21916]41
42 ; _OS2RaiseException is _cdecl
43
[620]44 push ebp
[21916]45 mov ebp, esp
[620]46 push eax
[21916]47
48 mov eax, 0
49 mov eax, ss
[620]50 push eax
[21916]51 mov eax, gs
[620]52 push eax
53 mov eax, fs
54 push eax
[21916]55 mov eax, es
[620]56 push eax
[21916]57 mov eax, ds
[620]58 push eax
[21916]59 mov eax, cs
60 push cs
61 push esi
62 push edi
63 push edx
64 push ecx
65 push ebx
66 push dword ptr [ebp-4] ; original eax
67 pushfd
68 push dword ptr [ebp] ; original ebp
69 push ebp
70 add dword ptr [esp], 4 ; original esp
71 push dword ptr [ebp + 4] ; original eip (return address)
[620]72
[21916]73 push dword ptr [ebp + 20] ; arg 4 (DWORD *lpArguments)
74 push dword ptr [ebp + 16] ; arg 3 (DWORD cArguments)
75 push dword ptr [ebp + 12] ; arg 2 (DWORD dwExceptionFlags)
76 push dword ptr [ebp + 8] ; arg 1 (DWORD dwExceptionCode)
77
78 call _OS2RaiseException
79
80 add esp, 20 * 4
81
82 pop eax
83 pop ebp
84
[4106]85 ret 16 ;__stdcall
[21916]86
[3275]87_RaiseException@16 endp
[620]88
[21916]89
[3275]90 public _RtlUnwind@16
[21916]91 extrn _OS2RtlUnwind : near
[620]92
[3275]93_RtlUnwind@16 proc near
[21916]94
95 ; OS2RtlUnwind is _cdecl
96
[620]97 push ebp
[21916]98 mov ebp, esp
[620]99 push eax
[21916]100
101 mov eax, 0
102 mov eax, ss
[620]103 push eax
[21916]104 mov eax, gs
[620]105 push eax
106 mov eax, fs
107 push eax
[21916]108 mov eax, es
[620]109 push eax
[21916]110 mov eax, ds
[620]111 push eax
[21916]112 mov eax, cs
113 push cs
114 push esi
115 push edi
116 push edx
117 push ecx
118 push ebx
119 push dword ptr [ebp-4] ; original eax
120 pushfd
121 push dword ptr [ebp] ; original ebp
122 push ebp
123 add dword ptr [esp], 4 ; original esp
124 push dword ptr [ebp + 4] ; original eip (return address)
[620]125
[21916]126 push dword ptr [ebp + 20] ; arg 4 (DWORD returnEax)
127 push dword ptr [ebp + 16] ; arg 3 (PWINEXCEPTION_RECORD pRecord)
128 push dword ptr [ebp + 12] ; arg 2 (LPVOID unusedEip)
129 push dword ptr [ebp + 8] ; arg 1 (PWINEXCEPTION_FRAME pEndFrame)
130
131 call _OS2RtlUnwind
132
133 add esp, 20 * 4
134
135 pop eax
136 pop ebp
137
[4106]138 ret 16 ;__stdcall
[21916]139
[3275]140_RtlUnwind@16 endp
[620]141
142
[10409]143 PUBLIC OS2ExceptionHandler
144 EXTRN OS2ExceptionHandler2ndLevel:NEAR
145
146OS2ExceptionHandler proc near
147 ;Clear the direction flag (as specified by the _System calling convention)
148 ;(OS/2 doesn't bother checking before calling our exception handler)
149 cld
150 jmp OS2ExceptionHandler2ndLevel
151OS2ExceptionHandler endp
152
[21999]153
154 PUBLIC OSLibDispatchException
155 EXTRN OSLibDispatchExceptionWin32:NEAR
156 EXTRN ___seh_handler_filter:NEAR
157
158; BOOL APIENTRY OSLibDispatchException(PEXCEPTIONREPORTRECORD pReportRec,
159; PEXCEPTIONREGISTRATIONRECORD pRegistrationRec,
160; PCONTEXTRECORD pContextRec, PVOID p,
161; BOOL fSEH);
162OSLibDispatchException proc near
163 cmp dword ptr [esp + 20], 0 ; fSEH == FALSE?
164 jz OSLibDispatchExceptionWin32
165 jmp ___seh_handler_filter
166OSLibDispatchException endp
167
168
[21916]169 PUBLIC _QueryExceptionChain
[620]170
[21916]171_QueryExceptionChain proc near
[620]172 mov eax, fs:[0]
173 ret
[21916]174_QueryExceptionChain endp
[620]175
176 PUBLIC GetExceptionRecord
177GetExceptionRecord proc near
178 push ebp
179 mov ebp, esp
180 push fs
181 push ebx
182
183 mov eax, [ebp+8]
184 mov fs, eax
185 mov ebx, [ebp+12]
186 mov eax, fs:[ebx]
187
188 pop ebx
189 pop fs
190 pop ebp
191 ret
192GetExceptionRecord endp
193
194 PUBLIC ChangeTIBStack
195ChangeTIBStack proc near
196; xor eax, eax
197 push ebx
198 mov eax, fs:[4]
199 mov ebx, fs:[8]
200 add ebx, 8
201 mov fs:[4], ebx
202 mov fs:[8], eax
203 pop ebx
204 ret
205ChangeTIBStack endp
206
207 PUBLIC _SetExceptionChain
208
209_SetExceptionChain proc near
210 mov eax, dword ptr [esp+4]
211 mov fs:[0], eax
212 ret
213_SetExceptionChain endp
214
215
[9913]216;;ULONG CDECL AsmCallThreadHandler(BOOL fAlignStack, ULONG handler, LPVOID parameter);
[5354]217 PUBLIC _AsmCallThreadHandler
218_AsmCallThreadHandler proc near
219 push ebp
220 mov ebp, esp
221
[9913]222;first check if we have 128kb stack or more; if not, then skip the stack alignment code
223 mov eax, [ebp+8]
224 cmp eax, 0
225 je @goodthreadstack
226
[9754]227;We're asking for problems if our stack start near a 64kb boundary
[9780]228;Some OS/2 thunking procedures can choke if there's not enough stack left
[9754]229 mov eax, esp
230 and eax, 0FFFFh
231 cmp eax, 0E000h
232 jge @goodthreadstack
233
[9780]234 ;set ESP to the top of the next 64kb block and touch each
235 ;page to make sure the guard page exception handler commits
236 ;those pages
237 mov edx, esp
238 sub edx, eax
239
240 and esp, 0FFFFF000h
241 dec esp
242
243@touchthreadstackpages:
244 mov al, byte ptr [esp]
245
246 sub esp, 1000h
247
248 cmp esp, edx
249 jg @touchthreadstackpages
250
251 mov esp, edx
252 sub esp, 16
253
[9822]254 ;also touch this page
255 mov eax, dword ptr [esp]
256
[9754]257@goodthreadstack:
258
[10409]259 mov eax, esp
260 sub eax, 16
261 and eax, 0FFFFFFF0h
262;now we make sure the stack is aligned at 16 bytes when the entrypoint is called
263;(8+4+4(return address) = 16)
264 add eax, 8
265 mov esp, eax
266
[9913]267 push dword ptr [ebp+16]
268 mov eax, dword ptr [ebp+12]
[5354]269 call eax
270
271 mov esp, ebp
272 pop ebp
273 ret
274_AsmCallThreadHandler endp
275
[6133]276 PUBLIC _CallEntryPoint
277_CallEntryPoint proc near
278 push ebp
279 mov ebp, esp
280
[9441]281;We're asking for problems if our stack start near a 64kb boundary
[9780]282;Some OS/2 thunking procedures can choke if there's not enough stack left
[6133]283 mov eax, esp
[9441]284 and eax, 0FFFFh
285 cmp eax, 0E000h
[9780]286 jge @goodmainstack
[9441]287
[9780]288 ;set ESP to the top of the next 64kb block and touch each
289 ;page to make sure the guard page exception handler commits
290 ;those pages
291 mov edx, esp
292 sub edx, eax
[9441]293
[9780]294 and esp, 0FFFFF000h
295 dec esp
296
297@touchmainstackpages:
298 mov al, byte ptr [esp]
299
300 sub esp, 1000h
301
302 cmp esp, edx
303 jg @touchmainstackpages
304
305 mov esp, edx
306 sub esp, 16
307
[9822]308 ;also touch this page
309 mov eax, dword ptr [esp]
310
[9780]311@goodmainstack:
312
[9441]313 mov eax, esp
[6133]314 sub eax, 16
315 and eax, 0FFFFFFF0h
[10409]316;now we make sure the stack is aligned at 16 bytes when the entrypoint is called
317;(8+4+4(return address) = 16)
318 add eax, 8
[6133]319 mov esp, eax
320
321 push dword ptr [ebp+12]
322 mov eax, dword ptr [ebp+8]
323 call eax
324
325 mov esp, ebp
326 pop ebp
327 ret
328_CallEntryPoint endp
329
[21916]330ifndef __EMX__
[6133]331
[5557]332 EXTRN WriteLog:PROC
333 EXTRN _GetThreadTEB@0:PROC
334IFDEF DEBUG
[21916]335 EXTRN _DbgEnabledKERNEL32:DWORD
[5557]336ENDIF
337
[21916]338; 129 static inline WINEXCEPTION_FRAME * EXC_push_frame( WINEXCEPTION_FRAME *frame )
339 align 04h
340
341EXC_push_frame proc
[5557]342 push ebp
343 mov ebp,esp
344 sub esp,04h
345 mov [ebp+08h],eax; frame
346
347; 132 TEB *teb = GetThreadTEB();
348 call _GetThreadTEB@0
349 mov [ebp-04h],eax; teb
350
351; 133 frame->Prev = (PWINEXCEPTION_FRAME)teb->except;
352 mov ecx,[ebp-04h]; teb
353 mov ecx,[ecx]
354 mov eax,[ebp+08h]; frame
355 mov [eax],ecx
356
357; 134 teb->except = frame;
358 mov eax,[ebp-04h]; teb
359 mov ecx,[ebp+08h]; frame
360 mov [eax],ecx
361
362; 135 return frame->Prev;
363 mov eax,[ebp+08h]; frame
364 mov eax,[eax]
365 leave
366 ret
[21916]367EXC_push_frame endp
[5557]368
369; 138 static inline WINEXCEPTION_FRAME * EXC_pop_frame( WINEXCEPTION_FRAME *frame )
370 align 04h
371
[21916]372EXC_pop_frame proc
[5557]373 push ebp
374 mov ebp,esp
375 sub esp,04h
376 mov [ebp+08h],eax; frame
377
378; 141 TEB *teb = GetThreadTEB();
379 call _GetThreadTEB@0
380 mov [ebp-04h],eax; teb
381
382; 142 teb->except = frame->Prev;
383 mov ecx,[ebp+08h]; frame
384 mov ecx,[ecx]
385 mov eax,[ebp-04h]; teb
386 mov [eax],ecx
387
388; 143 return frame->Prev;
389 mov eax,[ebp+08h]; frame
390 mov eax,[eax]
391 leave
392 ret
[21916]393EXC_pop_frame endp
[5557]394
[21916]395; 281 static extern "C" DWORD EXC_CallHandler( WINEXCEPTION_RECORD *record, WINEXCEPTION_FRAME *frame,
[5557]396 align 04h
[21916]397 PUBLIC _EXC_CallHandler
[5557]398
[21916]399_EXC_CallHandler proc
[5557]400 push ebp
401 mov ebp,esp
402 sub esp,010h
403 sub esp,04h
404 mov [ebp+08h],eax; record
405 mov [ebp+0ch],edx; frame
406 mov [ebp+010h],ecx; context
407
408; 296 newframe.frame.Handler = nested_handler;
409 mov eax,[ebp+01ch]; nested_handler
410 mov [ebp-08h],eax; newframe
411
412; 297 newframe.prevFrame = frame;
413 mov eax,[ebp+0ch]; frame
414 mov [ebp-04h],eax; newframe
415
416; 298 EXC_push_frame( &newframe.frame );
417 lea eax,[ebp-0ch]; newframe
[21916]418 call EXC_push_frame
[5557]419
420; 299 dprintf(("KERNEL32: Calling handler at %p code=%lx flags=%lx\n",
421IFDEF DEBUG
[21916]422 cmp word ptr _DbgEnabledKERNEL32+020h,01h
[5557]423 jne @BLBL20
424 mov eax,[ebp+08h]; record
425 push dword ptr [eax+04h]
426 mov eax,[ebp+08h]; record
427 push dword ptr [eax]
428 push dword ptr [ebp+018h]; handler
429 push offset FLAT:@CBE8
430 call WriteLog
431 add esp,010h
432ENDIF
433
434; 300 handler, record->ExceptionCode, record->ExceptionFlags));
435@BLBL20:
436
437; 301 ret = handler( record, frame, context, dispatcher );
438 push dword ptr [ebp+014h]; dispatcher
439 push dword ptr [ebp+010h]; context
440 push dword ptr [ebp+0ch]; frame
441 push dword ptr [ebp+08h]; record
442 call dword ptr [ebp+018h]; handler
443 mov [ebp-010h],eax; ret
444
445IFDEF DEBUG
446; 302 dprintf(("KERNEL32: Handler returned %lx\n", ret));
[21916]447 cmp word ptr _DbgEnabledKERNEL32+020h,01h
[5557]448 jne @BLBL21
449 push dword ptr [ebp-010h]; ret
450 push offset FLAT:@CBE9
451 call WriteLog
452 add esp,08h
453@BLBL21:
454ENDIF
455
456; 303 EXC_pop_frame( &newframe.frame );
457 lea eax,[ebp-0ch]; newframe
[21916]458 call EXC_pop_frame
[5557]459
460; 304 return ret;
461 mov eax,[ebp-010h]; ret
462 add esp,04h
463 leave
464 ret
[21916]465_EXC_CallHandler endp
[5557]466
[21916]467endif ; ifndef __EMX__
468
[620]469CODE32 ENDS
470
471 END
Note: See TracBrowser for help on using the repository browser.