home *** CD-ROM | disk | FTP | other *** search
- ;-----------------------------------------------------------------------------
- ;
- ; SAMPLE code for WINMEM32 DLL
- ;
- ;-----------------------------------------------------------------------------
-
- .386p
-
- memS equ 1
-
- .xlist
-
- include cmacros.inc
- ;
- ; NOTE that we CANNOT use the normal CMACROS segment macros:
- ;
- ; CreateSeg
- ; sBegin
- ; sEnd
- ;
- ; because since we are .386p the default segment type is USE32. Our segments
- ; need to be USE16 so we have to declare our segements manually so that the
- ; USE16 segment attribute is included.
- ;
- include windows.inc
-
- .list
- ;
- ; These equates would normally be in an app specific include file
- ;
- error_bad_file EQU 08001h
- error_wrong_mode EQU 08002h
-
- ;-----------------------------------------------------------------------------
- ;
- ; External WINMEM32 Procedures
- ;
- externFP GetWinMem32Version
- externFP Global32Alloc
- externFP Global32Realloc
- externFP Global32Free
- externFP Global16PointerAlloc
- externFP Global16PointerFree
- externFP Global32CodeAlias
- externFP Global32CodeAliasFree
-
- ;-----------------------------------------------------------------------------
- ;
- ; External Windows Procedures
- ;
- externFP OpenFile
- externFP GetWinFlags
- externFP _llseek
- externFP _lread
- externFP _lclose
- externFP OemToAnsi
-
- ;
- ; MANUAL VERSION OF: createSeg _HELPERCODE,hcode,word,public,CODE
- ;
- ; NOTE that this segment MUST NOT BE DISCARDABLE, it should be fixed.
- ; This is because the segment is called by USE32 code.
- ;
- _HELPERCODE segment word public 'CODE' use16
- _HELPERCODE ends
-
- ;
- ; MANUAL VERSION of the automatic data segment declaration
- ;
- _DATA segment word public 'DATA' use16
- _DATA ends
-
- _DATA segment use16
-
- globalD AddrOEMToANSI,0 ; Address of OEMToANSI helper function
- globalD AddrDOSGetFreeSpace,0 ; Address of DOS Get disk Free space
- ; helper function
- globalD U32RetVal,0 ; Return code from USE32 call
-
- globalD U16StackAlias,0 ; Alias for the stack
-
- globalD EntryStackSave,0 ; stack ptr save location
-
- ;
- ; This FWORD forms the entry point for the USE32 code
- ;
- U32EntryPt LABEL FWORD
- globalD U32EntOff,00010000h ; Entry assumed at offset 64K
- globalW U32CodeSel,0 ; CODE alias for the BIG object
-
- globalW U32DataSel,0 ; DATA selector for the BIG object
-
- _DATA ends
-
- _HELPERCODE segment use16
- assume cs:_HELPERCODE
-
- ;*****************************************************************************
- ;
- ; SetupCallUSE32
- ;
- ; SetupCallUSE32(fName)
- ;
- ; Setup and call into USE32 code
- ;
- ; ASSUMPTIONS:
- ; The USE32 Image is a 0 ORGed 32 bit code image with NO HEADER.
- ; The first 64k of the image (offsets 00000000-0000FFFFh) is reserved
- ; for the stack. We put the stack here so that the required stack
- ; switching (USE32<->USE16) is simply a matter of changing SS.
- ;
- ; The entry point of the USE32 code is assumed to be right after the
- ; stack at offset 00010000h in the image. We enter with DS, FS, GS
- ; and SS set to the FLAT data segment, and CS set to the flat code
- ; segment. It is the responsibility of the USE32 entry point to set
- ; ES AND PRESERVE IT FOR US.
- ;
- ; When this code wishes to call the two provided USE16 helper routines,
- ; it looks up the call addresses in the AddrOEMToANSI and
- ; AddrDOSGetFreeSpace variables in the _DATA segment.
- ; This "loader" code actually needs to pass the selector for the
- ; _DATA segment to the USE32 code so that it can access the data
- ; segment, or it needs to copy the call addresses into the USE32
- ; code/data segment. This detail of the implementation is NOT
- ; included in this code.
- ;
- ; ENTRY:
- ; FName - DWORD pointer to file name of USE32 image to load
- ;
- ; EXIT:
- ; AX != 0 If an error occurs
- ; AX = error code
- ; Else
- ; AX = 0 and U32RetVal contains the return code from the
- ; USE32 code.
- ; USES:
- ; C Standard
- ;
- ;*****************************************************************************
- cProc StartupCallUSE32,<FAR,PUBLIC>,<si,di>
-
- ParmD fName
-
- LocalD fSize ; Size of file
- LocalD U16RdAlias ; Alias for reading image
- LocalD FileOff ; Current file offset for read
- LocalW fHand ; File handle
- LocalV OpnBuf,<SIZE OPENSTRUC> ; Open file struct for openfile call
-
- cBegin
- assume ds:_DATA
- assume es:nothing
- assume ss:_DATA
- ;
- ; First check if we are running in enhanced mode
- ;
- ; NOTE THAT SINCE WE DO NOT KNOW AS YET WHAT MODE WE ARE IN WE NEED
- ; TO AVOID USING 386 SPECIFIC INSTRUCTIONS
- ;
- cCall GetWinFlags
-
- and ax,WF_PMODE + WF_ENHANCED
- cmp ax,WF_PMODE + WF_ENHANCED
- je short OKtoLoad ; MUST BE SHORT
- mov ax,error_wrong_mode
- jmp Done1
-
- ;
- ; We now know we are in the proper mode and that 386 instructions
- ; are now OK.
- ;
- OKtoLoad:
- ;
- ; Set up the addresses for the USE32 code to call the helper routines
- ;
- mov ax,cs
- mov word ptr [AddrOEMToANSI+2],ax
- mov word ptr [AddrOEMToANSI],offset _HELPERCODE:U32OEMtoANSI
- mov word ptr [AddrDOSGetFreeSpace+2],ax
- mov word ptr [AddrDOSGetFreeSpace],offset _HELPERCODE:U32GetDskFree
- ;
- ; Open the file
- ;
- lea bx,OpnBuf
- regptr ssbx,ss,bx
- cCall OpenFile,<fName,ssbx,OF_READ>
- cmp ax,-1 ; Did we find it?
- je Done1FlErr ; No, file error
- mov fHand,ax ; Save file handle
- ;
- ; Get file size
- ;
- cCall _llseek,<fHand,0,0,2>
- shl edx,16
- mov dx,ax
- inc edx
- jz Done1FlErr ; seek failed, file error
- dec edx
- mov fSize,edx
- cmp edx,10000h ; Image is at least 64k?
- jbe Done1FlErr ; No, size is too small, file error
- ;
- ; Move file pointer back to start of file for read
- ;
- cCall _llseek,<fHand,0,0,0>
- ;
- ; Allocate big USE32 object
- ;
- mov si,dataOffset U32DataSel
- regptr Selpt,ds,si
- cCall Global32Alloc,<fSize,Selpt,fSize,0>
- or ax,ax ; Worked?
- jnz FcloseEr ; No, return WINMEM32 error code
- ;
- ; Allocate USE16 stack alias for first 64K of object
- ;
- mov si,dataOffset U16StackAlias
- regptr Alipt,ds,si
- mov ecx,00010000h ; 64K
- cCall Global16PointerAlloc,<[U32DataSel],0,0,Alipt,ecx,0>
- or ax,ax ; Worked?
- jnz AliasErrF3 ; No, return WINMEM32 error code
- ;
- ; Allocate USE32 code alias
- ;
- mov si,dataOffset U32CodeSel
- regptr Alipt,ds,si
- cCall Global32CodeAlias,<[U32DataSel],Alipt,0>
- or ax,ax ; Worked?
- jnz AliasErrF2 ; No, return WINMEM32 error code
- ;
- ; Now read in the image. We will do this in 32K hunks.
- ;
- mov FileOff,0 ; Starting at file offset 0
- ReadLp:
- mov ecx,00008000h ; 32k
- cmp ecx,fSize
- jbe short Read32k
- mov ecx,fSize
- Read32k:
- ;
- ; Make a USE16 alias for this region of the object
- ;
- push ecx
- lea si,U16RdAlias
- regptr Alipt,ss,si
- cCall Global16PointerAlloc,<[U32DataSel],FileOff,Alipt,ecx,0>
- pop ecx
- or ax,ax
- jnz short AliasErrF1
- push ecx
- cCall _lread,<fHand,U16RdAlias,cx>
- push ax
- cCall Global16PointerFree,<[U32DataSel],U16RdAlias,0>
- pop ax
- pop ecx
- inc ax
- jz short FlRdErr
- dec ax
- cmp ax,cx
- jne short FlRdErr
- add FileOff,ecx
- sub fSize,ecx
- ja short ReadLp
-
- ;
- ; We are now ready to set up and call into the USE32 code
- ;
- ; Save the current stack so we can switch to the USE32 stack
- ;
- ; NOTE CAREFULLY THAT THIS MAKES THIS ROUTINE NON-REENTRANT
- ; SINCE IT SAVES THE CURRENT SS:SP IN A STATIC MEMORY LOCATION.
- ;
- mov word ptr [EntryStackSave],sp
- mov word ptr [EntryStackSave+2],ss
- mov ax,[U32DataSel]
- push ds
- pop es
- assume es:_DATA
- ;
- ; Set up all the segs, and call into USE32
- ;
- ; NOTE that we just leave the file open across the call.
- ;
- mov ds,ax
- assume ds:nothing
- mov fs,ax
- mov gs,ax
- mov ss,ax
- assume ss:nothing
- mov esp,0000FFFCh
- call [U32EntryPt]
- ;
- ; Recover DS and stack.
- ;
- mov bx,es
- mov ds,bx
- assume ds:_DATA
- mov ss,word ptr [EntryStackSave+2]
- assume ss:_DATA
- mov sp,word ptr [EntryStackSave]
- ;
- ; Set success return and clean up.
- ;
- mov [U32RetVal],eax
- xor ax,ax ; Return success
- jmp short AliasErrF1
-
- FlRdErr:
- mov ax,error_bad_file
- AliasErrF1:
- ;
- ; Free USE32 code alias
- ;
- push ax ; Save error code
- cCall Global32CodeAliasFree,<[U32DataSel],[U32CodeSel],0>
- pop ax
- AliasErrF2:
- ;
- ; Free USE16 stack alias
- ;
- push ax ; Save error code
- cCall Global16PointerFree,<[U32DataSel],[U16StackAlias],0>
- pop ax
- AliasErrF3:
- ;
- ; Free the object
- ;
- push ax ; Save error code
- cCall Global32Free,<[U32DataSel],0>
- pop ax
- FcloseEr:
- ;
- ; Close the file
- ;
- push ax ; Save error code
- cCall _lclose,<fHand>
- pop ax
- jmp short Done1
-
- Done1FlErr:
- mov ax,error_bad_file
- Done1:
- cEnd
-
- ;*****************************************************************************
- ;
- ; U32OEMtoANSI - Call OemToANSI from USE32 segment
- ;
- ; Assumes PASCAL calling convention
- ;
- ; ENTRY:
- ; U32OEMtoANSI(lpOemStr,lpAnsiStr)
- ;
- ; NOTE that these pointer arguments are NOT really LPSTRs. They
- ; are near pointers into the USE32 data object (implied segment
- ; is U32DataSel)
- ;
- ; EXIT:
- ; EAX is return code
- ;
- ; USES:
- ; 32 bit C Standard
- ;
- ;
- ;*****************************************************************************
- PUBLIC U32OEMtoANSI
-
- U32OEMtoANSI proc far
- assume ds:nothing
- assume es:nothing
- assume ss:nothing
- ;
- ; First switch to the USE16 stack
- ;
- mov cx,ds ; Save entry DS in cx till we get the
- stack switched
- mov ax,SEG _DATA
- mov ds,ax
- assume ds:_DATA
- mov ss,word ptr [U16StackAlias+2]
- push ecx ; Entry DS, as DWORD to keep stack aligned
- push ebp
- mov bp,sp
- ;
- ; Frame now looks like this:
- ;
- ; dword ptr [bp + 20] --> First arg to OEMToANSI lpOemStr
- (actually a 32 bit near pointer)
- ; dword ptr [bp + 16] --> Second arg to OEMToANSI lpAnsiStr
- (actually a 32 bit near pointer)
- ; dword ptr [bp + 12] --> Return CS
- ; dword ptr [bp + 8] --> Return EIP
- ; dword ptr [bp + 4] --> Entry DS pushed as DWORD
- ; dword ptr [bp + 0] --> Entry EBP
- ;
- lpOemStr equ dword ptr [bp+20]
- lpAnsiStr equ dword ptr [bp+16]
-
- sub sp,8 ; Need two LPSTRs for the aliases
-
- AlsOemStr equ dword ptr [bp-4] ; Alias for lpOemStr
- AlsAnsiStr equ dword ptr [bp-8] ; Alias for lpAnsiStr
-
- push esi
- push edi
- push ebx
- push es ; Preserve "flat" ES, FS, GS
- push fs
- push gs
- ;
- ; There is a ?, how BIG is lpOemStr? Need to know this to set the
- ; size of the alias(s). What we will do is "cheat". We will set
- ; the size to 64k (or size to end of USE32 object, whichever is
- ; smaller). NOTE that this assumes that the string is <= 64K which
- ; is a reasonable assumption since we can't alias something larger
- ; than that anyway.
- ;
- lsl eax,dword ptr [U32DataSel] ; Get limit of USE32 object
- inc eax ; Limit -> size
- mov edx,eax
- sub eax,lpOemStr ; Number of bytes to end of USE32 object
- jc SkipCall ; Bad string ptr
- sub edx,lpAnsiStr ; Number of bytes to end of USE32 object
- jc short SkipCall ; Bad string ptr
- cmp eax,edx
- jbe short UseSrcLim
- mov eax,edx ; lpAnsiStr is closer to end of object
- UseSrcLim:
- mov ecx,00010000h ; 64k
- cmp ecx,eax
- jbe short Use64k
- mov ecx,eax ; Limited by size to end of object
- Use64k:
- ;
- ; Create Alias for lpOemStr
- ;
- push ecx
- lea bx,AlsOemStr
- regptr AlsPt,ss,bx
-
- cCall Global16PointerAlloc,<[U32DataSel],lpOemStr,AlsPt,ecx,0>
-
- pop ecx
- or ax,ax
- jnz short SkipCall
- ;
- ; Create Alias for lpAnsiStr
- ;
- lea bx,AlsAnsiStr
-
- cCall Global16PointerAlloc,<[U32DataSel],lpAnsiStr,AlsPt,ecx,0>
-
- or ax,ax
- jnz short FreeOemAls
- ;
- ; Call OemToAnsi
- ;
- cCall OemToAnsi,<AlsOemStr,AlsAnsiStr>
- ;
- ; Free the aliases
- ;
- push ax ; Save RET code
-
- cCall Global16PointerFree,<[U32DataSel],AlsAnsiStr,0>
-
- pop ax ; Restore RET code
- FreeOemAls:
- push ax ; Save RET code
-
- cCall Global16PointerFree,<[U32DataSel],AlsOemStr,0>
-
- pop ax ; Restore RET code
- SkipCall:
- pop gs
- pop fs
- pop es
- pop ebx
- pop edi
- pop esi
- add sp,8
- pop ebp
- pop ecx ; Entry DS in CX
- ;
- ; Sign extend the return to make it 32 bit
- ;
- movsx eax,ax
- ;
- ; Switch back to the USE32 stack MAKING SURE TO SET HIGH 16 BITS OF ESP.
- ;
- mov ss,[U32DataSel]
- movzx esp,sp
- mov ds,cx
- assume ds:nothing
- db 66h ; USE32 override on far ret so it
- returns to EIP
- ret (2 * 4)
-
- U32OEMtoANSI endp
-
- ;*****************************************************************************
- ;
- ; U32GetDskFree - Issue DOS call to get disk free space
- ;
- ; Assumes PASCAL calling convention
- ;
- ; ENTRY:
- ; U32GetDskFree(drvnum)
- ;
- ; EXIT:
- ; EAX = Disk free space in bytes
- ; EAX == 0FFFFFFFFh if error
- ;
- ; USES:
- ; 32 bit C Standard
- ;
- ;
- ;*****************************************************************************
- PUBLIC U32GetDskFree
-
- U32GetDskFree proc far
- assume ds:nothing
- assume es:nothing
- assume ss:nothing
- ;
- ; First switch to the USE16 stack
- ;
- mov cx,ds ; Save entry DS in cx till we get the
- stack switched
- mov ax,SEG _DATA
- mov ds,ax
- assume ds:_DATA
- mov ss,word ptr [U16StackAlias+2]
- push ecx ; Entry DS, as DWORD to keep stack aligned
- push ebp
- mov bp,sp
- ;
- ; Frame now looks like this:
- ;
- ; dword ptr [bp + 16] --> Drive # argument (0 = default, A = 1 ...)
- ; dword ptr [bp + 12] --> Return CS
- ; dword ptr [bp + 8] --> Return EIP
- ; dword ptr [bp + 4] --> Entry DS pushed as DWORD
- ; dword ptr [bp + 0] --> Entry EBP
- ;
- ArgDrv equ dword ptr [bp+16]
-
- push esi
- push edi
- push ebx
- push es ; Preserve "flat" ES, FS, GS
- push fs
- push gs
-
- mov edx,ArgDrv ; Drive # to DL
- mov ah,36h
- int 21h ; Make DOS call
-
- movsx eax,ax ; Sign extend AX for error
- cmp ax,0FFFFh ; Error?
- je short BadDrv ; Yes, return 0FFFFFFFFh
- movzx eax,ax ; Convert sectors/cluster to 32 bit
- movzx ebx,bx ; Convert Available clusters to 32 bit
- movzx ecx,cx ; Convert bytes/sector to 32 bit
- mul ecx ; EAX = sectors/cluster * bytes/sector =
- ; bytes/cluster
- mul ebx ; EAX = bytes/cluster * Available clusters =
- ; free bytes
- BadDrv:
- pop gs
- pop fs
- pop es
- pop ebx
- pop edi
- pop esi
- pop ebp
- pop ecx ; Entry DS in CX
- ;
- ; Switch back to the USE32 stack MAKING SURE TO SET HIGH 16 BITS OF ESP.
- ;
- mov ss,[U32DataSel]
- movzx esp,sp
- mov ds,cx
- assume ds:nothing
- db 66h ; USE32 override on far ret so it
- returns to EIP
- ret (1 * 4)
-
- U32GetDskFree endp
-
- _HELPERCODE ends
-
- end
-