
; *** TESTDRUG.ASM ***

; Ultimate COMDLG32.DLL test tool (Win32 GUI executable)
; (C) Copyright 2011-11-15 by DOS386 | Freeware | USE AT YOUR OWN RISK !!!
; Compile with FASM -> TESTDRUG.EXE (2.5 KiB)

; System requirements:
; - At least 80386 CPU
; - A few MiB RAM (more for Windaube)
; - DOS and HX , or Windaube (ME 8 95 2000 Wi$ta NT 98 XP 7 XXX-32 or XXX-64)

; WARNING: This tool does one arguably exotic task very well !!!!!!!!!!!!!!!!

; "http://board.flatassembler.net/topic.php?t=11170"

; ----------------------------------------------------------------------

; ASS'ume: really nothing AKA BUGGER all ;-D

; ----------------------------------------------------------------------

define pope  pop
define popef popf

macro movntq mdst, msrc {
  if mdst in <eax,ebx,ecx,edx,esi,edi,ebp,ax,bx,cx,dx,si,di,bp> & msrc eq 0
    xor  mdst, mdst
  else
    mov  mdst, msrc
  end if
} ; endmacro

macro cmpntq minp, mref {
  if minp in <bl,cl,dl,ah,bh,ch,dh,ax,bx,cx,dx,si,di,bp,\
              eax,ebx,ecx,edx,esi,edi,ebp> & mref eq 0
    test minp, minp
  else
    cmp  minp, mref
  end if
} ; endmacro

; ----------------------------------------------------------------------

format binary as "EXE"
use32
org 0

; ----------------------------------------------------------------------

ccbase     = $0040'0000   ; 4 Mi for EXE
; ccbase     = $1000'0000   ; 1 Gi for DLL
ccstartrva = $1000        ; 4 Ki (increase if you have a big MZ stub !!!)

; ----------------------------------------------------------------------

; *** MZ-Header, stub (0,$60) ***

ccstacktop = $1040 ; MZ header $20 ; Program $0040 ; Heap 0 ; Stack $1000

  db "MZ"          ; Mark's Sigi
  dw $60           ; Bytes in last block (0 is full, includes header size)
  dw 1             ; Blocks per 512 Bytes (includes header size)
  db 0,0           ; No relox
  db 2,0           ; Header size
  dw $1000         ; Min (Heap + Stack) 4 KiB
  dw $1000         ; Max (Heap + Stack) 4 KiB
  dw 0             ; Stack segment: SS=CS !!!
  dw ccstacktop    ; Stack size (almost 4 KiB) / pointer in bytes !!!
  db 0,0,0,0,0,0   ; CHK, IP, CS
  dw $1C           ; Useless relox offset
  db 0,0           ; Useless "overlay"
  db 0,0,0,0       ; Padding / empty relox

; org = $20 , should be 0 but irrelevant :-D

  db $0E,$1F         ; PUSH CS   | POPE DS
  db $B4,9,$BA,$20,0 ; MOV AH, 9 | MOV DX, $0020
  db $CD,$21         ; INT $21
  db $B8,1,$4C       ; MOV AX, $4C01
  db $CD,$21         ; INT $21
  db 0,0             ; Wasting 2 bytes

; org = $30

  db 0,0,0,0,0,0,0,0,0,0,0,0   ; Wasting 12 bytes
  db $60,0,0,0                 ; PE begins here

; org = $40, should be $20

  db "Need HX-DOS Extender to run !",$0D,$0A,$24  ; 29 chars + 3 special

if ($<>$60)
  err "corrupt stub"
end if

; org = $60, content moved by +$20 bytes

; *** PE-Header ($60,$18) ***

db "PE", 0, 0 ; Signature

dw $014C      ; CPU: 80386 or compatible (nobody seems use 80486 or Pentium)
dw 1          ; Number of sections
dd 0          ; Useless "timestamp" :-(
dd 0, 0       ; Useless "symbols" :-(
dw $00E0      ; Size of Optional header (const ???)
dw $010F      ; Characteristics : "image", 32-bit, low junk, relox OFF
; dw $010E      ; Characteristics : "image", 32-bit, low junk, relox ON
; dw $210E      ; Characteristics : "image", 32-bit, low junk, relox ON, DLL

; *** The "portable" Optional header ($78,$1C) ***

dw $010B              ; Great "magic" for PE (PE32)
dw 0                  ; Useless "linker version" :-(
dd 0, 0, 0            ; Useless .code/.idata/.data sizes :-(
dd (llentry - ccbase) ; Entry point RVA
dd 0, 0               ; Useless .code/.data offsets :-(

; *** NT-specific Optional header extension ($94,$44) ***

dd ccbase         ; Base address
dd $1000, $0200   ; Section alignment in memory and file: 4 KiB / 512 B
dd 1              ; OS version ( "NT 1.0" !!!??? )
dd 0              ; Image version
dd 4              ; Great "subsystem" version
dd 0              ; Reserved

dd ((llveryend - ccbase + $0FFF) shr 12) shl 12 ; Image size
; Total size from base to end of sections, all aligned to $1000
; This includes all headers and stub !!!

dd $0200    ; Header size (MS-DOG + PE + Optional + Sectional), section offset
dd 0        ; Useless "checksum" :-(
dw 2        ; Critical: "subsystem": 2:GUI 3:Console (but for a DLL ... ???)
dw 0        ; Useless DLL stuff (???)

dd $C000, $C000, $C000, 0   ; Bloat: stack/heap reserve/commit (HX shooting)
; dd 0, 0, 0, 0               ; Bloat: ignored for a DLL ;-)
dd 0                        ; Obsolete/reserved :-(
dd 16         ; "directories" : 16 entries per 8 bytes : 128 = $80 bytes

; *** Directories ($D8,$80) ***

dq 0 ; dd (llexpbeg - ccbase), xxexpsize   ; Useful exports  ;-)
dd (llimpbeg - ccbase), xximpsize   ; Useful imports  ;-)
dq 3 dup(0)                         ; 3 empty entries :-D
dq 0 ; dd (llrelbeg - ccbase), 8           ; 8 Bytes of empty PE-relox if PIC
dq 10 dup(0)                        ; 10 empty entries :-D

; *** Sectional header ($158,$28) ***

db ".myvirus"             ; Section name, 8 Byte's, but nobody cares about it

dd (llveryend - llverybeg)  ; Exact section size
dd ccstartrva               ; Our "rva" of section begin
dd (llpadend - llverybeg)   ; Size rounded up to $0200 file alignment

dd $0200, 0, 0, 0   ; File offset, no COFF-specific relox/linenumber crap

; dd $E000'0020       ; Attr: b31 writable, b30 readable, b29 & b5 executable
dd $6000'0020       ; Attr: b30 readable, b29 & b5 executable

; *** Header padding ($180,$80) ***

db ($0200-$) dup(0)           ; Proceed to $0200/$1000
org (ccbase + ccstartrva)

; ----------------------------------------------------------------------

; ######## Our main section begins here ########

; ----------------------------------------------------------------------

virtual at ebp
  bbbuf256a:   rb 256 ; 256 | As recommend by M$ for "ofn" | Also other use
  bbbuf256b:   rb 256 ; 512 | "ofn" struct (76) and string bunching
  bbgetstring: rb 80  ; 592 | 39 char's max + TER-ZERO | "getstring" and UNI
  vvmodhan:    dd ?   ; 596 | UINT32
  vvstrcou:    db ?   ; 597 | UINT8
  vvunicrap:   db ?   ; 598 | UINT8
  vvmustex:    db ?   ; 599 | UINT8
  xxx:         db ?   ; 600
end virtual

; ----------------------------------------------------------------------

llverybeg:
llentry:

        cld
        sub    esp, 640
        mov    ebp, esp           ; 640 Byte's buffer at EBP

        mov    al, 1
        call   ssgetstring        ; "Welcome !!!"
        xchg   ecx, eax           ; ECX <- EAX
        call   ssmbok

        mov    al, 3
        call   ssgetstring        ; "VMM32.VXD"
        call   sstestlilo

        mov    al, 4
        call   ssgetstring        ; "SHELL32.DLL"
        call   sstestlilo

        mov    al, 5
        call   ssgetstring        ; "COMDLG32.DLL"
        call   sstestlilo
        cmpntq eax, 0
        je     no_dealer_ggg      ; NO short :-(
        mov    [vvmodhan], eax    ; Store module handle

        ; ------------------------------

        mov    al, 6
        call   ssgetstringcopy    ; "CommDlgBuggerAll"
        call   sstestgpra

        ; ------------------------------

        mov    al, 7
        call   ssgetstringcopy    ; "CommDlgExtendedError"
        call   sstestgpra

        ; ------------------------------

        mov    al, 8
        call   ssgetstringcopedi      ; "GetFileTitle"
        call   ssstosaa
        call   ssstoszero
        call   sstestgpra             ; "GetFileTitleA"
        cmpntq eax, 0
        je     no_title_a             ; FWD far | NO short :-(

        xchg   ebx, eax               ; EBX <- EAX | Proc address
        mov    [vvstrcou], byte 12    ; String counter

        lea    edi, [bbbuf256b]
        push   edi
        mov    al, 29
        call   ssgetstringcoany       ; "Do you want to test"
        call   ssstos32
        call   ssstos34
        mov    al, 8
        call   ssgetstringcoany       ; "GetFileTitle"
        call   ssstosaa               ; "A"
        call   ssstos34
        call   ssstos32
        mov    al, 63
        stosb
        call   ssstoszero
        pope   ecx
        call   ssmbyesno              ; 6 YES | 7 NO
        shr    al, 1
        jc     no_title_a             ; FWD far | NO short :-(

title_loop_insane:
        lea    edi, [bbbuf256b+3]       ; Reserve space for "Rejected"
        mov    al, 34
        call   ssgetstringcoany         ; "Input : "
        mov    al, [vvstrcou]
        call   ssgetstring              ; ??? Garbage string
        push   eax
        call   sslenquotcopyquotlenter  ; In is EAX !!!
        lea    ecx, [bbbuf256b+3]       ; Reserve space for "Rejected"
        call   ssmbok
        pope   eax
        mov    ch, [vvstrcou]
        mov    cl, 240
        cmp    ch, 14
        jne    short @f
        mov    cl, 3              ; Make buffer just fit | 2+1 !!!
@@:     cmp    ch, 15
        jne    short @f
        mov    cl, 2              ; Make buffer too small :-D
@@:     and    ecx, $FF
        push   ecx                ; Size dst
        lea    ecx, [bbbuf256a]   ; No +3 here !!!
        push   ecx                ; Buffer dst
        push   eax                ; For the call - src string
        call   ebx                ; !!! HOT !!! | Output ZERO is OK
        cmpntq eax, 0
        je     short title_ok
        lea    edi, [bbbuf256b]
        push   edi
        mov    al, 36
        call   ssgetstringcoany   ; "Rejected"
        pope   ecx
        call   ssmbevil
        jmp    short title_joint
        ;-----------------------

title_ok:
        mov    [bbbuf256a+240], byte 0  ; !!!
        lea    edi, [bbbuf256b]
        push   edi
        mov    al, 35
        call   ssgetstringcoany         ; "Output : "
        lea    eax, [bbbuf256a]
        call   sslenquotcopyquotlenter  ; In is EAX !!!
        pope   ecx
        call   ssmbok

title_joint:
        mov    al, [vvstrcou]
        inc    eax
        mov    [vvstrcou], al
        cmp    al, 29
        jne    title_loop_insane        ; BCK far | NO short :-(

no_title_a:

        ; ------------------------------

        mov    al, 8
        call   ssgetstringcopedi  ; "GetFileTitle"
        call   ssstosww
        call   ssstoszero
        call   sstestgpra         ; "GetFileTitleW"

        ; ------------------------------

        mov    al, 9
        call   ssgetstringcopedi  ; "GetOpenFileName"
        call   ssstosaa
        call   ssstoszero
        call   sstestgpra         ; "GetOpenFileNameA"
        cmpntq eax, 0
        je     short @f
        mov    [vvunicrap], byte 0
        mov    [vvmustex], byte 1
        call   ssofntest
@@:

        ; ------------------------------

        mov    al, 9
        call   ssgetstringcopedi  ; "GetOpenFileName"
        call   ssstosww
        call   ssstoszero
        call   sstestgpra         ; "GetOpenFileNameW"
        cmpntq eax, 0
        je     short @f
        mov    [vvunicrap], byte 1
        mov    [vvmustex], byte 1
        call   ssofntest
@@:

        ; ------------------------------

        mov    al, 10
        call   ssgetstringcopedi  ; "GetSaveFileName"
        call   ssstosaa
        call   ssstoszero
        call   sstestgpra         ; "GetSaveFileNameA"
        cmpntq eax, 0
        je     short @f
        mov    [vvunicrap], byte 0
        mov    [vvmustex], byte 0
        call   ssofntest
@@:

        ; ------------------------------

        mov    al, 10
        call   ssgetstringcopedi  ; "GetSaveFileName"
        call   ssstosww
        call   ssstoszero
        call   sstestgpra         ; "GetSaveFileNameW"
        cmpntq eax, 0
        je     short @f
        mov    [vvunicrap], byte 1
        mov    [vvmustex], byte 0
        call   ssofntest
@@:

        ; ------------------------------

        mov    al, 11
        call   ssgetstringcopedi  ; "PrintDlg"
        call   ssstosaa
        call   ssstoszero
        call   sstestgpra         ; "PrintDlgA"

        ; ------------------------------

        mov    al, 11
        call   ssgetstringcopedi  ; "PrintDlg"
        call   ssstosww
        call   ssstoszero
        call   sstestgpra         ; "PrintDlgW"

        ; ------------------------------

no_dealer_ggg:

        mov    al, 2
        call   ssgetstringcopy    ; "EOF !!!"
        xchg   ecx, eax
        call   ssmbok

        pushd  0
        call   dword [ExitProcess]
        ;-------------------------

; ----------------------------------------------------------------------

; ######## High level SUB's ########

; ----------------------------------------------------------------------

; SUB SSOFNTEST | IN EAX proc address , "vvunicrap" , "vvmustex"
; Trash EBX ESI EDI

ssofntest:

        xchg   ebx, eax       ; Proc address
        call   ssclearsetofn  ; Sets EDI | Uses "vvunicrap" and "vvmustex"
        push   edi            ; For the call address of "ofn"
        call   ebx            ; !!! HOT !!! | Output non-ZERO is OK
        cmpntq eax, 0
        je     short ofn_miserably_failed

        lea    edi, [bbbuf256b]   ; Out string from "ofn"
        movntq eax, 0
        mov    [edi+240], eax     ; !!!

        cmp    [vvunicrap], al
        je     short no_uni_shrinx

        movntq ecx, 0
@@:     mov    al, [edi+2*ecx]
        mov    [edi+ecx], al
        inc    ecx
        cmp    al, 0
        jne    short @b

no_uni_shrinx:
        lea    edi, [bbbuf256a]
        push   edi
        mov    al, 35
        call   ssgetstringcoany         ; "Output : "
        lea    eax, [bbbuf256b]
        call   sslenquotcopyquotlenter  ; In is EAX !!!
        pope   ecx
        call   ssmbok

        jmp    short ofn_joint
        ;---------------------

ofn_miserably_failed:
        call   ssmbfailure

ofn_joint:
        ret
        ;----

; SUB SSTESTLILO | IN EAX string | OUT EAX mh or ZERO
; Trash ECX , EDX , "bbbuf256a" , "bbgetstring"

sstestlilo:

        push   esi
        push   edi

        push   eax                ; String | Later POPE into ESI
        push   eax                ; String for call
        call   dword [LILO]
        pope   esi                ; String
        call   ssreporttest       ; Trash EDX ESI EDI "bbbuf256a"

        pope   edi
        pope   esi
        ret
        ;----

; SUB SSTESTGPRA | IN EAX string , "vvmodhan" | OUT EAX (address or ZERO)
; Trash ECX , EDX , "bbbuf256a" , "bbgetstring"

sstestgpra:

        push   esi
        push   edi

        push   eax                ; String | Later POPE into ESI
        push   eax                ; String for call
        push   dword [vvmodhan]   ; Module handle
        call   dword [GPRA]
        pope   esi                ; String
        call   ssreporttest       ; Trash EDX ESI EDI "bbbuf256a"

        pope   edi
        pope   esi
        ret
        ;----

; SUB SSREPORTTEST | IN EAX (address or ZERO) , ESI string
; Trash ECX , EDX , ESI , ESI , "bbbuf256a" , "bbgetstring"

ssreporttest:

        xchg   edx, eax       ; Save (address or ZERO) into EDX
        lea    edi, [bbbuf256a]
        push   edi
        call   ssstos34
        call   sscopyzstringz ; Updates ESI EDI | Does NOT set ZERO
        call   ssstos34
        call   ssstos32
        mov    al, 32         ; "is available"
        cmpntq edx, 0         ; Return value
        jne    short @f       ; GOOD
        inc    eax            ; "NOT"
@@:     call   ssgetstringcoany
        call   ssstoszero
        pope   ecx
        cmpntq edx, 0
        jne    short @f       ; GOOD
        call   ssmbevil
        jmp    short join_lilo
        ;---------------------
@@:     call   ssmbok
join_lilo:
        xchg   eax, edx       ; Return (address or ZERO) back into EAX
        ret
        ;----

; SUB SSCLEARSETOFN | IN "vvunicrap" "vvmustex" | OUT EDI
; Trash EAX , ECX , EDI
; Trash "bbgetstring" , "bbbuf256a" (struct) , "bbbuf256b"  (out string)

; The horrible thing eats 4 strings as input :
; - Title (may be empty but we do set it)
; - Preselected filename (may be empty, and we leave it empty)
; - 2 strings about the filter (may be empty ??? we do set it)

ssclearsetofn:

        movntq eax, 0
        movntq ecx, 0
        mov    cl, 128
        lea    edi, [bbbuf256a]   ; Clear "bbbuf256a" and "bbbuf256b"
        push   edi
        rep    stosd
        pope   edi

if ((bbbuf256a+256-bbbuf256b)<>0)
  err "(bbbuf256a+256)<>bbbuf256b"
end if

        mov    al, 30             ; "All silly files *.*  Testing" (28)
        call   ssgetstringcopy

        mov    cl, 0
        mov    [eax+15], cl
        mov    [eax+19], cl
        mov    [eax+20], cl
        mov    ch, 65             ; "A"
        cmp    [vvunicrap], byte 0
        je     short @f
        add    ch, 22             ; "A" -> "W"
@@:     mov    [eax+28], ch
        mov    [eax+29], cl       ; TER-ZERO

        cmp    [vvunicrap], byte 0
        je     short no_uni_expand

        push   edx
        movntq edx, 0             ; Value transfer
        movntq ecx, 0             ; Index
        mov    cl, 29
@@:     mov    dl, [eax+ecx]
        mov    [eax+2*ecx], dx
        dec    ecx
        jns    short @b
        pope   edx

no_uni_expand:

        mov    [edi], byte 76     ; "lStructSize" | Needed ???

        mov    [edi+12], eax      ; Filter | 2 str's | 21 char's incl. ZERO's

        lea    ecx, [bbbuf256b]   ; It's empty on entry ;-)
        mov    [edi+28], ecx      ; In and out buffer | 256 Byte's

        lea    ecx, [eax+21]      ; Last use of EAX address
        mov    al, 252            ; Buffer size limit
        cmp    [vvunicrap], byte 0
        je     short @f
        add    ecx, 21            ; Move up string address in Byte's
        mov    al, 126            ; DIV amount of char's fitting into buffer
@@:     mov    [edi+32], al       ; "nMaxFile"
        mov    [edi+48], ecx      ; "lpstrTitle"

        mov    eax, $1212'0004    ; Add $1000 for load (must exist)
        cmp    [vvmustex], byte 0
        je     short @f
        add    ah, 16             ; ADDNTQ EAX, $1000
@@:     mov    [edi+52], eax      ; "Flags"

        ret
        ;----

; SUB SSMBFAILURE | Trash EAX , ECX

ssmbfailure:

        mov    al, 31
        call   ssgetstring    ; "Failure (F**K!!!) :-("
        xchg   ecx, eax
        ; and pass

; SUB SSMBEVIL | IN ECX string | Trash EAX , ECX | Preserve EDX

ssmbevil:

        push   edx
        mov    edx, $10       ; & Total: Err + OK
        jmp    short ssmbdo
        ;------------------

; SUB SSMBOK | IN ECX string | Trash EAX , ECX | Preserve EDX

ssmbok:

        push   edx
        mov    edx, $30       ; & Total: Excl + OK
        jmp    short ssmbdo
        ;------------------

; SUB SSMBYESNO | IN ECX string | Trash ECX | Preserve EDX
; OUT EAX YES=6 NO=7

ssmbyesno:

        push   edx
        mov    edx, $24       ; & Total: Quest + Y/N
        ; and pass

; SUB SSMBDO

ssmbdo:
        mov    al, 0          ; "(C) 2011-" ...
        call   ssgetstring    ; Preserves ECX and EDX
        push   edx            ; MB type flags
        push   eax            ; & Icon: 0 none | $10 Err | $20 Quest | $30 Excl
        push   ecx            ; & Buttons: 0 OK | 4 Y/N
        pushd  0              ; ZERO ???
        call   dword [MessageBoxA]    ; NO JMP !!!
        pope   edx
        ret
        ;----

; SUB SSLENQUOTCOPYQUOTLENTER | IN EAX source , EDI dest
; Trash ESI , EDI , EAX
; Finds out length, quote-copies string and appends length to dest

sslenquotcopyquotlenter:

        mov    esi, eax           ; Now BOTH ESI and EAX hold the address
        call   ssstringlen        ; Sets new EAX | ESI preserved
        push   eax                ; Length
        call   ssstos34
        call   sscopyzstringz     ; Updates ESI EDI | Does NOT set ZERO
        call   ssstos34
        call   ssstos32
        pope   eax
        call   ssaltodecbra       ; Uses EAX | Trash EAX , ECX , EDI
        jmp    ssstoszero
        ;----------------

; ----------------------------------------------------------------------

; ######## Special SUB's ########

; ----------------------------------------------------------------------

; SUB SSGETSTRINGCOPY | IN AL | OUT EAX (begin od string, const)
; All other registers preserved !!!
; Trash "bbgetstring" !!!
; Drops string into "bbgetstring" and sets TER-ZERO too

ssgetstringcopy:

        push   edi
        call   ssgetstringcopedi
        call   ssstoszero
        pope   edi
        ret
        ;----

; SUB SSGETSTRINGCOPEDI | IN AL | OUT EAX (begin od string, const) , EDI
; All other registers preserved !!!
; Trash "bbgetstring" !!!
; Drops string into "bbgetstring" and DOESN'T set TER-ZERO
; EDI end of string

ssgetstringcopedi:

        lea    edi, [bbgetstring]
        call   ssgetstringcoany
        ret
        ;----

; SUB SSGETSTRINGCOANY | IN AL | OUT EAX | All other registers preserved !!!
; Drops string at EDI and DOESN'T set TER-ZERO
; Doesn't touch "bbgetstring"
; EDI updated, EAX holds original EAX value

ssgetstringcoany:

        push   esi
        call   ssgetstring
        xchg   esi, eax       ; ESI <- EAX
        push   edi
        call   sscopyzstringz ; Updates ESI EDI | Does NOT set ZERO
        pope   eax
        pope   esi
        ret
        ;----

; SUB SSGETSTRING | IN AL | OUT EAX | All other preserved !!!

ssgetstring:

        push   esi
        call   @f

        db "(C) 2011-11-15 | All rights reserved", 0          ; 0
        db "Ultimate COMDLG32.DLL test tool | Welcome !!!", 0 ; 1
        db "EOF !!!", 0                                       ; 2

        db "VMM32.VXD", 0             ; 3
        db "SHELL32.DLL", 0           ; 4
        db "COMDLG32.DLL", 0          ; 5

        db "CommDlgBuggerAll", 0      ; 6
        db "CommDlgExtendedError", 0  ; 7
        db "GetFileTitle", 0          ; 8
        db "GetOpenFileName", 0       ; 9
        db "GetSaveFileName", 0       ; 10
        db "PrintDlg", 0              ; 11

        db "DGJPP.EXE", 0                             ; 12
        db "XX.BAT", 0                                ; 13
        db "QQ", 0                                    ; 14
        db "QQ", 0                                    ; 15 | !! deli. dupe !!
        db "Q", 0                                     ; 16
        db "C:\YO.SYS", 0                             ; 17
        db "C:/YO.SYS", 0                             ; 18
        db "M:\XXX\YYY\ZZZ\NTVDM:NONTVDM.LNK", 0      ; 19
        db "C:\WINDAUBE/SYSTEM128\VMM128.VXD", 0      ; 20
        db "C:\WINDAUBE///SYSTEM128\\\VMM128.VXD", 0  ; 21
        db "XXX:WINDAUBE///SYSTEM128\\\VMM128.VXD", 0 ; 22
        db "\\//:WINDAUBE:SYSTEM8/VMM8.VXD", 0        ; 23
        db "http://www.xxx.com", 0                    ; 24
        db "F:TEST", 0                                ; 25
        db "f:test", 0                                ; 26
        db "f:TesT", 0                                ; 27
        db "\blah.tar.lzma.b64", 0                    ; 28

        db "Do you want to test", 0                   ; 29
        db "All silly files *.*  Testing", 0          ; 30 | FIXED LENGTHS !!!
        db "Failure (F**K!!!) :-(", 0                 ; 31
        db "is available", 0                          ; 32
        db "is NOT available", 0                      ; 33
        db "Input : ", 0                              ; 34 | FIXED LENGTHS !!!
        db "Output : ", 0                             ; 35 | FIXED LENGTHS !!!
        db "Rejected", 0                              ; 36 | FIXED LENGTHS !!!

@@:     pope   esi
        mov    ah, al         ; Index

st_sea_loop:
        cmpntq ah, 0
        je     short we_got_him
@@:     lodsb
        cmp    al, 0
        jne    short @b
        dec    ah
        jmp    short st_sea_loop
        ;-----------------------

we_got_him:
        xchg   eax, esi       ; EAX <- ESI
        pope   esi
        ret
        ;----

; ----------------------------------------------------------------------

; ######## Low level SUB's ########

; ----------------------------------------------------------------------

; SUB SSALTODECBRA | IN AL , EDI | OUT mem | Trash EAX , ECX , EDI

ssaltodecbra:

        and    eax, 255
        push   eax
        mov    al, 40         ; "("
        stosb
        pope   eax
        mov    cl, 10
        div    cl             ; DIV AX by CL | QUO AL REM AH
        push   eax
        mov    ah, 0
        div    cl             ; DIV AX by CL | QUO AL REM AH
        push   eax
        mov    ah, 0
        div    cl             ; DIV AX by CL | QUO AL REM AH
        add    ah, 48
        mov    al, ah
        stosb
        pope   eax
        add    ah, 48
        mov    al, ah
        stosb
        pope   eax
        add    ah, 48
        mov    al, ah
        stosb
        mov    al, 41         ; ")"
        stosb
        ret
        ;----

; SUB SSSTRINGLEN | IN EAX | OUT AL

ssstringlen:
        push   esi
        movntq eax, 0
@@:     lodsb
        cmp    al, 0
        je     short len_done_zzz
        inc    ah
        jnz    short @b       ; Give up at 256

len_done_zzz:
        shr    eax, 8
        pope   esi
        ret
        ;----

; SUB SSCOPYZSTRINGZ | !!! NOT FOOL-PROOF !!! | Trash EAX , ESI , EDI
; DOESN'T set TER-ZERO in dest

sscopyzstringz:

        lodsb
        cmp    al, 0
        je     short copy_done_zzz
        stosb
        jmp    short sscopyzstringz
        ;--------------------------

copy_done_zzz:
        ret
        ;----

; SUB's on STOS

ssstoszero:
        push   eax
        mov    al, 0
        stosb
        pope   eax
        ret
        ;----

ssstos32:
        push   eax
        mov    al, 32
        stosb
        pope   eax
        ret
        ;----

ssstos34:
        push   eax
        mov    al, 34
        stosb
        pope   eax
        ret
        ;----

ssstosaa:
        push   eax
        mov    al, 65
        stosb
        pope   eax
        ret
        ;----

ssstosww:
        push   eax
        mov    al, 87
        stosb
        pope   eax
        ret
        ;----

; ----------------------------------------------------------------------

if ( ($ mod 4) > 0 )
  db ( (3) - ($+3) mod 4 ) dup (0)
  ; Align to 4 // this ^^^ line fails if already aligned
end if

; ----------------------------------------------------------------------

; ######## Import block just follows, no private section ########

; ----------------------------------------------------------------------

; There must be a 20 Byte's long import descriptor for every DLL
; and an empty one as termination

llimpbeg:

dd 0, 0, 0, (dgjpp_kernel_name-ccbase), (dgjpp_kernel_table-ccbase)
dd 0, 0, 0, (dgjpp_user32_name-ccbase), (dgjpp_user32_table-ccbase)
dd 0, 0, 0, 0, 0

; There must be a table for every DLL and every table must have
; an UINT32 ZERO as termination

dgjpp_kernel_table:

ExitProcess: dd (_ExitProcess-ccbase)
LILO:        dd (_LILO-ccbase)
GPRA:        dd (_GPRA-ccbase)
dd 0

dgjpp_user32_table:

MessageBoxA: dd (_MessageBoxA-ccbase)
dd 0

; Now we get missaligned ;-)

; There is no obligation to sort import names, but there must be
; an additional UINT16 "ordinal hint" value (hint: ZERO is safe
; to use) preceding every piece. Export names MUST be sorted,
; as spec requires this, and otherwise risk that some name will not
; get found despite it is in there. Both export and import function
; names must be ZERO-terminated, as well as the DLL file names.

dgjpp_kernel_name: db "KERNEL32.DLL", 0
dgjpp_user32_name: db "USER32.DLL"      ; ZERO is below

_ExitProcess: db 0, 0, "ExitProcess"    ; ZERO is below
_GPRA:        db 0, 0, "GetProcAddress" ; ZERO is below
_LILO:        db 0, 0, "LoadLibraryA"   ; ZERO is below

_MessageBoxA: db 0, 0, "MessageBoxA", 0

xximpsize = ($ - llimpbeg)

db "Wow64", 0, "NTVDM.EXE", 0, "LSASS.EXE", 0, "IsdeBUGGERpresent", 0

llveryend:

; ----------------------------------------------------------------------

if ( ($ mod $0200) > 0 )
  db ( ($01FF) - ($+$01FF) mod $0200 ) dup (0)
  ; Align to $0200 // this ^^^ line fails if already aligned
end if

llpadend:

; ----------------------------------------------------------------------

; END.


