VxDCall vwin32 service id 0x0010 provides int21 dispatch functionality and VxDCall vwin32 service id 0x002a provides int41 dispatch functionality.
All of these vwin32 services together with existing service id 0x0029 (for int31/dpmi functionality) have same API, first VxDCall() argument is value for EAX register and second argument is value for ECX register.
VxDCall vwin32 service id 0x0010 is used by applications in Andrew Schulman's book Unauthorized Windows 95. For example by CHGDIR for getting PSP.
-- v2: vwin32.vxd: Add support for VxDCall() 0x0010 and 0x002a services
From: Pali Rohár pali@kernel.org
VxDCall vwin32 service id 0x0010 provides int21 dispatch functionality and VxDCall vwin32 service id 0x002a provides int41 dispatch functionality.
All of these vwin32 services together with existing service id 0x0029 (for int31/dpmi functionality) have same API, first VxDCall() argument is value for EAX register and second argument is value for ECX register.
VxDCall vwin32 service id 0x0010 is used by applications in Andrew Schulman's book Unauthorized Windows 95. For example by CHGDIR for getting PSP.
Signed-off-by: Pali Rohár pali@kernel.org --- dlls/vwin32.vxd/vwin32.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-)
diff --git a/dlls/vwin32.vxd/vwin32.c b/dlls/vwin32.vxd/vwin32.c index 38a3694127b..e176010baf4 100644 --- a/dlls/vwin32.vxd/vwin32.c +++ b/dlls/vwin32.vxd/vwin32.c @@ -199,23 +199,38 @@ DWORD WINAPI VWIN32_VxDCall( DWORD service, CONTEXT *context ) */ return 0x0405; } + case 0x0010: /* Int21 dispatch */ case 0x0029: /* Int31/DPMI dispatch */ + case 0x002a: /* Int41 dispatch */ { - DWORD callnum = stack32_pop(context); - DWORD parm = stack32_pop(context); + BYTE intnum = 0; + + context->Eax = stack32_pop( context ); + context->Ecx = stack32_pop( context ); + + switch ( LOWORD( service ) ) + { + case 0x0010: /* Int21 dispatch */ + intnum = 0x21; + break; + case 0x0029: /* Int31/DPMI dispatch */ + intnum = 0x31; + break; + case 0x002a: /* Int41 dispatch */ + intnum = 0x41; + break; + }
- TRACE("Int31/DPMI dispatch(%08lx)\n", callnum); + TRACE( "Int%x dispatch: " + "eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, " + "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx\n", + intnum, + context->Eax, context->Ebx, context->Ecx, + context->Edx, context->Esi, context->Edi );
- context->Eax = callnum; - context->Ecx = parm; - __wine_call_int_handler16( 0x31, context ); + __wine_call_int_handler16( intnum, context ); return LOWORD(context->Eax); } - case 0x002a: /* Int41 dispatch - parm = int41 service number */ - { - DWORD callnum = stack32_pop(context); - return callnum; /* FIXME: should really call INT_Int41Handler() */ - } default: FIXME("Unknown service %08lx\n", service); return 0xffffffff;
On Sun Apr 27 15:39:10 2025 +0000, Alexandre Julliard wrote:
Again, for this and the other changes, please always explain what application is fixed by the change. If it doesn't fix any known application, please don't touch the code at all. This is old and mostly bitrotten code that we don't want to have to spend more time on.
It is used by applications in the Andrew Schulman's book Unauthorized Windows 95. VxDCall from 32-bit PE binaries is used to issue 16-bit DOS calls, for example getting the PSP in CHGDIR.
The minimal reproducer for the issue with PSP is: ```c #include <stdio.h> #include <windows.h>
__declspec(dllimport) DWORD WINAPI VxDCall2(DWORD srvc, DWORD eax, DWORD ecx);
#define VWIN32_INT21_CALL 0x2A0010 #define DosCall(eax, ecx) VxDCall2(VWIN32_INT21_CALL, (eax), (ecx))
int main() { WORD psp; // Call DOS INT 21h function 62h (Get PSP) _asm mov bx, 0 DosCall(0x6200, 0); _asm mov psp, bx printf("PSP: %04Xh\n\n", psp); return 0; } ```
Without this change the PSP is zero.
Now I have rebased this merge request and tested also this minimal reproducer against wine and Win95 that it works and returns PSP.
This is old and mostly bitrotten code that we don't want to have to spend more time on.
Does it mean that the 16-bit NE-related code is forbidden to improve and changes for fixing compatibility with Win3.x/Win9x from developers outside of the project would not be accepted? Just want to know as I do not want to spend time on preparing something, which would not be taken.
Does it mean that the 16-bit NE-related code is forbidden to improve and changes for fixing compatibility with Win3.x/Win9x from developers outside of the project would not be accepted? Just want to know as I do not want to spend time on preparing something, which would not be taken.
They are accepted provided that they fix actual applications that users may want to run. Fixing sample code from Schulman's book is not particularly useful, unless there is evidence that this code has been used in real applications.
On Sun Apr 27 19:28:17 2025 +0000, Alexandre Julliard wrote:
Does it mean that the 16-bit NE-related code is forbidden to improve
and changes for fixing compatibility with Win3.x/Win9x from developers outside of the project would not be accepted? Just want to know as I do not want to spend time on preparing something, which would not be taken. They are accepted provided that they fix actual applications that users may want to run. Fixing sample code from Schulman's book is not particularly useful, unless there is evidence that this code has been used in real applications.
Those examples are good starting point for any debugging. Without understanding what is going wrong in small examples, it is impossible at least for me to fix the actually crashing application.
For me the first thing is to figure out why the wine's behavior deviates from the original Windows behavior. And this is one example which is aligning wine's behavior to Windows one, and make one part of the CHGDIR application to not crash.
On Sat May 3 10:04:45 2025 +0000, Pali Rohár wrote:
Those examples are good starting point for any debugging. Without understanding what is going wrong in small examples, it is impossible at least for me to fix the actually crashing application. For me the first thing is to figure out why the wine's behavior deviates from the original Windows behavior. And this is one example which is aligning wine's behavior to Windows one, and make one part of the CHGDIR application to not crash.
All changes have a cost, in reviewer's time, in code churn, in possible regressions. The cost needs to be balanced by an actual benefit, i.e. it should improve something for a real user.
That's doubly true for very old 16-bit code. If no user has run into these issues for all these years, and with 16-bit usefulness dwindling, it seems unlikely that making changes there would have any benefit. Simply "aligning behavior with Windows" is not considered a benefit in itself, particularly in such old code.
If you have a real application that's crashing, please file a bug about it, and then we can discuss how to fix it, ideally with a minimal amount of changes.