You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1615 lines
33 KiB
1615 lines
33 KiB
TITLE RESAUX - support routines for resource manager
|
|
|
|
.xlist
|
|
include kernel.inc
|
|
include newexe.inc
|
|
include tdb.inc
|
|
include protect.inc
|
|
.list
|
|
|
|
ifdef WOW
|
|
WOW_OPTIMIZE_PRELOADRESOURCE = 1
|
|
endif
|
|
|
|
externA __AHINCR
|
|
externFP _lclose
|
|
externFP GlobalFree
|
|
externFP GlobalLock
|
|
externFP GlobalUnlock
|
|
externFP GlobalFlags
|
|
externFP GlobalReAlloc
|
|
externFP GlobalHandle
|
|
externFP GetExePtr
|
|
externFP MyOpenFile
|
|
externFP FarMyUpper
|
|
;externFP GlobalAlloc
|
|
externFP lstrlen
|
|
externFP lstrOriginal
|
|
externFP Int21Handler
|
|
|
|
externFP AllocSelector
|
|
externFP FreeSelector
|
|
externFP LongPtrAdd
|
|
ifdef WOW
|
|
externFP WOWFreeResource
|
|
endif
|
|
|
|
ifdef WOW_OPTIMIZE_PRELOADRESOURCE
|
|
externFP LongPtrAddWOW
|
|
externFP AllocSelectorWOW
|
|
endif
|
|
|
|
if KDEBUG
|
|
externFP OutputDebugString
|
|
endif
|
|
|
|
DataBegin
|
|
|
|
externW Win_PDB
|
|
|
|
if KDEBUG
|
|
externB fLoadTrace
|
|
endif
|
|
|
|
DataEnd
|
|
|
|
sBegin CODE
|
|
assumes CS,CODE
|
|
assumes DS,NOTHING
|
|
assumes ES,NOTHING
|
|
|
|
externNP MyAlloc
|
|
externNP MyLock
|
|
externNP GetOwner
|
|
externNP SetOwner
|
|
externNP GetCachedFileHandle
|
|
externNP CloseCachedFileHandle
|
|
|
|
externFP AllocSelectorArray
|
|
externFP set_discarded_sel_owner
|
|
externNP SetResourceOwner
|
|
externNP AllocResSelArray
|
|
ifdef WOW
|
|
externFP hMemCpy
|
|
externFP _HREAD
|
|
externW gdtdsc
|
|
endif
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; ;
|
|
; DirectResAlloc - This allocates memory for creating cursors and icons;
|
|
; "on the fly". ;
|
|
; ;
|
|
; Arguments: ;
|
|
; parmW hinstance ; Identifies the instance that allocates ;
|
|
; parmW resFlags ; Flags to be used in memory allocation ;
|
|
; parmW nBytes ; The size of the memory to be allocated ;
|
|
; ;
|
|
; Returns: ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; AX = 0 ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Fri 06 Jan 1989 -- Written by Sankar. ;
|
|
; ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc DirectResAlloc, <PUBLIC, FAR>, <si,di>
|
|
parmW hInstance
|
|
parmW resFlags
|
|
parmW nBytes
|
|
|
|
cBegin
|
|
cCall GetExePtr, <hInstance>
|
|
or ax, ax
|
|
jz err_end
|
|
push ax ; Save ptr to EXE header
|
|
|
|
xor bx, bx
|
|
cCall MyResAlloc, <ax, resFlags, nBytes, bx>
|
|
xchg ax,dx
|
|
pop cx ; restore exe header address
|
|
or ax,ax
|
|
jz err_end
|
|
cCall SetOwner,<ax,cx>
|
|
xchg ax,dx
|
|
err_end:
|
|
cEnd
|
|
|
|
|
|
cProc MyResAlloc,<PUBLIC,NEAR>
|
|
parmW hExe
|
|
parmW resFlags
|
|
parmW nBytes
|
|
parmW nAlign
|
|
cBegin
|
|
mov bx,resFlags ; Allocate memory for
|
|
or bl,NSTYPE or RNMOVE ; non-code, non-data segment
|
|
cCall MyAlloc,<bx,nBytes,nAlign>
|
|
test dl,GA_FIXED
|
|
jnz mysox
|
|
mov bx,dx
|
|
|
|
HtoS bx ; Make it ring 1
|
|
lar cx, bx
|
|
jnz mysox
|
|
test ch, 80h ; Present?
|
|
jnz mysox
|
|
int 3
|
|
mov es, hExe ; Set limit to the owner ie. hExe.
|
|
cCall set_discarded_sel_owner
|
|
|
|
mysox:
|
|
xchg ax,dx
|
|
cEnd
|
|
|
|
cProc IAllocResource,<PUBLIC,FAR>,<si>
|
|
parmW hResFile
|
|
parmW hResInfo
|
|
parmD newSize
|
|
cBegin
|
|
cCall GetExePtr,<hResFile>
|
|
or ax,ax
|
|
jz arx
|
|
mov es,ax
|
|
push es ; Save exe header address
|
|
mov si,hResInfo
|
|
push es ; push hexe
|
|
mov bx,es:[si].rn_flags
|
|
or bl,NSTYPE ; non-code, non-data segment
|
|
push bx ; push flags
|
|
push es:[si].rn_length ; push default size
|
|
mov bx,es:[ne_rsrctab]
|
|
mov cx,es:[bx].rs_align
|
|
mov dx,OFF_newSize
|
|
or dx,SEG_newSize ; Want a different size?
|
|
jz ar1 ; No, continue
|
|
pop dx ; Yes discard default size
|
|
push cx ; Save alignment shift
|
|
mov dx,newSize.hi ; Round up new size by alignment
|
|
xor ax,ax
|
|
not ax
|
|
shl ax,cl
|
|
not ax
|
|
add ax,newSize.lo
|
|
adc dx, 0
|
|
ar0:
|
|
shr dx,1 ; convert to alignment units
|
|
rcr ax,1
|
|
loop ar0
|
|
pop cx ; Restore alignment shift
|
|
push ax ; Push new size
|
|
ar1:
|
|
cmp es:[si].rn_handle,0 ; Already a handle?
|
|
je ar2 ; No, continue
|
|
pop ax ; AX = length
|
|
add sp,4 ; ignore flags and hExe
|
|
xor dx,dx
|
|
jcxz ma3
|
|
ma2:
|
|
shl ax,1
|
|
rcl dx,1
|
|
loop ma2
|
|
ma3:
|
|
xor cx,cx
|
|
cCall GlobalReAlloc,<es:[si].rn_handle,dxax,cx>
|
|
cwd ; zero dx (may not be needed)
|
|
or ax,ax ; did it fail?
|
|
jz ar3
|
|
|
|
cCall GlobalHandle,<ax>
|
|
jmps ar3
|
|
ar2:
|
|
push cx ; push alignment shift count
|
|
cCall MyResAlloc ; rn_flags, rn_length, rs_align
|
|
ar3:
|
|
xchg ax,dx
|
|
pop cx ; restore exe header address
|
|
or ax,ax
|
|
jz arx
|
|
cCall SetOwner,<ax,cx>
|
|
xchg ax,dx
|
|
arx:
|
|
or ax, ax
|
|
jnz @F
|
|
KernelLogError DBF_WARNING,ERR_ALLOCRES,"AllocResource failed"
|
|
xor ax, ax ; Restore the NULL value in ax
|
|
@@:
|
|
mov cx,ax
|
|
cEnd
|
|
|
|
|
|
cProc ResAlloc,<PUBLIC,FAR>,<si,di>
|
|
parmD pResInfo
|
|
parmW fh
|
|
parmW isfh
|
|
ifdef WOW_OPTIMIZE_PRELOADRESOURCE
|
|
parmW hiResOffset
|
|
parmW loResOffset
|
|
endif
|
|
localW hres
|
|
cBegin
|
|
xor ax,ax
|
|
cCall IAllocResource,<pResInfo,ax,ax>
|
|
les si,pResInfo
|
|
mov hres,ax ; Returns handle in AX
|
|
mov ax,dx ; Segment address in DX
|
|
mov bx,es:[ne_rsrctab]
|
|
mov cx,es:[bx].rs_align
|
|
mov dx,es:[si].rn_length
|
|
xor bx,bx
|
|
cmp hres,bx
|
|
; jnz ra1
|
|
jz rax
|
|
|
|
ra1: shl dx,1
|
|
rcl bx,1
|
|
loop ra1
|
|
push ds
|
|
mov cx,dx
|
|
mov si, bx ; Save hi word of length
|
|
mov bx,fh
|
|
cmp isfh,bx ; is bx a file handle?
|
|
je ra2 ; if so, load from file
|
|
ifdef WOW
|
|
ifdef WOW_OPTIMIZE_PRELOADRESOURCE
|
|
cmp hiResOffset, 0
|
|
jz @F
|
|
push ax
|
|
mov al, __AHINCR
|
|
mul byte ptr hiResOffset
|
|
add bx,ax
|
|
pop ax
|
|
@@:
|
|
cCall hMemCpy,<ax,0,bx,loResOffset,si,cx>
|
|
else
|
|
cCall hMemCpy,<ax,0,bx,0,si,cx>
|
|
endif
|
|
jmps ra3
|
|
ra2:
|
|
cCall _hRead,<bx,ax,0,si,cx>
|
|
cmp dx, si ; If we didn't read what we wanted
|
|
jnz rafail ; then fail
|
|
cmp ax, cx
|
|
jnz rafail
|
|
else ; NOT WOW
|
|
cCall CopyResource,<ax,bx,si,cx>
|
|
jmps ra3
|
|
ra2:
|
|
cCall ReadResource,<ax,bx,si,cx>
|
|
jc rafail
|
|
endif ; WOW
|
|
ra3:
|
|
pop ds
|
|
ra4:
|
|
mov ax,hres
|
|
jmps rax
|
|
rafail:
|
|
mov bx,ds
|
|
pop ds
|
|
rafail2:
|
|
cCall GlobalFree,<hres>
|
|
if KDEBUG
|
|
push es
|
|
mov bx,SEG_pResInfo
|
|
mov es,bx
|
|
xor bx,bx
|
|
KernelLogError <DBF_WARNING>,ERR_BADRESREAD,"Unable to read resource from @ES:BX"
|
|
pop es
|
|
endif
|
|
xor ax,ax
|
|
rax:
|
|
cEnd
|
|
|
|
cProc CopyResource,<PUBLIC,NEAR>
|
|
parmW DestSeg
|
|
parmW SrcSeg
|
|
parmD nBytes
|
|
cBegin
|
|
push es
|
|
mov ds, SrcSeg ; bx is segment of resource
|
|
mov es, DestSeg
|
|
xor si, si
|
|
xor di, di
|
|
cld
|
|
rc_next:
|
|
mov cx, 8000h
|
|
cmp word ptr [nBytes+2], 0
|
|
clc ; No odd byte to copy
|
|
jne big_copy
|
|
mov cx, word ptr [nBytes]
|
|
shr cx, 1 ; Word count
|
|
big_copy:
|
|
rep movsw
|
|
rcl cx, 1 ; Rescue low bit
|
|
rep movsb ; Any odd byte
|
|
|
|
dec word ptr [nBytes+2]
|
|
js rc_done
|
|
|
|
mov ax, ds
|
|
add ax, __AHINCR
|
|
mov ds, ax
|
|
mov ax, es
|
|
add ax, __AHINCR
|
|
mov es, ax
|
|
jmp rc_next
|
|
|
|
rc_done:
|
|
pop es
|
|
cEnd
|
|
|
|
cProc ReadResource,<PUBLIC,NEAR>
|
|
parmW DestSeg
|
|
parmW fh
|
|
parmD nBytes
|
|
cBegin
|
|
mov bx, fh
|
|
xor dx, dx
|
|
mov ds, DestSeg
|
|
mov di, word ptr nBytes
|
|
mov si, word ptr [nBytes+2]
|
|
around_again:
|
|
mov cx, 8000h
|
|
or si, si
|
|
jnz big_xfer
|
|
cmp di, cx
|
|
jae big_xfer
|
|
mov cx, di
|
|
big_xfer:
|
|
mov ah, 3Fh
|
|
DOSCALL
|
|
jc rrfail
|
|
cmp ax, cx
|
|
jne rrfail
|
|
|
|
sub di, cx
|
|
sbb si, 0
|
|
jnz incr_address
|
|
or di, di
|
|
jz rrdone
|
|
incr_address:
|
|
add dx, cx
|
|
jnc around_again
|
|
mov ax, ds
|
|
add ax, __AHINCR
|
|
mov ds, ax
|
|
jmp around_again
|
|
|
|
rrfail:
|
|
stc
|
|
jmps rrx
|
|
rrdone:
|
|
clc
|
|
rrx:
|
|
cEnd
|
|
|
|
cProc IAccessResource,<PUBLIC,FAR>
|
|
parmW hResFile
|
|
parmW hResInfo
|
|
cBegin
|
|
xor ax, ax
|
|
cCall InternalAccessResource,<hResFile,hResInfo,ax>
|
|
cEnd
|
|
|
|
cProc InternalAccessResource,<PUBLIC>
|
|
parmW hResFile
|
|
parmW hResInfo
|
|
parmW CachedFile
|
|
cBegin
|
|
cCall GetExePtr,<hResFile>
|
|
mov es,ax
|
|
mov bx, hResInfo
|
|
mov ax,es:[bx].rn_flags
|
|
push es:[bx].rn_length
|
|
push es:[bx].rn_offset
|
|
mov dx,es:[ne_pfileinfo]
|
|
mov bx,es:[ne_rsrctab]
|
|
mov cx,es:[bx].rs_align
|
|
push cx
|
|
push es
|
|
cmp CachedFile, 0
|
|
je open_it
|
|
mov cx, -1
|
|
cCall GetCachedFileHandle,<es,cx,cx>
|
|
mov bx, ax
|
|
jmps got_fh
|
|
open_it:
|
|
if SHARE_AWARE
|
|
mov bx,OF_REOPEN or OF_VERIFY or OF_NO_INHERIT or OF_SHARE_DENY_WRITE
|
|
else
|
|
mov bx,OF_REOPEN or OF_VERIFY or OF_NO_INHERIT
|
|
endif
|
|
regptr esdx,es,dx
|
|
push es
|
|
push dx
|
|
cCall MyOpenFile,<esdx,esdx,bx> ; returns handle in ax & bx
|
|
pop dx
|
|
pop es
|
|
;;; cmp ax, -1 ; Success?
|
|
;;; jne got_fh ; yes.
|
|
;;; ; no, try compatibility mode
|
|
;;; mov bx,OF_REOPEN or OF_VERIFY or OF_NO_INHERIT
|
|
;;; regptr esdx,es,dx
|
|
;;; cCall MyOpenFile,<esdx,esdx,bx> ; returns handle in ax & bx
|
|
got_fh:
|
|
pop es
|
|
pop cx
|
|
pop dx
|
|
inc ax
|
|
jnz ra2c
|
|
pop dx
|
|
ra2b:
|
|
mov bx,-1
|
|
jmps ra2x
|
|
ra2c:
|
|
xor ax,ax
|
|
push cx
|
|
AR_shift:
|
|
shl dx,1
|
|
rcl ax,1
|
|
loop AR_shift
|
|
mov cx,ax
|
|
mov ax,4200h
|
|
DOSCALL
|
|
pop cx
|
|
pop dx
|
|
jc ra2b
|
|
xor ax,ax
|
|
AR_shift1:
|
|
shl dx,1
|
|
rcl ax,1
|
|
loop AR_shift1
|
|
mov cx,ax ; CX:DX is size of resource
|
|
ra2x:
|
|
mov ax,bx ; AX and BX are file handle
|
|
cEnd
|
|
|
|
cProc ILockResource,<PUBLIC,FAR>,<si>
|
|
parmW hres
|
|
localD lpfn
|
|
cBegin
|
|
mov ax,hres ; Get object handle
|
|
or ax,ax
|
|
jnz short_rel
|
|
lrfail0:
|
|
jmp lrfail
|
|
short_rel:
|
|
|
|
ifdef WOW
|
|
test ax, GA_WOWHANDLE ; should we call WOW32 FreeResource?
|
|
jnz @f
|
|
jmp lrfail
|
|
|
|
@@:
|
|
endif; WOW
|
|
|
|
cCall GlobalLock,<ax> ; Attempt to lock it
|
|
jcxz yawn
|
|
jmp lrx
|
|
yawn:
|
|
mov bx,hres ; Failed, is it fixed?
|
|
test bl,GA_FIXED
|
|
jnz lrfail0 ; Yes, fail all the way
|
|
|
|
HtoS bx
|
|
; On WOW we don't copy the owner to the real LDT since it is slow to call
|
|
; the NT Kernel, so we read our copy of it directly.
|
|
; see set_discarded_sel_owner mattfe mar 23 93
|
|
|
|
push cx
|
|
lar cx, bx
|
|
pop cx
|
|
jnz lrfail0 ; NZ -> LAR failed
|
|
mov es,cs:gdtdsc
|
|
and bl, not 7
|
|
mov bx,es:[bx].dsc_owner
|
|
mov es,bx
|
|
assumes es,nothing
|
|
cmp es:[ne_magic],NEMAGIC ; Does owner point to EXE header?
|
|
jne lrfail ; No, fail.
|
|
mov bx,es:[ne_rsrctab] ; Yes, scan resource table
|
|
cmp es:[ne_restab],bx ; Is there a resource table?
|
|
je lrfail ; No, just free the global object
|
|
push ds
|
|
SetKernelDS
|
|
pop ds
|
|
assumes ds, nothing
|
|
mov dx,hres ; Yes, look for this handle
|
|
add bx,SIZE NEW_RSRC ; Point to first resource type
|
|
lrloop0:
|
|
cmp es:[bx].rt_id,ax ; End of table?
|
|
je lrfail ; Yes, just return failure
|
|
lea si,[bx].rt_proc ; Remember address of type proc.
|
|
mov cx,es:[bx].rt_nres
|
|
add bx,SIZE RSRC_TYPEINFO ; Point to first resource of this type
|
|
lrloop:
|
|
cmp es:[bx].rn_handle,dx ; Is this the one?
|
|
je lr3 ; Yes, go see if type proc to call
|
|
add bx,SIZE RSRC_NAMEINFO ; No, point to next resource
|
|
loop lrloop ; Any more resources for this type?
|
|
jmps lrloop0 ; No, advance to next type
|
|
lr3:
|
|
cmp word ptr es:[si+2],0 ; Was there a proc defined for this type
|
|
je lrfail ; No, return failure.
|
|
|
|
if KDEBUG
|
|
jmp PrintInfo
|
|
PrintedInfo:
|
|
endif
|
|
push ds ; preserve these registers across call
|
|
push es
|
|
push bx
|
|
|
|
mov ax,word ptr es:[si] ; set up proc addr to call on stack
|
|
mov word ptr lpfn,ax
|
|
mov ax,word ptr es:[si]+2
|
|
mov word ptr lpfn+2,ax
|
|
|
|
mov cx,es ; cx = es for later push
|
|
|
|
mov ax,ss ; Zap segment registers so he can't
|
|
mov es,ax ; diddle DS
|
|
mov ds,ax
|
|
|
|
cCall lpfn,<dx,cx,bx> ; Yes, call proc to reload
|
|
|
|
xchg ax,cx ; cx = result
|
|
jcxz @F ; skip lock if NULL
|
|
|
|
cCall GlobalLock,<cx> ; Attempt to lock result
|
|
@@:
|
|
pop bx
|
|
pop es
|
|
pop ds
|
|
jcxz lrfail
|
|
or byte ptr es:[bx].rn_flags,RNLOADED ; Mark loaded
|
|
jmps lrx
|
|
lrfail: ; Here to return failure.
|
|
KernelLogError DBF_WARNING,ERR_LOCKRES,"LockResource failed"
|
|
xor ax,ax
|
|
cwd
|
|
lrx:
|
|
cEnd
|
|
|
|
if KDEBUG
|
|
RCTypes:
|
|
db 'Custom', 0
|
|
db 'Cursor', 0
|
|
db 'Bitmap', 0
|
|
db 'Icon', 0
|
|
db 'Menu', 0
|
|
db 'Dialog', 0
|
|
db 'String', 0
|
|
db 'FontDir', 0
|
|
db 'Font', 0
|
|
db 'Accelerator', 0
|
|
db 'RCData', 0
|
|
db 'Type11', 0
|
|
db 'GroupCursor', 0
|
|
db 'Type13', 0
|
|
db 'GroupIcon', 0
|
|
db 0
|
|
PrintInfo:
|
|
pusha
|
|
mov cx, word ptr es:[si][rt_id-rt_proc]
|
|
and ch, not 80h
|
|
mov si, offset RCTypes
|
|
pi_1: inc si
|
|
pi_2: cmp byte ptr cs:[si], 0
|
|
jnz pi_1
|
|
inc si
|
|
cmp byte ptr cs:[si], 0
|
|
loopnz pi_2
|
|
jnz @F
|
|
mov si, offset RCTypes
|
|
@@:
|
|
mov ax, es:[bx].rn_id
|
|
; test ah, 80h
|
|
; jz pi_name
|
|
and ah, not 80h
|
|
krDebugOut <DEB_TRACE or DEB_krLoadSeg>, "%es0: reading resource @CS:SI.#ax"
|
|
; jmps pi_done
|
|
;pi_name:
|
|
; int 3
|
|
; krDebugOut <DEB_TRACE or DEB_krLoadSeg>, "%es0: reading resource @CS:SI.@ES:AX"
|
|
;pi_done:
|
|
popa
|
|
jmp PrintedInfo
|
|
endif
|
|
|
|
|
|
cProc IFreeResource,<PUBLIC,FAR>,<ds,si>
|
|
parmW hres
|
|
cBegin
|
|
mov ax,hres ; Get segment address of resource
|
|
or ax,ax
|
|
jz frxj
|
|
ifdef WOW
|
|
test ax, GA_WOWHANDLE ; should we call WOW32 FreeResource?
|
|
jnz @f
|
|
cCall WOWFreeResource,<ax> ; you bet !
|
|
xor ax, ax
|
|
jmp frxx
|
|
|
|
@@:
|
|
endif; WOW
|
|
cCall MyLock,<ax>
|
|
or ax,ax ; Discarded or invalid handle?
|
|
jnz fr0a ; No, continue
|
|
mov bx,hres
|
|
|
|
test bl,GA_FIXED
|
|
jnz fr2 ; Return NULL
|
|
HtoS bx ; Fix RPL so we can do LAR
|
|
lar cx, bx
|
|
jnz fr2 ; LAR failed, return NULL
|
|
test ch, 80h ; Present?
|
|
jnz fr2 ; yes, return NULL
|
|
; On WOW we don't copy the owner to the real LDT since it is slow to call
|
|
; the NT Kernel, so we read our copy of it directly.
|
|
; see set_discarded_sel_owner mattfe mar 23 93
|
|
|
|
mov ds,cs:gdtdsc
|
|
and bl, not 7
|
|
mov cx,ds:[bx].dsc_owner
|
|
mov ds,cx
|
|
jmps fr0b
|
|
frxj:
|
|
jmps frx
|
|
|
|
fr0a:
|
|
cCall GetOwner,<ax>
|
|
mov ds,ax
|
|
xor ax,ax
|
|
|
|
fr0b:
|
|
cmp ds:[ne_magic],NEMAGIC ; Is it an exe header?
|
|
jne fr1 ; No, just free the handle
|
|
mov bx,ds:[ne_rsrctab]
|
|
cmp ds:[ne_restab],bx ; Is there a resource table?
|
|
je fr1 ; No, just free the handle
|
|
mov dx,hres
|
|
add bx,SIZE NEW_RSRC ; Point to first resource type
|
|
frloop0:
|
|
cmp ds:[bx].rt_id,ax ; End of table?
|
|
je fr1 ; Yes, just free the handle
|
|
mov cx,ds:[bx].rt_nres
|
|
add bx,SIZE RSRC_TYPEINFO ; Point to first resource of this type
|
|
frloop:
|
|
cmp ds:[bx].rn_handle,dx ; Is this the one?
|
|
je fr0 ; Yes, go decrement usage count
|
|
add bx,SIZE RSRC_NAMEINFO ; No, point to next resource
|
|
loop frloop ; Any more resources for this type?
|
|
jmps frloop0 ; No, advance to next type
|
|
fr0:
|
|
cmp ds:[bx].rn_usage,ax ; Already zero?
|
|
je fr1a ; Yes, then free this resource now
|
|
dec ds:[bx].rn_usage ; Decrement use count
|
|
jg frx ; Positive means still in use
|
|
test ds:[bx].rn_flags,RNDISCARD ; Discardable?
|
|
jnz fr2 ; Yes, let discard logic toss it
|
|
fr1a:
|
|
mov ds:[bx].rn_handle,ax ; o.w. free memory now
|
|
and byte ptr ds:[bx].rn_flags,not RNLOADED ; Mark not loaded
|
|
fr1:
|
|
cCall GlobalFree,<hres> ; Free global object
|
|
fr2:
|
|
mov hres,ax
|
|
frx:
|
|
mov ax,hres ; Return zero if freed, hres o.w.
|
|
frxx:
|
|
cEnd
|
|
|
|
|
|
cProc ISizeofResource,<PUBLIC,FAR>
|
|
parmW hResFile
|
|
parmW hResInfo
|
|
cBegin
|
|
cCall GetExePtr,<hResFile>
|
|
mov es,ax
|
|
mov bx,hResInfo
|
|
mov ax,es:[bx].rn_length
|
|
xor dx,dx
|
|
mov bx,es:[ne_rsrctab]
|
|
mov cx,es:[bx].rs_align
|
|
sr0: shl ax,1
|
|
rcl dx,1
|
|
loop sr0
|
|
cEnd
|
|
|
|
|
|
cProc DefaultResourceHandler,<PUBLIC,FAR>,<si,di>
|
|
parmW hRes
|
|
parmW hResFile
|
|
parmW hResInfo
|
|
localW SavePDB
|
|
cBegin
|
|
cCall GetExePtr,<hResFile>
|
|
or ax,ax
|
|
jz drhx
|
|
mov si,ax
|
|
mov cx,hRes ; if hRes == NULL, we need to allocate.
|
|
jcxz @F
|
|
cCall GlobalHandle,<cx>
|
|
or dx,dx ; Nothing to do for allocated resources
|
|
jnz drhx
|
|
@@:
|
|
SetKernelDS
|
|
mov ax, Win_PDB ; Save current PDB
|
|
mov SavePDB, ax
|
|
mov ax, 1
|
|
cCall InternalAccessResource,<si,hResInfo,ax>
|
|
mov di,ax
|
|
inc ax
|
|
jz drhx
|
|
ifdef WOW_OPTIMIZE_PRELOADRESOURCE
|
|
cCall ResAlloc,<si,hResInfo,di,di, 0, 0>
|
|
else
|
|
cCall ResAlloc,<si,hResInfo,di,di>
|
|
endif
|
|
push ax
|
|
;;; cCall _lclose,<di>
|
|
push bx
|
|
cCall CloseCachedFileHandle,<di>
|
|
mov bx, SavePDB
|
|
mov Win_PDB, bx ; Restore PDB
|
|
pop bx
|
|
pop ax
|
|
drhx:
|
|
cEnd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; LoadResource ;
|
|
; ;
|
|
; Called by each task ONCE to load a resource. ;
|
|
; If this is the VERY FIRST time this resource is loaded ;
|
|
; AND it is fixed, then the resource handler proc is called. ;
|
|
; AND it is discardable then only a handle is allocated. We wait ;
|
|
; until LockResource to actually load the resource. ;
|
|
; ;
|
|
; If the resource had been loaded by a previous task ;
|
|
; then we load it if it has been discarded. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; HANDLE hResFile ;
|
|
; HANDLE hResInfo ;
|
|
; ;
|
|
; Returns: ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Tue Jan 01, 1980 07:23:34p -by- David N. Weise [davidw] ;
|
|
; ReWrote it from C into assembly and added this nifty comment block. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc ILoadResource,<PUBLIC,FAR>,<di,si>
|
|
|
|
parmW hResFile
|
|
parmW hResInfo
|
|
localV DscBuf,DSC_LEN
|
|
localD lpfn
|
|
cBegin
|
|
mov di,hResInfo ; DI = pName
|
|
or di,di
|
|
jnz got_a_hResInfo
|
|
jmp lr_error_ret
|
|
got_a_hResInfo:
|
|
|
|
cCall GetExePtr,<hResFile>
|
|
or ax,ax
|
|
jnz got_a_resource_file
|
|
jmp lr_error_ret
|
|
got_a_resource_file:
|
|
|
|
mov ds,ax ; DS = pExe
|
|
mov si,ds:[ne_rsrctab] ; DS:SI = pRes
|
|
cmp si,ds:[ne_restab]
|
|
jnz got_a_resource_table
|
|
jmp lr_error_ret
|
|
got_a_resource_table:
|
|
|
|
; If first LoadResource on resource, then call resource handler proc
|
|
; associated with resource type.
|
|
|
|
mov ax,[di].rn_usage
|
|
or ax,ax
|
|
jz maybe_load_it
|
|
got_it: inc [di].rn_usage
|
|
mov ax,[di].rn_handle
|
|
jmp lr_ret
|
|
|
|
; IF
|
|
; 1) the resource is discardable
|
|
; 2) and has been loaded before
|
|
; 3) and has been FreeResource'd
|
|
; 4) but not yet discarded (See FreeResource for this madness!)
|
|
; THEN
|
|
; 1) the usage count is zero
|
|
; 2) it's still marked loaded
|
|
; 3) it's still in memory
|
|
|
|
maybe_load_it:
|
|
cmp ax,[di].rn_handle ; we know that ax == rn_usage == 0
|
|
jz not_loaded_before
|
|
test [di].rn_flags,RNLOADED
|
|
jz load_it
|
|
cCall GlobalFlags,<[di].rn_handle>
|
|
test ah,HE_DISCARDED
|
|
jz got_it
|
|
jmps load_it
|
|
|
|
not_loaded_before:
|
|
test [di].rn_flags,RNDISCARD
|
|
jz load_it
|
|
|
|
; Allocate a zero length object to get a handle.
|
|
|
|
push si
|
|
mov ax, [di].rn_length
|
|
xor dx, dx
|
|
mov bx, ds:ne_rsrctab
|
|
mov cx, [bx].rs_align
|
|
fred:
|
|
shl ax, 1
|
|
rcl dx, 1
|
|
loop fred
|
|
|
|
add ax, 15
|
|
adc dx, 0
|
|
mov cx, dx
|
|
inc cx ; # selectors
|
|
;; WOW x86 only
|
|
cCall AllocResSelArray,<cx,ds>
|
|
jz no_sel
|
|
StoH al
|
|
no_sel:
|
|
pop si
|
|
mov [di].rn_handle,ax
|
|
jmp got_it
|
|
load_it:
|
|
lea si,[si].SIZE new_rsrc ; DS:SI = pType
|
|
lr_type_loop:
|
|
cmp [si].rt_id,0
|
|
jz lr_error_ret
|
|
lea bx,[si].SIZE rsrc_typeinfo ; BX =pName1
|
|
mov ax,word ptr [si].rt_proc[0]
|
|
or ax,word ptr [si].rt_proc[2]
|
|
jz lr_skip_name
|
|
mov cx,[si].rt_nres
|
|
jcxz lr_next_type
|
|
lr_name_loop:
|
|
cmp bx,di
|
|
jnz lr_next_name
|
|
|
|
push ds ; Zap segment registers to prevent
|
|
|
|
mov ax,word ptr [si].rt_proc
|
|
mov word ptr lpfn,ax
|
|
mov ax,word ptr [si].rt_proc+2
|
|
mov word ptr lpfn+2,ax
|
|
|
|
push [di].rn_handle
|
|
push hResFile
|
|
push hResInfo
|
|
|
|
mov ax,ss ; callee from trashing our DS.
|
|
mov ds,ax
|
|
mov es,ax
|
|
|
|
call lpfn
|
|
|
|
pop ds
|
|
|
|
or ax,ax
|
|
jz lr_ret
|
|
mov [di].rn_handle,ax
|
|
or [di].rn_flags,RNLOADED
|
|
jmp got_it
|
|
|
|
lr_next_name:
|
|
add bx,SIZE rsrc_nameinfo
|
|
loop lr_name_loop
|
|
jmps lr_next_type
|
|
|
|
lr_skip_name:
|
|
mov ax,[si].rt_nres
|
|
mov cx,SIZE rsrc_nameinfo
|
|
mul cx
|
|
add bx,ax
|
|
|
|
lr_next_type:
|
|
mov si,bx
|
|
jmp lr_type_loop
|
|
|
|
|
|
lr_error_ret:
|
|
if KDEBUG
|
|
xor bx,bx
|
|
kerror ERR_BADRESFILE,<Error loading from resource file - >,ds,bx
|
|
endif
|
|
xor ax,ax
|
|
lr_ret:
|
|
|
|
cEnd
|
|
|
|
sEnd CODE
|
|
|
|
|
|
sBegin MISCCODE
|
|
assumes CS,MISCCODE
|
|
assumes DS,NOTHING
|
|
assumes ES,NOTHING
|
|
|
|
externNP MISCMapDStoDATA
|
|
|
|
cProc GetResOrd,<PUBLIC,NEAR>,<si,di>
|
|
parmW hResFile
|
|
parmD lpszType
|
|
parmD lpszName
|
|
localW hRes
|
|
cBegin
|
|
cCall OrdinalOrString, <lpszType>
|
|
mov si,ax
|
|
cCall OrdinalOrString, <lpszName>
|
|
mov di,ax
|
|
|
|
gro_maybe_search_nametable:
|
|
;
|
|
; First see if we need to search the name table at all (if we have ordinals
|
|
; already, we don't need to do the search).
|
|
;
|
|
xor ax,ax
|
|
cmp si,ax
|
|
jz gro_do_search_nametable
|
|
or ax,di
|
|
jnz gro_exit1 ; Both are ordinals - just exit
|
|
or ax,seg_lpszName ; If lpszName is NULL, exit because
|
|
jnz gro_do_search_nametable ; we have the type ordinal.
|
|
|
|
gro_exit1:
|
|
jmp gro_exit
|
|
|
|
gro_do_search_nametable:
|
|
cCall GetExePtr,<hResFile>
|
|
mov es,ax
|
|
mov bx,es:[ne_rsrctab]
|
|
cmp bx,es:[ne_restab]
|
|
jz gro_exit1
|
|
|
|
add bx,SIZE new_rsrc
|
|
|
|
gro_check_resource_type:
|
|
cmp es:[bx].rt_id,0
|
|
jz gro_exit1
|
|
cmp es:[bx].rt_id,(RT_NAMETABLE OR RSORDID)
|
|
jz gro_found_resource_table_entry
|
|
|
|
mov cx,es:[bx].rt_nres
|
|
add bx,SIZE RSRC_TYPEINFO
|
|
|
|
; add 12*nres to bx (12*size of resource)
|
|
|
|
.errnz ((SIZE RSRC_NAMEINFO) - 12)
|
|
|
|
shl cx,1
|
|
shl cx,1
|
|
add bx,cx
|
|
shl cx,1
|
|
add bx,cx
|
|
jmps gro_check_resource_type
|
|
|
|
|
|
gro_found_resource_table_entry:
|
|
add bx,SIZE RSRC_TYPEINFO
|
|
mov ax,es:[bx].rn_handle
|
|
or ax,ax
|
|
jnz gro_have_handle_nametable
|
|
|
|
xor ax,ax
|
|
mov dx,1
|
|
mov bx,RT_NAMETABLE
|
|
cCall <far ptr IFindResource>,<hResFile,ax,dx,ax,bx>
|
|
or ax,ax
|
|
jz gro_exit1
|
|
|
|
push ds ; DS not even really used probably
|
|
cCall MISCMapDStoDATA ; Hack, need DS pointing to something
|
|
cCall ILoadResource,<hResFile,ax> ; with a handle
|
|
pop ds
|
|
or ax,ax
|
|
jnz gro_have_handle_nametable
|
|
gro_exit2:
|
|
jmp gro_exit
|
|
|
|
gro_have_handle_nametable:
|
|
|
|
mov hRes,ax
|
|
push ds ; DS not even really used probably
|
|
cCall MISCMapDStoDATA ; Hack, need DS pointing to something
|
|
cCall ILockResource,<ax> ; with a handle
|
|
pop ds
|
|
|
|
mov cx,ax
|
|
or cx,dx
|
|
jcxz gro_exit2
|
|
|
|
mov es,dx ; es:bx is a pointer to resource
|
|
mov bx,ax
|
|
|
|
;
|
|
; Now we have a pointer to the resource. Scan through the name table and
|
|
; find a match in the table with the passed type/name.
|
|
; SI = type ordinal, 0 if string type
|
|
; DI = name ordinal, 0 if string name
|
|
;
|
|
gro_nametable_loop:
|
|
|
|
or si,si
|
|
jz gro_do_type_string_match
|
|
|
|
cmp si,es:[bx].ntbl_idType
|
|
jnz gro_next_nametable_entry
|
|
jmps gro_do_name_match
|
|
|
|
gro_do_type_string_match:
|
|
|
|
push es ; Save pntbl
|
|
push bx
|
|
|
|
lea ax,es:[bx].ntbl_achTypeName
|
|
push es
|
|
push ax
|
|
push seg_lpszType
|
|
push off_lpszType
|
|
call lstrOriginal ; compare against type name
|
|
|
|
pop bx ; Restore pntbl
|
|
pop es
|
|
|
|
or ax,ax
|
|
jnz gro_next_nametable_entry
|
|
|
|
gro_do_name_match:
|
|
|
|
or di,di
|
|
jz gro_do_name_string_match
|
|
|
|
cmp di,es:[bx].ntbl_idName
|
|
jnz gro_next_nametable_entry
|
|
jmps gro_found_nametable_match
|
|
|
|
gro_do_name_string_match:
|
|
|
|
cmp seg_lpszName, 0
|
|
jne want_name
|
|
mov si,es:[bx].ntbl_idType ; Hey man, can't check name!
|
|
jmps gro_unlock_resource
|
|
|
|
want_name:
|
|
push es ; push pntbl for later restoration
|
|
push bx
|
|
|
|
push es ; push pntbl for later strcmp
|
|
push bx
|
|
lea ax,es:[bx].ntbl_achTypeName
|
|
|
|
push es
|
|
push ax
|
|
call lstrlen ; get string length
|
|
|
|
mov bx,sp ; Adjust pointer on stack to point
|
|
add ss:[bx],ax ; past first string
|
|
add word ptr ss:[bx],ntbl_achTypeName + 1
|
|
push seg_lpszName
|
|
push off_lpszName
|
|
call lstrOriginal
|
|
|
|
pop bx
|
|
pop es
|
|
|
|
or ax,ax
|
|
jz gro_found_nametable_match
|
|
|
|
gro_next_nametable_entry:
|
|
|
|
add bx,es:[bx].ntbl_cbEntry
|
|
cmp es:[bx].ntbl_cbEntry,0
|
|
jnz gro_nametable_loop
|
|
jmps gro_unlock_resource
|
|
|
|
gro_found_nametable_match:
|
|
|
|
mov ax,es:[bx].ntbl_idType
|
|
test ax,RSORDID
|
|
jz gro_try_replace_name
|
|
mov si,ax
|
|
|
|
gro_try_replace_name:
|
|
|
|
mov ax,es:[bx].ntbl_idName
|
|
test ax,RSORDID
|
|
jz gro_unlock_resource
|
|
mov di,ax
|
|
|
|
gro_unlock_resource:
|
|
|
|
push hRes
|
|
call GlobalUnlock
|
|
|
|
gro_exit:
|
|
xor ax,ax
|
|
cwd
|
|
or ax,si
|
|
jz gro_test_name_ordinal
|
|
or ax,RSORDID
|
|
|
|
gro_test_name_ordinal:
|
|
or dx,di
|
|
jz gro_leave
|
|
or dx,RSORDID
|
|
|
|
gro_leave:
|
|
cEnd
|
|
|
|
cProc OrdinalOrString, <PUBLIC, NEAR>, <si>
|
|
parmD s
|
|
cBegin
|
|
les si,s
|
|
mov cx,si
|
|
mov ax,es
|
|
or ax,ax
|
|
jz codone
|
|
xor cx,cx ; sum = zero
|
|
cld
|
|
lods byte ptr es:[si] ; c = *pName++
|
|
cmp al,'#'
|
|
jne codone
|
|
coloop:
|
|
lods byte ptr es:[si] ; c = *pName++
|
|
or al,al ; if (!c) break;
|
|
jz codone
|
|
sub al,'0' ; if (!isdigit(c))
|
|
cmp al,9
|
|
ja codone ;
|
|
xor ah,ah
|
|
mov bx,ax ; sum = (sum * 10) + (c - '0')
|
|
mov al,10
|
|
mul cx
|
|
add ax,bx
|
|
mov cx,ax
|
|
jmp coloop
|
|
codone:
|
|
mov ax,cx
|
|
coexit:
|
|
cEnd
|
|
|
|
cProc CmpResStr,<PUBLIC,NEAR>,<ds,si>
|
|
parmD pRes
|
|
parmW id
|
|
parmD s
|
|
cBegin
|
|
mov ax,id
|
|
test ax,RSORDID
|
|
jnz crsneq
|
|
lds si,pRes
|
|
add si,ax
|
|
xor ax,ax
|
|
cld
|
|
lodsb
|
|
mov cx,ax
|
|
les bx,s
|
|
crsloop:
|
|
mov al,es:[bx]
|
|
inc bx
|
|
or al,al
|
|
jz crsneq
|
|
call FarMyUpper
|
|
mov ah,al
|
|
lodsb
|
|
cmp ah,al
|
|
jne crsneq
|
|
loop crsloop
|
|
xor ax,ax
|
|
cmp es:[bx],al
|
|
jne crsneq
|
|
not ax
|
|
jmps crsexit
|
|
crsneq:
|
|
xor ax,ax
|
|
crsexit:
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; SetResourceHandler ;
|
|
; ;
|
|
; Sets the resource handler for the given type. ;
|
|
; ;
|
|
; Note that the string pointed to can be the resource ID. In this ;
|
|
; case the string should have the form #ID. ;
|
|
; ;
|
|
; If the seg of pointer = 0, then the offset is taken as the ID. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; HANDLE hResFile ;
|
|
; char far *lpszType ;
|
|
; FARPROC lpHandler ;
|
|
; ;
|
|
; Returns: ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; GetExePtr ;
|
|
; GetResOrd ;
|
|
; CmpResStr ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Tue Jan 01, 1980 04:13:03p -by- David N. Weise [davidw] ;
|
|
; ReWrote it from C into assembly and added this nifty comment block. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc ISetResourceHandler,<PUBLIC,FAR>,<di,si>
|
|
|
|
parmW hResFile
|
|
parmD lpszType
|
|
parmD lpHandler
|
|
cBegin
|
|
cCall GetExePtr,<hResFile>
|
|
mov ds,ax ; DS = pExe
|
|
mov si,ds:[ne_rsrctab] ; DS:SI = pRes
|
|
cmp si,ds:[ne_restab]
|
|
jz srh_type_not_found ; No resources in this module!
|
|
|
|
;
|
|
; Pass the type string and NULL for the name string. AX = type ordinal, 0
|
|
; if it doesn't exist.
|
|
;
|
|
push hResFile
|
|
push seg_lpszType
|
|
push off_lpszType
|
|
xor ax,ax
|
|
push ax
|
|
push ax
|
|
call GetResOrd
|
|
|
|
lea di,[si].SIZE new_rsrc ; DS:DI = pType
|
|
srh_type_loop:
|
|
mov cx,[di].rt_id
|
|
jcxz srh_type_not_found
|
|
push ax ; typeord
|
|
or ax,ax
|
|
jz srh_compare_string
|
|
cmp ax,cx
|
|
jz srh_type_found
|
|
jmps srh_next_type
|
|
srh_compare_string:
|
|
cCall CmpResStr,<ds,si,cx,lpszType>
|
|
or ax,ax
|
|
jnz srh_type_found
|
|
srh_next_type:
|
|
mov ax,[di].rt_nres
|
|
mov cx,SIZE rsrc_nameinfo
|
|
mul cx
|
|
add ax, SIZE rsrc_typeinfo
|
|
add di,ax
|
|
pop ax
|
|
jmp srh_type_loop
|
|
|
|
srh_type_found:
|
|
pop ax ; clean stack
|
|
mov dx,word ptr lpHandler[2]
|
|
mov ax,word ptr lpHandler[0]
|
|
xchg dx,word ptr [di].rt_proc[2]
|
|
xchg ax,word ptr [di].rt_proc[0]
|
|
jmps srh_ret
|
|
|
|
srh_type_not_found:
|
|
xor ax,ax
|
|
xor dx,dx
|
|
srh_ret:
|
|
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; FindResource ;
|
|
; ;
|
|
; Returns a near pointer (into the module database) to the resource ;
|
|
; description structure. ;
|
|
; ;
|
|
; Note that the string pointed to can be the resource ID. In this ;
|
|
; case the string should have the form #ID. ;
|
|
; ;
|
|
; If the seg of pointer = 0, then the offset is taken as the ID. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; HANDLE hResFile ;
|
|
; char far *lpszName ;
|
|
; char far *lpszType ;
|
|
; ;
|
|
; Returns: ;
|
|
; AX = near pointer to resource description structure. ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; AX = 0 ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; DI,SI,DS ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; BX,CX,DX,ES ;
|
|
; ;
|
|
; Calls: ;
|
|
; GetExePtr ;
|
|
; GetResOrd ;
|
|
; CmpResStr ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Tue Jan 01, 1980 10:00:15p -by- David N. Weise [davidw] ;
|
|
; ReWrote it from C into assembly and added this nifty comment block. ;
|
|
; Wed May 31, 1989 09:17:00a -by- Scott R. Ludwig [scottlu]
|
|
; Rewrote so that string identifiers map to ordinals through an indirection
|
|
; table called a 'name table'. For OS/2 .EXE Compatibility.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc IFindResource,<PUBLIC,FAR>,<di,si>
|
|
|
|
parmW hResFile
|
|
parmD lpszName
|
|
parmD lpszType
|
|
localW typeord
|
|
localW nameord
|
|
cBegin
|
|
cCall GetExePtr,<hResFile>
|
|
mov ds,ax ; DS = pExe
|
|
mov si,ds:[ne_rsrctab] ; DS:SI = pRes
|
|
cmp si,ds:[ne_restab]
|
|
jz fr_error_ret
|
|
|
|
;
|
|
; Get resource ordinals. ax = type ordinal, dx = name ordinal. (0 if not
|
|
; ordinals).
|
|
;
|
|
cCall GetResOrd,<hResFile, lpszType, lpszName>
|
|
mov typeord,ax
|
|
mov nameord,dx
|
|
|
|
; First find the resource type.
|
|
|
|
lea di,[si].SIZE new_rsrc ; DS:DI = pType
|
|
fr_type_loop:
|
|
mov cx,[di].rt_id
|
|
jcxz fr_error_ret
|
|
mov ax,typeord
|
|
or ax,ax
|
|
jz fr_compare_type_string
|
|
cmp ax,cx
|
|
jz fr_found_type
|
|
jmps fr_next_type
|
|
fr_compare_type_string:
|
|
cCall CmpResStr,<ds,si,cx,lpszType>
|
|
or ax,ax
|
|
jnz fr_found_type
|
|
fr_next_type:
|
|
mov ax,[di].rt_nres
|
|
mov cx,SIZE rsrc_nameinfo
|
|
mul cx
|
|
add ax,SIZE rsrc_typeinfo
|
|
add di,ax
|
|
jmp fr_type_loop
|
|
fr_found_type:
|
|
|
|
; Now find the resource name.
|
|
|
|
mov cx,[di].rt_nres
|
|
lea di,[di].SIZE rsrc_typeinfo ; DS:DI = pName
|
|
fr_name_loop:
|
|
mov bx,nameord
|
|
or bx,bx
|
|
mov ax,[di].rn_id
|
|
jz fr_compare_name_string
|
|
cmp ax,bx
|
|
jz fr_found_name
|
|
jmps fr_next_name
|
|
fr_compare_name_string:
|
|
push cx
|
|
cCall CmpResStr,<ds,si,ax,lpszName>
|
|
pop cx
|
|
or ax,ax
|
|
jnz fr_found_name
|
|
fr_next_name:
|
|
add di,SIZE rsrc_nameinfo
|
|
loop fr_name_loop
|
|
fr_error_ret:
|
|
xor ax,ax
|
|
jmps fr_ret
|
|
|
|
fr_found_name:
|
|
mov ax,di
|
|
fr_ret:
|
|
cEnd
|
|
|
|
sEnd MISCCODE
|
|
|
|
|
|
sBegin NRESCODE
|
|
assumes CS,NRESCODE
|
|
assumes DS,NOTHING
|
|
assumes ES,NOTHING
|
|
|
|
|
|
cProc PreloadResources,<PUBLIC,NEAR>,<si,di>
|
|
parmW hExe
|
|
parmW fh
|
|
parmW hBlock
|
|
parmD FileOffset
|
|
ifdef WOW_OPTIMIZE_PRELOADRESOURCE
|
|
localW hiResOffset
|
|
localW loResOffset
|
|
endif
|
|
|
|
cBegin
|
|
mov es,hExe
|
|
xor bx,bx
|
|
mov si,es:[bx].ne_rsrctab
|
|
cmp es:[bx].ne_restab,si
|
|
jne prnotdone
|
|
prdonej:
|
|
jmp prdone
|
|
prnextj:
|
|
jmp prnext
|
|
|
|
prnotdone:
|
|
mov di,es:[si].rs_align
|
|
add si,SIZE new_rsrc
|
|
prtype:
|
|
cmp es:[si].rt_id,0
|
|
je prdonej
|
|
mov cx,es:[si].rt_nres
|
|
mov word ptr es:[si].rt_proc[0],codeOffset DefaultResourceHandler
|
|
mov word ptr es:[si].rt_proc[2],codeBase
|
|
add si,SIZE rsrc_typeinfo
|
|
prname:
|
|
push cx
|
|
mov ax,es:[si].rn_flags
|
|
; cmp word ptr es:[ne_ver],4 ; Produced by version 4.0 LINK?
|
|
; ja prname2
|
|
; test ah,0Fh ; Is old discard field set?
|
|
; jz prname1
|
|
; or ax,RNDISCARD ; Yes, convert to bit
|
|
;prname1:
|
|
; and ax,not RNUNUSED ; Clear unused bits in 4.0 LINK files
|
|
prname2:
|
|
or ax,NENOTP
|
|
errnz <NENOTP - 8000h>
|
|
test es:[ne_flags],NENOTP
|
|
jnz prname4 ; Mark as EMSable if resource belongs
|
|
xor ax,NENOTP ; to a task.
|
|
prname4:
|
|
mov es:[si].rn_flags,ax
|
|
test al,RNPRELOAD
|
|
jz prnextj
|
|
|
|
mov cx, seg_FileOffset
|
|
or cx, off_FileOffset
|
|
jcxz PL_file
|
|
|
|
cmp di, 4 ; Must be at least paragraph aligned
|
|
jb PL_file
|
|
|
|
push es
|
|
cCall GlobalLock,<hBlock>
|
|
ifdef WOW_OPTIMIZE_PRELOADRESOURCE
|
|
mov ax,dx ; no need to alloc a selector. we will use the
|
|
; the current one.
|
|
if KDEBUG
|
|
or ax, ax
|
|
jnz @F
|
|
int 3 ; // should never happen
|
|
@@:
|
|
endif
|
|
|
|
else
|
|
cCall AllocSelector,<dx>
|
|
endif
|
|
|
|
pop es
|
|
mov bx,es:[si].rn_offset
|
|
xor dx,dx
|
|
mov cx,di
|
|
PL_shift:
|
|
shl bx,1
|
|
rcl dx,1
|
|
loop PL_shift
|
|
|
|
sub bx, off_FileOffset
|
|
sbb dx, seg_FileOffset
|
|
ifdef WOW_OPTIMIZE_PRELOADRESOURCE
|
|
; call to longptraddwow basically is a nop. it doesn't set the
|
|
; descriptor. it is called 'cause it sets some registers.
|
|
|
|
mov hiResOffset, dx
|
|
mov loResOffset, bx
|
|
push ax
|
|
push es
|
|
cCall LongPtrAddWOW,<ax,cx,dx,bx, 0, 0> ; (cx is 0)
|
|
pop es
|
|
dec cx
|
|
cCall ResAlloc,<essi,dx,cx, hiResOffset, loResOffset>
|
|
pop cx
|
|
push ax
|
|
else
|
|
push ax
|
|
push es
|
|
cCall LongPtrAdd,<ax,cx,dx,bx> ; (cx is 0)
|
|
pop es
|
|
dec cx
|
|
cCall ResAlloc,<essi,dx,cx, 0, 0>
|
|
pop cx
|
|
push ax
|
|
cCall FreeSelector,<cx>
|
|
endif
|
|
cCall GlobalUnlock,<hBlock>
|
|
pop ax
|
|
jmps PL_loaded
|
|
|
|
PL_file:
|
|
mov dx,es:[si].rn_offset
|
|
xor ax,ax
|
|
mov cx,di
|
|
PL_shift1:
|
|
shl dx,1
|
|
rcl ax,1
|
|
loop PL_shift1
|
|
mov cx,ax
|
|
mov ax,4200h
|
|
mov bx,fh
|
|
DOSFCALL
|
|
ifdef WOW_OPTIMIZE_PRELOADRESOURCE
|
|
cCall ResAlloc,<essi,bx,bx, 0, 0>
|
|
else
|
|
cCall ResAlloc,<essi,bx,bx>
|
|
endif
|
|
|
|
PL_loaded:
|
|
mov es,hExe
|
|
mov es:[si].rn_handle,ax
|
|
prnext:
|
|
pop cx
|
|
add si,SIZE rsrc_nameinfo
|
|
dec cx
|
|
jz prtypej
|
|
jmp prname
|
|
prtypej:
|
|
jmp prtype
|
|
prdone:
|
|
cEnd
|
|
|
|
sEnd NRESCODE
|
|
|
|
end
|