WINPKT theory Joe Doupnik 17 Dec 1991 Here's the simple story on calling a Windows application from a driver/TSR loaded before Windows starts. This shim behaves like an application to a Packet Driver. To the real application it looks like a Packet Driver on another interrupt. There are four essential steps. 1. Recognize when Windows starts operation. This is done by monitoring Int 2Fh (Multiplexor Int) for such a broadcast by Windows. Since a lot of apps also use Int 2Fh in various ways this one method seems to avoid being deceived by other apps (including NetWare shells). We do the same monitor and pass-on operation when Windows broadcasts it is shutting down. In summary, this part tells the driver when an Environment is active. ; Windows (and many many other programs) use the Int 2Fh Multiplexor link, ; and each is supposed to grab it's own calls as seen in AX, or chain them ; to the previous Int 2Fh owner. Windows 3 uses function 16h for most work. ; This is our Int 2Fh routine. our_2f_isr: assume ds:nothing, es:nothing cmp ax,1608h ; Windows Enhanced "Init completed" broadcast? jne our_2f_1 ; ne = not that function, chain it mov vmm_running,1 ; remember that Windows has started jmp their_2f_isr ; pass it on down the chain our_2f_1: cmp ax,1609h ; Windows Enhanced "Begin Exit" broadcast? jne our_2f_2 ; ne = no mov vmm_running,0 ; remember that Windows has stopped our_2f_2: jmp their_2f_isr ; propagate broadcasts down the Int 2Fh chain ---------------- 2. When the application attaches to the driver it uses a Packet Driver interrupt. When that happens ask Windows for the virtual machine then in use and remember it with the app's request info. access_type_4: mov [bx].their_handle,ax ; handle returned in ax mov _AX[bp],ax ; save return handle cmp vmm_running,0 ; Windows Enhanced mode running? je access_type_5 ; e = no push bx ; Windows "Get Current Virtual Mach" mov ax,1683h int 2fh ; get current VM_ID to bx mov ax,bx pop bx mov [bx].vm_id,ax ; save ident as part of our handle access_type_5: --------------------- 3. When the driver is invoked by an interrupt from the lan adapter hardware it wants to call the application to deliver a packet. It needs to know the virtual machine ident so the correct v.m. will receive the call, else disaster. Int 2Fh again, as shown below. This step gets the current v.m. and compares it with that of the application needing calling. If the v.m.'s are the same then do a double call of the application in real time. Otherwise do step 4. push bx mov ax,1683h ; Windows, get current vir mach ident int 2fh mov ax,bx ; ident returned in bx pop bx cmp ax,[bx].vm_id ; same as the one the app is using? je our_handler_5 ; e = yes, correct VM is running jmp our_handler_7 ; no, another VM is running, switch to wanted our_handler_5: ; inc gvm_pkts call pass_to_app ; copy buffer to application, via double call retf pass_to_app: xor ax,ax ; set up register for first upcall to app mov bx,their_bx ; handle from Packet Driver mov cx,buffer_len ; packet size push ds call their_handler ; do first upcall (request buffer address) pop ds mov ax,es ; check for 0:0 as reject value or ax,ax jnz pass_to_app_1 ; nz = have an address or di,di ; check for 0:offset (rather unlikely) jnz pass_to_app_1 ; nz = have an offset mov buffer_flag,0 ; packet is being declined, free our buffer ret pass_to_app_1: ; copy from our buffer to app's es:di push di mov cx,buffer_len mov si,offset our_buffer cld rep movsb ; copy frame into apps buffer mov ax,1 ; set up regs for second upcall mov bx,their_bx ; handle mov cx,buffer_len ; report packet length too pop si mov dx,es push ds mov ds,dx assume ds:nothing call their_handler ; call the application pop ds assume ds:code mov buffer_flag,0 ; free buffer ret ---------------------- 4. Have Windows invoke the desired virtual machine and then we call the application (twice in rapid succession, once to get a buffer pointer and then to tell the app the copy has completed). As noted Windows may delay invoking the target v.m. by a long time and thus this shim must buffer the incoming packet to both clear the lan adapter and to reenable interrupts. We tell Windows to call us when the correct v.m. is available. We ought to declare critical regions in both steps 3 and 4, and maybe I will if trouble ensues later on. ; Windows Enhanced, request virtual machine in bx, and call back at es:di ; when it's ready (which, knowing Windows, may take quite a while, hence ; the requirement to buffer the packet to clear the lan board and ints). our_handler_7: ; inc bvm_pkts mov ax,1685h ; request switch VMs and callback mov bx,[bx].vm_id ; virtual machine of the app xor cx,cx ; flags (bits 0 and 1), zero is don't wait mov dx,40h ; dx:si is priority boost xor si,si push cs pop es ; es:di is address of callback routine mov di,offset our_callback int 2fh retf assume ds:nothing our_callback: ; get here with correct virtual machine push ax ; call application twice (a la PD) to deliver push bx ; the buffered packet push cx push dx push si push di push ds push es push bp mov ax,cs mov ds,ax ; set up our ds assume ds:code call pass_to_app pop bp pop es pop ds assume ds:nothing pop di pop si pop dx pop cx pop bx pop ax iret -------------------------------------------------------------------------