525 lines
11 KiB
NASM
525 lines
11 KiB
NASM
page ,132
|
||
title OLE2STUB.ASM
|
||
;***********************************************************************
|
||
;* *
|
||
;* MODULE : OLE2STUB.ASM *
|
||
;* *
|
||
;* DESCRIPTION : Provide functions to allow run-time linking to *
|
||
;* the ACM. *
|
||
;* *
|
||
;* COPYRIGHT : Copyright 1991, Microsoft Corp. All Rights Reserved.*
|
||
;* *
|
||
;* Author: David Maymudes *
|
||
;* Based on similar code for MMSYSTEM by: *
|
||
;* Todd Laney and Matt Saettler - Multimedia Systems *
|
||
;* *
|
||
;***********************************************************************
|
||
|
||
;-----------------------------------------------------------------------
|
||
;
|
||
; Documentation (such as it is)
|
||
;
|
||
;------------------------------------------------------------------------
|
||
;
|
||
; Call function as you normally would. Include OLE2.H normally.
|
||
; However, instead of linking to OLE2.LIB, link to OLE2STUB.OBJ
|
||
;
|
||
; All functions will return error conditions if OLE2.DLL is not present.
|
||
;
|
||
; Because I'm lazy, the calling routine has to load the module into
|
||
; memory before calling any of this.
|
||
;------------------------------------------------------------------------
|
||
|
||
page
|
||
|
||
.286
|
||
?PLM=1 ; PASCAL Calling convention is DEFAULT
|
||
?WIN=0 ; Windows calling convention
|
||
|
||
.xlist
|
||
include cmacros.inc
|
||
.list
|
||
|
||
;*********************************************************************
|
||
; CONSTANT DECLARATIONS
|
||
;*********************************************************************
|
||
|
||
ifndef FALSE
|
||
FALSE equ 0
|
||
endif
|
||
ifndef NULL
|
||
NULL equ 0
|
||
endif
|
||
ifndef MMSYSERR_ERROR
|
||
MMSYSERR_ERROR equ 1
|
||
endif
|
||
|
||
;*********************************************************************
|
||
; EXTERN DECLARATIONS
|
||
;*********************************************************************
|
||
|
||
externFP OutputDebugString
|
||
externFP _wsprintf
|
||
externFP GetProcAddress
|
||
externFP GetModuleHandle
|
||
|
||
;ifdef DEBUG
|
||
; externFP __dprintf ; in DPRINTF.C
|
||
;endif
|
||
|
||
;*********************************************************************
|
||
; STRUCTURE DECLARATIONS
|
||
;*********************************************************************
|
||
|
||
LONG struc
|
||
lo dw ?
|
||
hi dw ?
|
||
LONG ends
|
||
|
||
FARPOINTER struc
|
||
off dw ?
|
||
sel dw ?
|
||
FARPOINTER ends
|
||
|
||
PROCENTRY struc
|
||
curproc dd ? ; see parameters to macros, below
|
||
ordinal dw ?
|
||
numparms dw ?
|
||
errret dd ?
|
||
|
||
ifdef DEBUG
|
||
szProc db ?
|
||
endif
|
||
PROCENTRY ends
|
||
|
||
MODENTRY struc
|
||
hModule dw ?
|
||
szModule db ?
|
||
MODENTRY ends
|
||
|
||
;*********************************************************************
|
||
; DATA SEGMENT DECLARATIONS
|
||
;*********************************************************************
|
||
|
||
ifndef SEGNAME
|
||
SEGNAME equ <_TEXT>
|
||
endif
|
||
|
||
createSeg %SEGNAME, CodeSeg, word, public, CODE
|
||
|
||
page
|
||
|
||
;*********************************************************************
|
||
; MACRO DECLARATIONS
|
||
;*********************************************************************
|
||
|
||
;
|
||
;------------------------------------------------------------------------------
|
||
;
|
||
; MACRO DOUT
|
||
;
|
||
; Parms:
|
||
;
|
||
; text Text to output using OutputDebugString when DEBUG is defined
|
||
; Text is automatically appended with CR/LF
|
||
;
|
||
|
||
DOUT macro text
|
||
local string_buffer
|
||
|
||
ifdef DEBUG ; only do output if DEBUG is defined
|
||
|
||
_DATA segment
|
||
string_buffer label byte
|
||
db "&text&",13,10,0
|
||
_DATA ends
|
||
pusha
|
||
push DataBASE
|
||
push DataOFFSET string_buffer
|
||
call OutputDebugString
|
||
popa
|
||
endif
|
||
endm
|
||
|
||
;
|
||
;------------------------------------------------------------------------------
|
||
;
|
||
; MACRO Begin_Module_Table
|
||
;
|
||
; Parms:
|
||
;
|
||
; Module_Name Name of Module to Run-Time-Link
|
||
;
|
||
; defines <Module_Name>_Proc Macro
|
||
;
|
||
; Use End_Module_Table to close
|
||
|
||
Begin_Module_Table MACRO Module_Name
|
||
|
||
sBegin DATA
|
||
|
||
ifdef DEBUG
|
||
public Module_Name&_Module_Table
|
||
endif
|
||
|
||
Module_Name&_Module_Table label word
|
||
dw -1 ; hModule
|
||
db "&Module_Name&",0
|
||
|
||
sEnd Data
|
||
|
||
sBegin CodeSeg
|
||
assumes cs,CodeSeg
|
||
assumes ds,Data
|
||
assumes es,nothing
|
||
|
||
ifdef DEBUG ; make public so debugger is aware of it
|
||
public load&Module_Name
|
||
endif
|
||
|
||
;
|
||
; entry:
|
||
; DS:BX --> ProcEntry for API being called
|
||
;
|
||
load&Module_Name& proc far
|
||
; stack frame is not modified or copied
|
||
; vars are still in place
|
||
|
||
mov ax,DataOFFSET Module_Name&_Module_Table
|
||
jmp LoadModuleStub
|
||
|
||
load&Module_Name& endp
|
||
|
||
sEnd CodeSeg
|
||
|
||
page
|
||
|
||
;
|
||
;------------------------------------------------------------------------------
|
||
;
|
||
; MACRO <Module_Name>_Proc
|
||
;
|
||
; Parms:
|
||
;
|
||
; Name of procedure Name of procedure to emulate
|
||
; ordinal of exported proc
|
||
; # of stack parms use 0 for CDECL routines
|
||
; error return value default error value for use by FailAPIStub
|
||
; fail proc defaults to FailAPIStub if not specified
|
||
; use custom 'fail' proc to replace functionlity
|
||
; if specified module/proc not found in system
|
||
;
|
||
Module_Name&_Proc macro ProcName, Ordinal, sizestack, errret, failproc
|
||
|
||
sBegin Data
|
||
|
||
ifdef DEBUG
|
||
public Module_Name&&Ordinal&
|
||
endif
|
||
|
||
Module_Name&&Ordinal& label word
|
||
ifb <failproc>
|
||
dd load&Module_Name
|
||
dw &Ordinal
|
||
dw &sizestack
|
||
dd &errret
|
||
else
|
||
dd load&Module_Name
|
||
dw &Ordinal
|
||
dw -1
|
||
dd &failproc
|
||
endif
|
||
|
||
ifdef DEBUG
|
||
db "&ProcName&",0
|
||
endif
|
||
|
||
sEnd Data
|
||
|
||
sBegin CodeSeg
|
||
assumes cs,CodeSeg
|
||
assumes ds,Data
|
||
assumes es,nothing
|
||
|
||
public &ProcName&
|
||
|
||
&ProcName& proc far
|
||
; stack frame is not modified or copied
|
||
; vars are still in place
|
||
|
||
mov bx,DataOFFSET Module_Name&&Ordinal&
|
||
jmp [bx].curproc ; current proc
|
||
|
||
&ProcName& endp
|
||
|
||
sEnd CodeSeg
|
||
|
||
endm
|
||
endm
|
||
|
||
page
|
||
;------------------------------------------------------------------------------
|
||
;
|
||
; MACRO End_Module_Table
|
||
;
|
||
; Parms
|
||
; Module_Name Must be the same as in Begin_Module_Table
|
||
;
|
||
|
||
End_Module_Table macro Module_Name
|
||
|
||
purge Module_Name&_Proc
|
||
|
||
endm
|
||
|
||
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; Helper routines for SHELL
|
||
;
|
||
;-----------------------------------------------------------------------------
|
||
sBegin CodeSeg
|
||
assumes cs,CodeSeg
|
||
assumes ds,Data
|
||
assumes es,nothing
|
||
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; FailApiStub
|
||
;
|
||
; Default handler if Module or Proc Address is not found.
|
||
;
|
||
; returns default error code
|
||
;
|
||
; entry:
|
||
; DS:BX --> PROCENTRY
|
||
;
|
||
|
||
FailApiStub proc far
|
||
|
||
pop dx ; get return addr
|
||
pop ax
|
||
|
||
add sp,[bx].numparms ; remove params from stack
|
||
|
||
push ax ; restore return addr
|
||
push dx
|
||
mov ax,[bx].errret.lo ; return fail code
|
||
mov dx,[bx].errret.hi
|
||
retf
|
||
|
||
FailApiStub endp
|
||
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; LoadModuleStub
|
||
;
|
||
; Initial handler for all procs. Attempts to load module (if not already
|
||
; loaded) and then gets proc address. If any errors, sets curproc to
|
||
; failproc for 'unavailable' processing.
|
||
;
|
||
; If successful, then sets curproc to imported function and calls it.
|
||
;
|
||
; entry:
|
||
; DS:BX --> PROCENTRY
|
||
; DS:AX --> MODENTRY
|
||
;
|
||
; NOTE: Assumes module is already loaded
|
||
;
|
||
; To be totally general:
|
||
; if can't GetModuleHandle(),
|
||
; needs to do a OpenFile(OF_EXIST,...) + LoadLibrary()
|
||
; needs to FreeLibrary() all DLLs at end/exit
|
||
;
|
||
LoadModuleStub proc far
|
||
|
||
ifdef DEBUG
|
||
pusha
|
||
sub sp,128
|
||
mov si,sp
|
||
|
||
mov di,ax ; DS:DI --> MODENTRY
|
||
|
||
push [bx].ordinal ; %d
|
||
|
||
lea ax,[bx].szProc ; %ls
|
||
push ds
|
||
push ax
|
||
|
||
lea ax,[di].szModule ; %ls
|
||
push ds
|
||
push ax
|
||
|
||
lea ax,format_string ; format string
|
||
push cs
|
||
push ax
|
||
|
||
push ss ; buffer
|
||
push si
|
||
call _wsprintf
|
||
add sp,9*2 ; clear 9 words
|
||
|
||
cCall OutputDebugString,<ss,si>
|
||
|
||
add sp,128
|
||
popa
|
||
jmp short @f
|
||
format_string:
|
||
db "Linking %ls!%ls@%d",13,10,0
|
||
@@:
|
||
endif
|
||
pusha
|
||
|
||
mov si,ax ; ds:[si] --> MODENTRY
|
||
mov di,bx ; ds:[di] --> PROCENTRY
|
||
|
||
mov ax,[si].hModule
|
||
or ax,ax
|
||
jz LoadModuleStubFail ; module does not exist
|
||
|
||
cmp ax,-1
|
||
jne LoadModuleStubGetProc
|
||
|
||
lea ax,[si].szModule
|
||
cCall GetModuleHandle, <ds,ax>
|
||
mov [si].hModule,ax
|
||
or ax,ax
|
||
jz LoadModuleStubLoad
|
||
|
||
LoadModuleStubGetProc:
|
||
cCall GetProcAddress,<ax,0,[di].ordinal>
|
||
or dx,dx
|
||
jz LoadModuleStubFail
|
||
|
||
LoadModuleStubDone:
|
||
mov [di].curproc.lo,ax
|
||
mov [di].curproc.hi,dx
|
||
|
||
popa
|
||
jmp [bx].curproc
|
||
|
||
LoadModuleStubLoad:
|
||
|
||
;; call load library here after verifying with OpenFile()
|
||
;
|
||
|
||
; for now, fall through to error
|
||
|
||
LoadModuleStubFail:
|
||
DOUT <*** API not found! ***>
|
||
|
||
mov ax,CodeSegOFFSET FailApiStub
|
||
mov dx,cs
|
||
|
||
cmp [di].numparms,-1 ; do we have a fail proc?
|
||
jne LoadModuleStubDone ; no...use FailApiStub
|
||
|
||
mov ax,[di].errret.lo ; yes..it is stored in errret
|
||
mov dx,[di].errret.hi
|
||
jmp short LoadModuleStubDone ; use it
|
||
|
||
LoadModuleStub endp
|
||
|
||
sEnd CodeSeg
|
||
|
||
page
|
||
;*********************************************************************
|
||
; CODE and DATA
|
||
;*********************************************************************
|
||
|
||
|
||
;
|
||
; Define OLE2 Run-Time-Load Table
|
||
|
||
Begin_Module_Table OLE2
|
||
|
||
OLE2_Proc OleInitialize 2, 4, 8000ffffh
|
||
OLE2_Proc OleUninitialize 3, 0, 8000ffffh
|
||
OLE2_Proc ReleaseStgMedium 32, 4, 8000ffffh
|
||
OLE2_Proc OleSetClipboard 49, 4, 8000ffffh
|
||
OLE2_Proc OleGetClipboard 50, 4, 8000ffffh
|
||
OLE2_Proc OleFlushClipboard 76, 0, 8000ffffh
|
||
|
||
;
|
||
; end the OLE2 R-T-L table
|
||
|
||
End_Module_Table OLE2
|
||
|
||
;*********************************************************************
|
||
; STUB ROUTINES
|
||
;*********************************************************************
|
||
|
||
; no stub routines for OLE2.
|
||
|
||
|
||
;*********************************************************************
|
||
; 'C' RUNTIME HACK
|
||
;*********************************************************************
|
||
|
||
if 0 ;--- dont want this for nt
|
||
|
||
sBegin Code
|
||
assumes cs,Code
|
||
assumes ds,nothing
|
||
assumes es,nothing
|
||
|
||
externFP GlobalAlloc
|
||
externFP GlobalLock
|
||
externFP GlobalFree
|
||
|
||
.386
|
||
|
||
;
|
||
; stutpid hack to get GetDGOUP to work!!!
|
||
;
|
||
public ___ExportedStub
|
||
___ExportedStub:
|
||
mov ax,DataBASE
|
||
|
||
|
||
|
||
%out ***************** WHY IS THE C RUNTIME BROKEN???
|
||
|
||
|
||
GMEM_MOVEABLE equ 0002h
|
||
|
||
public __fmalloc
|
||
|
||
__fmalloc proc far
|
||
|
||
pop eax
|
||
pop bx
|
||
push bx
|
||
push eax
|
||
|
||
GMEM_SHARE equ 2000h
|
||
GMEM_MOVEABLE equ 0002h
|
||
|
||
cCall GlobalAlloc, <GMEM_MOVEABLE+GMEM_SHARE, 0, bx>
|
||
cCall GlobalLock, <ax>
|
||
|
||
retf
|
||
|
||
__fmalloc endp
|
||
|
||
public __ffree
|
||
|
||
__ffree proc far
|
||
|
||
pop eax ; return addr
|
||
pop ebx ; sel:off
|
||
push ebx
|
||
push eax
|
||
|
||
shr ebx,16
|
||
cCall GlobalFree, <bx>
|
||
retf
|
||
|
||
__ffree endp
|
||
|
||
sEnd
|
||
|
||
endif
|
||
|
||
end
|
||
|