From: sandmann AT clio DOT rice DOT edu (Charles Sandmann) Message-Id: <10109230603.AA14592@clio.rice.edu> Subject: Win2K/XP nesting fix To: djgpp-workers AT delorie DOT com (DJGPP developers) Date: Sun, 23 Sep 2001 01:03:38 -0500 (CDT) Cc: theowl AT freemail DOT c3 DOT hu X-Mailer: ELM [version 2.5 PL2] Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Reply-To: djgpp-workers AT delorie DOT com On my long list of things to do was to test alternate ways of fixing the nesting crash on Win2K and XP. On the basis of a "maybe" from The Owl, I tried to replace our set psp call with a PM get psp call. At the same time I replaced the call to int86 with a line of in-line assembler to avoid namespace issues with int86 and code bloat. The getpsp call seems to work just as well as the setpsp call on the tests I've run. The getpsp code is much safer (it could be called under any DPMI provider) and requires less code to set up. I would recommend getting rid of the windows version test code and testing entirely on the DOS version 0x532 (which will someday be stored in a global variable ...) - and on that basis doing the very simple getpsp code. If some strange DOS version advertises like NT the getpsp will still be harmless and just waste an interrupt call. Included is prelim difference for comments - doing more testing now. It would have been nice to have this in Andrew's most recent update on clio, but that's life. *** dpmiexcp.c_ Fri Sep 7 00:38:42 2001 --- dpmiexcp.c Sun Sep 23 01:02:30 2001 *************** *** 21,27 **** #include #include /* For DS base/limit info */ #include - #include #define err(x) _write(STDERR_FILENO, x, sizeof(x)-1) --- 21,26 ---- *************** __djgpp_set_ctrl_c(int enable_sigs) *** 586,614 **** return oldenable; } - unsigned short _windows_major, _windows_minor; - - /* Compute the version Windows reports via Int 2Fh/AX=1600h. */ - static void - get_windows_version(void) - { - if (!_windows_major) - { - __dpmi_regs r; - - r.x.ax = 0x1600; - __dpmi_int(0x2f, &r); - if (r.h.al > 2 && r.h.al != 0x80 && r.h.al != 0xff - && (r.h.al > 3 || r.h.ah > 0)) - { - _windows_major = r.h.al; - _windows_minor = r.h.ah; - } - else - _windows_major = 0xff; /* meaning no Windows */ - } - } - /* A work-around for a bug in W2K's NTVDM, suggested by The Owl . --- 585,590 ---- *************** get_windows_version(void) *** 628,641 **** DOSX does pass the parent PSP selector to NTVDM when it notifies it about a DPMI program exit, but NTVDM does not use this information.) ! To work around that, we force NTVDM to record a valid PSP before we ! exit. We do that by invoking a PM Int 21h, function 50h, passing ! it our PM selector for the PSP, as it was returned by the PM switch ! entry point we called at startup to enter protected mode. We do ! that just before exiting, to make sure that even an application ! which crashes (e.g., due to SIGSEGV or Ctrl-BREAK) immediately ! after its child returns will always leave its valid PSP recorded by ! NTVDM before it exits. (To play it safe in the face of non-DJGPP DPMI programs and old DJGPP programs, we also restore the PSP in dosexec.c, which see.) --- 604,616 ---- DOSX does pass the parent PSP selector to NTVDM when it notifies it about a DPMI program exit, but NTVDM does not use this information.) ! To work around that, we ask NTVDM to record a valid PSP before we ! exit. We do that by invoking a PM Int 21h, function 51h, which gets ! the PM selector for the PSP (which triggers NTVDM to record the ! correct internal value). We do that just before exiting, to make ! sure that even an application which crashes (e.g., due to SIGSEGV ! or Ctrl-BREAK) immediately after its child returns will always leave ! its valid PSP recorded by NTVDM before it exits. (To play it safe in the face of non-DJGPP DPMI programs and old DJGPP programs, we also restore the PSP in dosexec.c, which see.) *************** get_windows_version(void) *** 646,667 **** void __maybe_fix_w2k_ntvdm_bug(void) { ! /* The _osmajor == 0 case takes care of a crash that happens before ! we had a chance to get DOS version. (Yes, I am being paranoiac!) */ ! if ((_osmajor == 5 || _osmajor == 0) && _osminor == 0 ! && _get_dos_version(1) == 0x0532) /* NT or Windows 2000? */ ! { ! get_windows_version(); ! if (_windows_major == 0xff) /* this is NT or W2K */ ! { ! extern int _int86(int ivec, union REGS *in, union REGS *out); ! union REGS regs; ! ! regs.h.ah = 0x50; ! regs.d.ebx = _stubinfo->psp_selector; ! _int86 (0x21, ®s, ®s); ! } ! } } void __attribute__((noreturn)) --- 621,632 ---- void __maybe_fix_w2k_ntvdm_bug(void) { ! if (_osmajor == 5 && _get_dos_version(1) == 0x0532) /* NT or Windows 2000? */ ! { ! /* Protected mode call to GetPSP - may return RM PSP if not extended */ ! asm volatile("movb $0x51, %%ah ; int $0x21" ! : : : "ax", "bx" ); /* input, output, regs */ ! } } void __attribute__((noreturn))