f16ptr typedef ptr far16 f32ptr typedef ptr far32 ;============================================================================== ; save all 16-bit registers, except dx:ax ; ;============================================================================== SAVEALL macro push cx ; save all 16-bit registers, except dx:ax push bx push bp push si push di push ds push es endm ;============================================================================== ; restore all 16-bit registers, except dx:ax ; ;============================================================================== RESTOREALL macro StackType:= POPW es ; restore all 16-bit registers, except dx:ax CHECKW ds, StackType POPW ds CHECKW di, StackType pop di CHECKW si, StackType pop si CHECKW bp, StackType pop bp pop bx pop cx endm ;============================================================================== ; test two text macros for equality ; ; ;============================================================================== TextEqual? macro Text_1, Text_2 ifidni , exitm endif exitm <0> endm ;============================================================================== ; test two text macros for difference ; ; ;============================================================================== TextDiff? macro Text_1, Text_2 ifidni , exitm <0> endif exitm endm ;============================================================================== ; check a word on top of the stack ; if not equal, break ; ;============================================================================== CHECKW macro CurrentReg, StackType:= if (@WordSize eq 4) and TextDiff? (&StackType&,Stack16) push eax mov ax,&CurrentReg& cmp ax,word ptr [esp+4] pop eax je @F int 3 @@: else push bp push ax mov ax,&CurrentReg& mov bp,sp and ebp,0ffffh cmp ax,word ptr [ebp+4] pop ax pop bp je @F int 3 @@: endif endm ;============================================================================== ; pop word ; ;============================================================================== POPW macro SegReg if @WordSize eq 4 db 66h endif pop SegReg endm ;============================================================================== ; pop dword ; ;============================================================================== POPD macro SegReg if @WordSize eq 2 db 66h endif pop SegReg endm ;============================================================================== ; operand-size override ; ;============================================================================== OTHER_OPERAND_SIZE macro arg db 66h arg endm ;============================================================================== ; address-size override ; ;============================================================================== OTHER_ADDRESS_SIZE macro arg db 67h arg endm ;============================================================================== ; allocate and public a byte flag ; ;============================================================================== PubByte macro name, value public name name db value endm ;============================================================================== ; log an api call, 16-bit ; ;============================================================================== APILOG16 macro argName, argFlag, argComment local do_it,done,szApiName ifdef DEBUG externDef PCodeDebug16:far16 externDef OutputDebugString:far16 push ds push ax mov ax,seg &argFlag mov ds,ax cmp &argFlag,0 je done jmp do_it szApiName db 'Api 16=>32: &argName& &argComment&',0Ah,0Dh,0 do_it: push seg szApiName push offset szApiName call OutputDebugString done: pop ax pop ds call PCodeDebug16 endif endm ;============================================================================== ; log an api call, 32-bit ; ;============================================================================== APILOG macro argName, argFlag local do_it,done,szApiName ifdef DEBUG ;externDef _DbgPrint:near32 ;;If argFlag is nonzero, print out the message. cmp argFlag&,0 jnz do_it jmp short done ;;Define the name here so we can pass it to _DbgPrint. szApiName db '&argName&',0 do_it: push offset FLAT:szApiName push offset FLAT:szApiFmt ;call _DbgPrint add esp,2*4 done: endif endm ;============================================================================== ; log 16-bit api return, in 32-bit code ; ;============================================================================== RETLOG macro argFlag local do_it, done, szRetFmt ifdef DEBUG externDef argFlag&:byte ;externDef _DbgPrint:near32 cmp argFlag&,0 je done jmp do_it szRetFmt db "Ret 16=>32: %4x:%4x",0dh,0ah,0 do_it: push eax ;;save return code value push edx push word ptr 0 ;;parameters to _DbgPrint push ax push word ptr 0 push dx push offset szRetFmt ;call _DbgPrint add esp,3*4 pop edx ;;restore return code pop eax done: endif endm ;============================================================================== ; conditionally break ; ;============================================================================== SWITCHABLE_INT3 macro argLabel, argFlag externDef argLabel :far16 push ds push ax mov ax,seg &argFlag mov ds,ax cmp &argFlag,0 je @F argLabel& label far16 int 3 @@: pop ax pop ds endm ;============================================================================== ; ; ;============================================================================== STUB0 macro module, argLabel, nBytes, argComment:= externDef argLabel&16 :far16 argLabel&16 label far16 ifdef FSAVEALL SAVEALL endif APILOG16 argLabel&16, f&module&ApiLog, argComment ifdef INT3 SWITCHABLE_INT3 argLabel&_stub, f&module&Int3 endif xor ax,ax cwd ifdef FSAVEALL RESTOREALL endif retf &nBytes& endm ;============================================================================== ; ; ;============================================================================== STUB macro module, argLabel, nBytes, nRetAX, argComment:= externDef argLabel&16 :far16 externDef PCodeDebug16 :far16 argLabel&16 label far16 ifdef FSAVEALL SAVEALL endif APILOG16 argLabel&16, f&module&ApiLog, argComment nRetAX ifdef INT3 SWITCHABLE_INT3 argLabel&_stub, f&module&Int3 endif mov ax,&nRetAX ifdef FSAVEALL RESTOREALL endif retf nBytes endm ;============================================================================== ; repack TEXTMETRIC from 32-bit to 16-bit ; ;============================================================================== PACK_TEXTMETRIC_32_16 macro lodsd ; first 8 int widened stosw lodsd stosw lodsd stosw lodsd stosw lodsd stosw lodsd stosw lodsd stosw lodsd stosw add esi,12 ; 9 bytes moved to end movsd movsd movsb sub esi,21 ; final 3 int lodsd stosw lodsd stosw lodsd stosw endm ;============================================================================== ; repack TEXTMETRIC from 16-bit to 32-bit ; ;============================================================================== PACK_TEXTMETRIC_16_32 macro lodsw ; first 8 int widened cwde stosd lodsw cwde stosd lodsw cwde stosd lodsw cwde stosd lodsw cwde stosd lodsw cwde stosd lodsw cwde stosd lodsw cwde stosd add esi,9 ; 3 ints after nine bytes lodsw cwde stosd lodsw cwde stosd lodsw cwde stosd sub esi,21 ; now do the nine bytes movsd movsd movsb endm ;============================================================================== ; repack BITMAP from 32-bit to 16-bit ; ;============================================================================== PACK_BITMAP_32_16 macro lodsd ; first 4 int widened stosw lodsd stosw lodsd stosw lodsd stosw add esi,4 ; 2 bytes moved to end movsw sub esi,6 movsd ; bmBits endm ;============================================================================== ; entry code for flat common callback ; ;============================================================================== CALLBACK_PROLOGUE macro pop eax ; 16:16 callback pop edx ; eip, API32 push cs ; flat cs push edx ; eip, API32 push eax ; 16:16 callback push ebp mov ebp,esp push ds ; save registers push es push ebx push edi push esi endm ;============================================================================== ; exit code for flat common callback ; ;============================================================================== CALLBACK_EPILOGUE macro size LOCAL bad_esp ;-------------------------------------------------- ; switch stacks and jump to 16:16 callback ; when the 16:16 callback does a retf, we will hit our cleanup routine push dword ptr ADDR_THK_CLEANUP_&size ; prepare to transfer to the 16-bit callback function push pCallback16 ; get the ss16 we had when we entered the callback API16 ; make the 16-bit ss:sp point to the same linear address as the flat ss:esp call UsrQuerySS16 mov esi,eax ; save ss16 push eax call GetSelectorBase32 ; LATER: LDT lookup xchg eax,esp sub eax,esp jb bad_esp cmp eax,65535 ja bad_esp mov ss,si mov sp,ax ; effectively, jmp to 16:16 callback retw bad_esp: int 3 endm ;============================================================================== ; 16-bit callback cleanup code ; ;============================================================================== CALLBACK_CLEANUP macro size pop si ; get hMem pop di mov cx,si or cx,di jz @F push di ; hMem !NULL, so dealloc push si call LocalFree @@: call UnmapLS ; thunk id already on stack add sp,2 ; flat setup pushed dword movzx ecx,sp ; restore flat stack lss esp,ss:[ecx] pop esi ; restore registers pop edi pop ebx POPD es POPD ds pop ebp pop ecx ; discard 16:16 callback retd size ; return to the 32-bit API endm ;============================================================================== ; save flat stack and thunkID ; ;============================================================================== SAVE_STACK_AND_THUNKID macro lea eax,[addr_registers] ; save flat stack push ss push eax call GetThunkID32 push eax ; save 16:16 thunkID endm ;============================================================================== ; entry code for 16-bit common callback to 32-bit function ; ;============================================================================== CALLBACK_BODY_16 macro name, size, aliases local callback_ret CB16_&name label far16 for x, CB16_&x label far16 endm push bp push si push di push ds mov ax,sp push ss push ax mov ax,sp push ss push ax call SelectorOffsetToLinear16 mov ebx,eax and eax,not 3 mov cx,cs:FlatData mov ss,cx mov esp,eax mov ds,cx mov es,cx push cs push offset callback_ret jmp f32ptr ptr pfn&name&Callback callback_ret: lss sp,ss:[ebx] pop ds pop di pop si pop bp retf size ; return to the 16-bit API endm