Mail Archives: djgpp-workers/2001/04/29/18:27:12
> > 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).
- Raw text -