Category : Files from Magazines
Archive   : DDJ9404B.ZIP
Filename : LISTINST.ASM

 
Output of file : LISTINST.ASM contained in archive : DDJ9404B.ZIP
;ListInst.ASM
;from Dr. Dobbs Journal,April 1994
;Copyright (c) 1994 Klaus Mueller. All rights reserved.

OPTION M510

.386p

INCLUDE VMM.INC
INCLUDE INT2FAPI.INC
INCLUDE WIN386.INC
Create_ListInst_Service_Table EQU 1 ;service table created
INCLUDE LISTINST.INC

;*****************************************************************************
; V I R T U A L D E V I C E D E C L A R A T I O N
;*****************************************************************************

Declare_Virtual_Device ListInst, 1, 0, ListInst_VxD_Control, \
ListInst_Device_ID,ListInst_Init_Order, \
ListInst_V86_API


;*****************************************************************************
; R E A L M O D E I N I T I A L I Z A T I O N
;*****************************************************************************

VXD_REAL_INIT_SEG

real_init proc near
push edx
mov ah, 9
mov dx, offset copyright
int 21h
xor ax, ax
xor bx, bx
xor si, si
pop edx
ret
real_init endp

copyright db 'ListInst.386 -- provides structures of the Instance Data'
db ' Manager.',0dh,0ah

db 'Copyright (c) 1994 Klaus Mueller. All Rights Reserved.'
db 0dh,0ah,'$'

VXD_REAL_INIT_ENDS

VxD_ICODE_SEG


BeginProc ListInst_Sys_Critical_Init

;int 3
movzx eax,dx ;real mode offset of ref data from
and edx,0ffff0000h ;VxDLoad TSR
shr edx,0ch ;segment
add edx,eax ;linear address
mov w386_sis_tbl,edx
mov Data_Buf_Size,1000h
;allocate 1 page for the InstDataStrucs from the hooked _AddInstanceItem call
VMMcall _PageAllocate <1, PG_SYS, 0, 0, 0, 0, 0, PAGEFIXED+PAGEZEROINIT>
cmp eax,0
je allocerr
mov Data_Buf_Handle,eax
mov Data_Buf_Addr,edx
int 3

;Instancing of the first byte in the 1st MB in order to get all calls to
;_AddInstanceItem befor ListInst_Sys_Critical_Init. The _AddInstanceItem
;service chains the InstDataStrucs together to a sorted double linked list
;via InstLinkF and instLinkB.
;If the LinkF field is -1, no other calls were made.
;If LinkF <> -1, then it represents a call to _AddInstanceItem caused by an
;system.ini - entry "LOCALTSRS= tsr_name". The VMM instances the hole TSR,
;the first 16 Byte represents the MCB of the PSP. So we can determine the name
;of the fully instanced TSR.

mov KM_Instance.InstLinAddr,0
mov KM_Instance.InstSize,1
mov KM_Instance.InstType,ALWAYS_FIELD
mov esi,offset32 KM_Instance
VMMcall _AddInstanceItem
cmp KM_Instance.InstLinkF,-1 ;any LOCALTSRS ?
je nolocal
mov esi,KM_Instance.InstLinkF ;yes, get it
loclp: mov Inst_Struc_Ptr,esi
mov calladr,'LTSR'
call addinst ;add instance item to our list
mov esi,[esi.InstDataStruc.InstLinkF] ;get next InstDataStruc
cmp esi,-1 ;no more strucs?
jne loclp
nolocal:mov eax,_AddInstanceItem
mov esi,offset32 myhook
VMMcall Hook_Device_Service
mov [oldservice],esi
;int 3 ;uncomment this for debug
clc ;no error
ret
allocerr:
stc
ret
EndProc ListInst_Sys_Critical_Init



VxD_ICODE_ENDS

;*****************************************************************************
; L O C K E D C O D E S E G M E N T
;*****************************************************************************

VxD_LOCKED_CODE_SEG

BeginProc ListInst_VxD_Control

Control_Dispatch Sys_Critical_Init, ListInst_Sys_Critical_Init
; Control_Dispatch Init_Complete, ListInst_Init_Complete
clc
ret

EndProc ListInst_VxD_Control

VxD_LOCKED_CODE_ENDS

;*****************************************************************************
; O N L Y D A T A S E G M E N T
;*****************************************************************************

VxD_DATA_SEG

w386_sis_tbl dd 0
oldservice dd 0
count dd 0
ddbpointer dd 0
Inst_Struc_Ptr dd 0
calladr dd 0
init_done dd 0
Inst_Data_Count dd 0
inst_count dd 0
desc_count dd 0
VMCB_PG_Table dd 0
SYS_PG_Table dd 0
win4_flag dd 0
w4_pres_count dd 0
w4_npres_count dd 0
w4_cur_handle dd 0
Inst_Desc_Buf dd 0
Inst_Buf_Handle dd 0
Inst_Buf_Size dd 0
bit_array dd 0
Data_Buf_Handle dd 0
Data_Buf_Addr dd 0
Data_Buf_Size dd 0
hook_err dd 0
string_buf dd 0
string_buf_handle dd 0
string_buf_size dd 0
int_2f_string db 'VMM:Create_Int_2F_Inst_Tbl: ',0
localtsr_string db 'VMM:Instance_LOCALTSRS : ',0
dos_sys_string db 'SYS DRV '
nostring db '????'
cur_inst dd 0

KM_Instance InstDataStruc {}

VxD_DATA_ENDS

VxD_CODE_SEG

BeginProc Hooked_AddInstanceItem
;The AddInstanceItem Hook stores the callers address and the instance data
;pointer in the Inst_Data_Buf buffer.
myhook:
;int 3 ;uncomment this for debug
push ebp
mov ebp,esp
push [ebp+0ch] ;Flags
push [ebp+8] ;Instance Structure Pointer
push [ebp+8]
pop Inst_Struc_Ptr
push [ebp+4] ;Callers returnaddress
pop calladr
call [oldservice] ;call old handler
add esp,8
pop ebp
;int 3
cmp eax,0 ;error in AddInstanceItem ?
je exit
call addinst ;add Instance Item to our list
exit: ;int 3
ret

;*****************************************************************************
;addinst - adds a instance item to our list.
;INPUT: calladr - address of caller of _AddInstanceItem
; Inst_Struc_Ptr - address of InstDataStruc
;OUTPUT: hookerr = -1 - error growing Data_Buf
; hookerr = 0 - all O.K.
;*****************************************************************************

addinst:push edi
push esi
push ecx
push eax
hook2: mov edi,Data_Buf_Addr
mov ecx,Inst_Data_Count
imul ecx,sizeof KM_InstData
add edi,ecx
push edi
add edi,sizeof KM_InstData
mov ecx,Data_Buf_Addr
add ecx,Data_Buf_Size
cmp edi,ecx
pop edi
jl hook1
mov ecx,Data_Buf_Size
add ecx,1000h
shr ecx,0ch
mov edx,Data_Buf_Handle
VMMcall _PageReAllocate
cmp eax,0
je hookerr
add Data_Buf_Size,1000h
mov Data_Buf_Handle,eax
mov Data_Buf_Addr,edx
jmp hook2
hook1: mov eax,calladr ;save callers address in buffer
stosd
mov esi,Inst_Struc_Ptr
mov ecx,(sizeof InstDataStruc)/4
rep movsd ;save instance data struc
inc Inst_Data_Count
hookret:pop eax ;next offset pair
pop ecx
pop esi
pop edi
ret
hookerr:mov hook_err,-1
jmp hookret

EndProc Hooked_AddInstanceItem

BeginProc ListInst_Get_Instance_Desc_Buffer, Service

cmp Inst_Desc_Buf,0
jne getdes
call descr ;build Instance Description Buf
jc getderr ;error in decr buf build
getdes: mov esi,Inst_Desc_Buf ;return address of buffer
clc
getderr:ret

EndProc ListInst_Get_Instance_Desc_Buffer



BeginProc ListInst_V86_API
;int 3
cmp [ebp.Client_AX],Inst_Map
je instmap
cmp [ebp.Client_AX],Inst_Ownership
je instown
cmp [ebp.Client_AX],Desc_Buf_Size
je descsize
cmp [ebp.Client_AX],Inst_Map_Size
je mapsize
v86err: or [ebp.Client_FLAGS],1 ;set carry
ret
descsize:
call descr
jc v86err
mov eax,Inst_Buf_Size
Client_Ptr_Flat edi, DS, BX
stosd
ret
mapsize:mov eax,Inst_Data_Count ;# of inst strucs
imul eax, sizeof Inst_Hook_Struc
Client_Ptr_Flat edi, DS, BX
stosd
ret


;V86 API, determine instance page ownership

instown:;int 3
VMMcall Get_VMM_Version
cmp ah,3
je win3
cmp ah,4
je win4
or [ebp.Client_FLAGS],1
ret
win3: cmp ecx,0 ;debug VMM ?
je nodeb3 ;no, retail VMM
mov VMCB_PG_Table,CB_PT_Deb31_Off ;debug VMM loaded
jmp vm1
nodeb3: mov VMCB_PG_Table,CB_PT_Ret31_Off ;get offset for retail VMM
jmp vm1
win4: cmp ecx,0 ;debug VMM ?
je nodeb4
or [ebp.Client_FLAGS],1 ;yes, cannot handle
ret
nodeb4: mov win4_flag,-1
mov VMCB_PG_Table,CB_PT_Ret40_Off
vm1: VMMcall Get_Sys_VM_Handle
mov ecx,110h
mov edi,VMCB_PG_Table
mov edx,[ebx+edi] ;get page table of SYS VM
mov SYS_PG_Table,edx
ownloop:mov eax,[edx] ;get page entry
mov esi,eax
cmp win4_flag,-1
jne w3loop
and esi,P_WRITE
jz nextpg
jmp gotinst
w3loop: and esi,PG_Type ;filter "Avail" field of entry
cmp esi,PgT_INSTANCE ;instanced page found ?
je gotinst
nextpg: add edx,4 ;no, test next page
lp1: loop ownloop
done: cmp Inst_Desc_Buf,0
jne done1
call descr ;build Instance Description Buf
jnc done1 ;error in decr buf build
Client_Ptr_Flat edi,DS,BX ;get callers buffer
mov edi,[edi] ;get far pointer
call v862lin
mov eax,0
mov ecx,(sizeof Inst_Desc_Struc)/4
rep stosd
jmp done2
done1: mov ecx,Inst_Buf_Size
shr ecx,2 ;copy dword
mov esi,Inst_Desc_Buf
Client_Ptr_Flat edi,DS,BX ;get callers buffer
mov edi,[edi] ;get far pointer
call v862lin
rep movsd ;copy Instance Description Buf
done2: Client_Ptr_Flat edi,DS,DX ;get callers buffer
mov edi,[edi] ;get far pointer
call v862lin
mov esi,inst_count
imul esi,sizeof Inst_Ownership_Struc
add edi,esi
mov eax,Last_Entry
stosd
mov inst_count,0
ret ;walked all VM's
gotinst:and eax,P_PRES ;page present ?
jnz gotpres
got1: cmp win4_flag,-1
jne got31
inc w4_npres_count
got31: VMMcall Get_Next_VM_Handle ;SYS VM does not own Inst Pg
VMMCall Test_Sys_VM_Handle ;check all others
jnz nextvm ;Z=1 if SYS VM
cmp win4_flag,-1
jne lp3
cmp w4_pres_count,1
jne lp4
cmp w4_npres_count,0
je lp4
mov eax,110h
sub eax,ecx
cmp eax,0a0h
jl got4
cmp eax,0c8h ;exclude screen mem
jl lp4
got4: push ebx
mov ebx,w4_cur_handle
call storepg ;write instance page to V86 buf
pop ebx ;restore current VM handle
lp4: mov w4_pres_count,0
mov w4_npres_count,0
lp3: add edx,4 ;next page table entry
jmp lp1
nextvm: push edx
sub edx,SYS_PG_Table ;current offset into page table
mov eax,edx
mov edi,VMCB_PG_Table
mov edx,[ebx+edi] ;get page table of next VM
add edx,eax ;current entry
mov eax,[edx] ;get current entry
pop edx ;current entry from SYS_VM
jmp gotinst
gotpres:cmp win4_flag,-1
jne gotpr3
inc w4_pres_count
mov w4_cur_handle,ebx
jmp got31 ;test next entry
gotpr3: call storepg ;store page number in V86 buffer
jmp got31 ;test next entry

;Storepg - Writes number of instanced page and VM handle, flags, ID
;to V86 buffer in DS:DX
;INPUT: EBX = VM handle
; EBP = Client_Ptr
; ECX = current pagecount (<110h)

storepg:push eax
push esi
push edi
mov eax,110h
sub eax,ecx ;eax = number of inst page
Client_Ptr_Flat edi,DS,DX ;get callers buffer
mov edi,[edi] ;get far pointer
call v862lin
mov esi,inst_count
imul esi,sizeof Inst_Ownership_Struc
add edi,esi
mov [edi.Inst_PG_No],eax ;store number of instanced page
mov [edi.Owner_VM_Handle],ebx ;store VM_Handle
mov eax,[ebx.CB_VM_Status]
mov [edi.Owner_VM_Flags],eax
mov eax,[ebx.CB_VMID] ;get VMID
mov [edi.Owner_VM_ID],eax ;store ID
inc inst_count
pop edi
pop esi
pop eax
ret

;Create the Instance Description Buffer with data from hooked _AddInstanceItem

;Since 140 Kb are not a big problem in win386, I simply allocate a bit array.
;Every bit stands for a Byte in the first 10fh pages.
;A bit is set if the corresponding byte is marked instanced in an InstData
;struc. In this way I must not handle the overlapping (left, right, lower,
;upper) instance items for building the Instance Description Buffer.
;If you ever inspect the code from the VMM, which generates the VMM
;Instance Description Buffer, you will be astonished how a different approach
;can avoid al lot of programming work.

descr: ;int 3
pushad
cmp hook_err,-1 ;error in _AddInstanceItemhook?
je deserr
mov eax,110000h
shr eax,3
mov ecx,eax
push ecx
VMMcall _HeapAllocate
pop ecx
cmp eax,0
je deserr
mov edi,eax
mov bit_array,eax
shr ecx,2
mov eax,0
push edi
rep stosd ;perform ZeroInit
pop edi
mov Inst_Buf_Size,1000h ;size in dword
VMMcall _PageAllocate <1,PG_SYS,0,0,0,0,0,PAGEFIXED+PAGEZEROINIT>
mov Inst_Desc_Buf,edx ;store address
mov Inst_Buf_Handle,eax ;store handle
mov ebx,8
mov esi,Data_Buf_Addr
mov ecx,Inst_Data_Count ;# of InstData strucs
;int 3
desclp: push ecx
mov eax,[esi.KM_InstData.InstType]
cmp eax,ALWAYS_Field
je blp1
cmp eax,INDOS_Field
jnz skiplp
blp1: mov eax,[esi.KM_InstData.InstLinaddr] ;get VM linear address
mov ecx,[esi.KM_InstData.InstSize]
bitlp: bts [edi],eax ;386 power!,set bit in array
inc eax
loop bitlp
skiplp: add esi,sizeof KM_InstData ;next InstData Struc
pop ecx ;current Inst_Data_Count
loop desclp
mov ecx,110000h
mov ebx,Inst_Desc_Buf ;all bits set
mov eax,0 ;begin with bit 0
mov esi,0 ;size of last item
tstlp: bt [edi],eax ;test bit
inc eax
jc bitset
loop tstlp
desret: mov eax,bit_array
VMMcall _HeapFree
clc
popad
ret ;all bits tested
itemend:mov [ebx.Inst_Desc_Struc.Item_Size],edx
cmp edx,4
push edx
jb item5
mov edx,[ebx.Inst_Desc_Struc.VM_Lin_Address]
test edx,3
jz item2
and edx,3
sub edx,4
neg edx
push eax

mov eax,[ebx.Inst_Desc_Struc.Item_Size]
sub eax,edx
cmp eax,4
jb item4
mov eax,esi
and eax,3
sub eax,4
neg eax
cmp eax,edx
jz item4
ja item3
add esi,eax
add esi,4
sub esi,edx
jmp item4
item3: sub eax,edx
add esi,eax
item4: pop eax
jmp item5
item2: add esi,3 ;last Inst_Buf_Off
and esi,not 3
item5: ;int 3
mov [ebx.Inst_Desc_Struc.Inst_Buf_Off],esi ;offset in Inst Buf
pop edx
add esi,edx ;Inst_Buf_Off for next item
add ebx,sizeof Inst_Desc_Struc ;next entry
push ebx
mov edx,Inst_Desc_Buf
add edx,Inst_Buf_Size
add ebx,sizeof Inst_Desc_Struc ;next entry
cmp ebx,edx
pop ebx
jl item1
sub ebx,Inst_Desc_Buf
push ebx
push eax
push ecx
mov ecx,Inst_Buf_Size
add ecx,1000h
shr ecx,0ch
mov edx,Inst_Buf_Handle
VMMcall _PageReAllocate
cmp eax,0
je deserr
add Inst_Buf_Size,1000h
mov Inst_Buf_Handle,eax
mov Inst_Desc_Buf,edx
pop ecx
pop eax
pop ebx
add ebx,Inst_Desc_Buf
item1: dec ecx
jnz tstlp
jmp desret ;all bits tested
bitset: dec ecx
mov edx,1 ;instanced byte counter
dec eax
mov [ebx.Inst_Desc_Struc.VM_Lin_Address],eax
inc eax
itemlp: bt [edi],eax ;test following bit
inc eax ;next bit
jnc itemend
inc edx ;instanced byte counter++
loop itemlp
jmp desret ;all bits tested
deserr: stc ;signal error
popad
ret

;V86 API, result of _AddInstanceItem hook

instmap:;int 3
cmp hook_err,-1 ;errore during -AddInstanceItem hook ?
jne hookok
or [ebp.Client_Flags],1 ;signal error
ret
hookok: cmp string_buf,0 ;already build ?
je instgo
jmp instcpy
instgo: mov eax,Inst_Data_Count
imul eax,sizeof Inst_Hook_Struc
cmp eax,1000h
ja instgo1
mov eax,1
jmp instgo2
instgo1:add eax,1000h
and eax,0fffh
shr eax,0ch
instgo2:VMMcall _PageAllocate
cmp eax,0
je inster1
mov string_buf_handle,eax
mov string_buf,edx

mov ecx,Inst_Data_Count
instlp: push ecx
mov esi,count
imul esi,sizeof KM_InstData
add esi,Data_Buf_Addr
;int 3
mov edi,[esi.KM_InstData.AddInst_Caller]
mov cur_inst,esi
cmp edi,'LTSR' ;instance struc from LOCALTSRS entry ?
je locadd
VxDcall VxDQuery_Address_to_VxDName
jc insterr
isVxD: push edi ;points to VxDname received from VxDQuery
;int 3
mov edi,w386_sis_tbl ;first Win386_KM_SIS
nextsis:mov ebx,[edi.KM_SIS.SIS_Instance_Data_Ptr]
cmp ebx,0 ;any instance data in current Win386_KM_SIS ?
jne idata
endlst: cmp [edi.KM_SIS.SIS_Next_Ptr],0 ;last SIS ?
je no2f
add edi,sizeof KM_SIS ;next Win386_KM_SIS
jmp nextsis
idata: mov esi,ebx ;Seg:Off of inst data list
movzx eax,si ;offset of inst data list
and esi,0ffff0000h
shr esi,0ch ;linear address of segment
add esi,eax ;linadr of inst data list
nextiis:int 3
mov ebx,[esi.IIS_Ptr] ;Seg:Off of instance item
cmp ebx,0 ;no more items ?
je endlst
movzx eax,bx ;offset of Instance Item
and ebx,0ffff0000h
shr ebx,0ch ;linear address of segment
add ebx,eax ;linadr of instance item
mov eax,cur_inst ;current Instance struc
;current instance item from int_2f_inst_table ?
cmp ebx,[eax.KM_InstData.InstLinAddr]
je inst2f
add esi,sizeof Instance_Item_Struc ;next Instance_Item_Struc
jmp nextiis
;InstDataStruc of DOS-TSR via int 2f
inst2f: add esp,4 ;forget name from VxDQuery
;int 3
mov esi,offset32 int_2f_string
mov ebx,edi ;current Win386_KM_SIS
inst2f1:mov edi,[count]
imul edi,sizeof Inst_Hook_Struc
add edi,string_buf
push edi ;current Inst_Hook_Struc
mov ecx,string_len/4
rep movsd ;copy "Create_Int_2F_Inst_Table" string
sub edi,9
mov esi,ebx ;points to Win386_KM_SIS
add esi,offset KM_SIS.Tsr_Name ;points to name of DOS TSR
cmp byte ptr [esi],'S'
jne inst1
cmp byte ptr[esi+1],'D'
jne inst1
mov esi,offset32 dos_sys_string
movsd ;copy "CONFIG DRV" string
movsd
jmp endname
inst1: movsd
movsd ;copy name of DOS TSR
sub edi,8
mov ecx,9
mov al,0
repne scasb
jne endname
mov al,20h
dec edi
rep stosb ;fill up with spaces
jmp endname
;InstDataStruc of a LOCALTSR via system.ini entry
locadd: ;int 3 ;uncomment this for debug
mov esi,offset32 localtsr_string
mov edi,[count]
imul edi,sizeof Inst_Hook_Struc
add edi,string_buf
push edi ;current Inst_Hook_Struc
mov ecx,string_len/4
rep movsd ;copy "VMM: Instance_LOCALTSRS " string
sub edi,9
mov esi,cur_inst ;InstDataStruc
mov esi,[esi.KM_InstData.InstLinAddr] ;esi = MCB of LOCALTSR
add esi,offset MCB_Name ;points to name of DOS TSR
movsd
movsd ;copy name of DOS TSR
sub edi,8
mov ecx,9
mov al,0
repne scasb
jne endname
mov al,20h
dec edi
rep stosb ;fill up with spaces
jmp endname
no2f: pop edi
mov esi,edi ;pointer to VxDName
mov edi,count
imul edi,sizeof Inst_Hook_Struc
add edi,string_buf
push edi
mov ecx,string_len/4
rep movsd ;save VxDName in string_buf
endname:pop edi ;current Inst_Hook_Struc
mov eax,cur_inst ;Instance struc
mov edx,[eax.KM_InstData.InstLinAddr]
mov [edi.Inst_Hook_Struc.Inst_Lin_Adr],edx
mov edx,[eax.KM_InstData.InstSize]
mov [edi.Inst_Hook_Struc.Inst_Size],edx
inc count
pop ecx
dec ecx
jnz instlp
instcpy:Client_Ptr_Flat edi,DS,DX ;address of callers ptr to buffer
mov edi,[edi]
call v862lin
mov esi,string_buf
mov ecx,Inst_Data_Count ;# of inst strucs
imul ecx, sizeof Inst_Hook_Struc
shr ecx,2
rep movsd ;copy data into callers V86 buffer
mov count,0
ret
insterr:pop ecx
inster1:or [ebp.Client_FLAGS],1 ;set carry, error
ret

;INPUT edi = Seg:Offs V86
;OUTPUT edi = linadr
v862lin:push edx
movzx edx,di
shr edi,10h
shl edi,4
add edi,edx
pop edx
ret


EndProc ListInst_V86_API

VxD_CODE_ENDS

END


  3 Responses to “Category : Files from Magazines
Archive   : DDJ9404B.ZIP
Filename : LISTINST.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/