Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

195 lines
4.3 KiB

;;--------------------------------------------------------------------
;;
;; Microsoft OS/2 LAN Manager
;; Copyright(c) Microsoft Corp., 1990
;;
;;------------------------------------------------------------------
;;
;;Description :
;; Demand load functions into a DOS psuedo DLL.
;;
;;History :
;;
;;stevez 03-23-92 First bits into the bucket.
;;
;; jroberts 06-05-94 If LoadDll fails, it returns
;; rpc_s_name_service_unavailable
.model large, c
TableSegment segment word public 'data'
FunctionNames label dword
TableSegment ends
dgroup group TableSegment
.data
hModule dd 0
.code
LoadModR proto moduleName:ptr byte, handle:ptr dword
CallExportInit proto handle:dword
GetProcAddrR proto handle:dword, FunctionName:ptr byte, Address:ptr dword
UnloadModR proto handle:dword
iFunctionCurrent = 0
; The following macro creates a function thunk, a entry
; in the function table of pointers and a entry in the
; table of function names.
ExportFunction macro FunctionName:req, ArgWordCount:req
local StringName
; A thunk is simply a jump indirect through a table.
; AX is loaded with enough information to demand load the
; table entry if the dll hasn't been loaded.
FunctionName proc Pascal
mov ax, iFunctionCurrent*4 + (ArgWordCount*2 shl 8)
jmp FunctionTable[iFunctionCurrent*4]
FunctionName endp
; Create a string for the function name and a pointer to that
; string in the TableSegment.
.data
StringName db "&FunctionName", 0
@CurSeg ends
TableSegment segment word public 'data'
dd StringName
TableSegment ends
.code
iFunctionCurrent = iFunctionCurrent + 1
endm
ModuleName macro ModName, extension:=<.rpc>
.data
FunctionMax dw iFunctionCurrent*4
DllName db "&ModName&&extension", 0
; This is the vector of funtion pointers used to call indirect with.
; The table is initialized to point the the routine which demand loads
; all the entrys in the table.
FunctionTable dd iFunctionCurrent dup (LoadDLL)
.code
; The following function unloads the DLL.
ModName&Discard proc public uses di
; First, reset the table to the load function.
mov ax, word ptr hModule
or ax, word ptr hModule+2
jz Done
mov ax, offset LoadDLL
mov bx, cs
push ds
pop es
mov di, offset FunctionTable
mov cx, iFunctionCurrent
.repeat
stosw
xchg ax,bx
stosw
xchg ax,bx
.untilcxz
; Free the memory allocated by this DLL.
invoke UnloadModR, hModule
mov word ptr hModule,0
mov word ptr hModule+2,0
Done:
ret
ModName&Discard endp
.data
ErrorExit dd ?
.code
LoadDLL proc private uses si
push ax ; save the function ordinal
; First, open up the DLL module.
invoke LoadModR, Addr DllName, Addr hModule
.if ax
ErrorReturn:
mov ax, 80 ; rpc_s_name_service_unavailable
pop bx ;Bx = number of argumnets to call
xchg bh,bl
xor bh,bh
pop si ; restore the registers
; Since this is a pascal function we must fix up the stack
; on return, do this by poping the return into a static,
; adjusting the stack and then jumping to the return.
pop word ptr ErrorExit
pop word ptr ErrorExit+2
add sp, bx
jmp [ErrorExit]
.endif
invoke CallExportInit, hModule
; For each function, look up the address in the DLL.
xor si,si
.while (si < FunctionMax)
mov ax,offset FunctionTable
add ax,si
invoke GetProcAddrR, hModule, FunctionNames[si], ds::ax
or ax,ax
jnz ErrorReturn
add si,4
.endw
; All the function pointers have been fixed up. Now
; jump to the function now that we have the address
pop bx ; Function ordinal in Bx
xor bh,bh
pop si ; Restore registers
; jump to function with stack adjusted just like a normal call.
jmp FunctionTable[Bx]
LoadDLL endp
end
endm