From: "The Owl" To: Eli Zaretskii Date: Sun, 29 Apr 2001 23:14:16 +0200 MIME-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Subject: Re: win2000/ntvdm/djgpp (fwd) CC: sandmann AT clio DOT rice DOT edu, djgpp-workers AT delorie DOT com Message-ID: <3AECA048.20910.63E613@localhost> In-reply-to: <7263-Sun29Apr2001212412+0300-eliz@is.elta.co.il> References: <3AEC65FA DOT 5812 DOT 13D9D56A AT localhost> (theowl AT freemail DOT c3 DOT hu) X-mailer: Pegasus Mail for Win32 (v3.12c) Reply-To: djgpp-workers AT delorie DOT com Errors-To: nobody AT delorie DOT com X-Mailing-List: djgpp-workers AT delorie DOT com X-Unsubscribes-To: listserv AT delorie DOT com Precedence: bulk > > unfortunately no attempt at setting the real mode PSP will have any > > effect on _CurrentPSPSelector (as far as i can tell). > > Does this mean that the set-PSP event which causes NTVDM to set > _CurrentPSPSelector is the PM interrupt issued by DOSX? If not, who > else can issue such interrupts? the set-PSP event chain is started by a dpmi app issuing a pm int 21. this in turn will call the pm int handler in dosx (called PMINTRDOS) which then will use the Bop interface (ie. not a pm int) to tell ntvdm to handle this int 21 (in _DpmiXlatInt21Call AT 0). ntvdm (for ah=50) calls _SetPSP AT 0 which first translates the PSP selector to a real mode segment then switches to real mode and reflects the interrupt. and it also stores the PSP selector in _CurrentPSPSelector. real mode (v86) ints will never end up executing _SetPSP AT 0 in ntvdm. > I can't say I like this solution too much (for the reasons you > yourself mentioned), but perhaps people could try this patch and see > how easy it is to patch NTVDM, before we decide. i see only one other way, but i have yet to verify if it will work reliably. in any case, here it goes: instead of issuing a pm int 21/50, we can try to issue a pm int 21/51 (that is, get PSP). a similar chain of events as described above will lead to executing _GetPSP AT 0 in ntvdm. this will first switch to real mode and reflect down the interrupt and once it returns, the situation becomes really interesting to us. first of all, _GetPSP AT 0 looks up the base address of _CurrentPSPSelector in an internal 'cache' called _FlatAddress which is basically an array of base addresses for all allocated LDT selectors (it is indexed by the selector itself). next it shifts the base address to the right by 4 (essentially converting it to a segment value) and compares it to the real mode PSP returned in the bx register. if they are equal, _GetPSP AT 0 simply returns _CurrentPSPSelector to the dpmi app, otherwise it will convert the real mode PSP segment to a selector by calling _SegmentToSelector AT 8 and return that to the dpmi app *and* update _CurrentPSPSelector as well. now this is the point where i have some doubts. namely, after the ntvdm bug is triggered and _CurrentPSPSelector gets zeroed out, the above cache lookup will compare the current real mode PSP against whatever the base value of the first LDT selector is (that is what a 0 selector will look up). if we are lucky (and i hope we are), then this value will always be different from any possible real mode PSP segment value and therefore the call to _SegmentToSelector AT 8 will always be issued. the reason we want this to happen is that this function is clever enough to try to look up an already existing selector that maps the given segment which in our case will always succeed (since the parent is still running). in the worst case, we would end up creating a new selector (and leak it as well, but it is probably the least issue). so, we have two potential solutions, with different benefits and drawbacks. patch: + no need to modify anything in djgpp + 'guaranteed' to work (as in i am already running it happily ;-) - users will have to patch a system file, probably no hassle in a home environment, but in a corporate one it can be - patch has to be updated with each new version of ntvdm (until MS fixes the problem) - potentially a legal problem, we most definitely could not distribute a patched ntvdm (anyone thought of djvdm? ;-), at most release the patch info (which i actually did already, hopefully no problems will arise) getPSP: + no legal issues -+ not yet clear if it will work 100% reliably (although i am quite sure that it will as it seems that noone really wants to allocate the first LDT selector, and the cache itself is 0 initialized and no real mode PSP segment should exist there) - libc has to be modified plus all apps recompiled/linked that spawn dpmi apps. honestly, i could not tell you what way to go, for now i am personnaly satisfied with what i have. what the djgpp folks should do, i leave it up to you. > Won't this cause trouble when it really is time to put zero in > _CurrentPSPSelector, i.e. when the DOS box is closing? i was not clear enough: my patch does NOT prevent ntvdm from zeroing out _CurrentPSPSelector (it still will), but _DpmiFreeAppXmem AT 0 will rely on the dx register (properly filled in by dosx) instead of _CurrentPSPSelector to determine the 'current dpmi app' (and since _DpmiFreeAppXmem AT 0 is called only from _DpmiTerminateApp AT 0, there should not be undesired side effects).