home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / SAMPLES / WINMEM32 / WINMEM32.TX_ / WINMEM32.TX
Encoding:
Text File  |  1993-02-08  |  17.8 KB  |  594 lines

  1. ;-----------------------------------------------------------------------------
  2. ;
  3. ;   SAMPLE code for WINMEM32 DLL
  4. ;
  5. ;-----------------------------------------------------------------------------
  6.  
  7. .386p
  8.  
  9. memS    equ     1
  10.  
  11.         .xlist
  12.  
  13.         include    cmacros.inc
  14. ;
  15. ; NOTE that we CANNOT use the normal CMACROS segment macros:
  16. ;
  17. ;       CreateSeg
  18. ;       sBegin
  19. ;       sEnd
  20. ;
  21. ; because since we are .386p the default segment type is USE32. Our segments
  22. ; need to be USE16 so we have to declare our segements manually so that the
  23. ; USE16 segment attribute is included.
  24. ;
  25.         include    windows.inc
  26.  
  27.         .list
  28. ;
  29. ; These equates would normally be in an app specific include file
  30. ;
  31. error_bad_file    EQU   08001h
  32. error_wrong_mode  EQU   08002h
  33.  
  34. ;-----------------------------------------------------------------------------
  35. ;
  36. ; External WINMEM32 Procedures
  37. ;
  38. externFP        GetWinMem32Version
  39. externFP        Global32Alloc
  40. externFP        Global32Realloc
  41. externFP        Global32Free
  42. externFP        Global16PointerAlloc
  43. externFP        Global16PointerFree
  44. externFP        Global32CodeAlias
  45. externFP        Global32CodeAliasFree
  46.  
  47. ;-----------------------------------------------------------------------------
  48. ;
  49. ; External Windows Procedures
  50. ;
  51. externFP        OpenFile
  52. externFP        GetWinFlags
  53. externFP        _llseek
  54. externFP        _lread
  55. externFP        _lclose
  56. externFP        OemToAnsi
  57.  
  58. ;
  59. ; MANUAL VERSION OF: createSeg _HELPERCODE,hcode,word,public,CODE
  60. ;
  61. ; NOTE that this segment MUST NOT BE DISCARDABLE, it should be fixed.
  62. ;      This is because the segment is called by USE32 code.
  63. ;
  64. _HELPERCODE segment word public 'CODE' use16
  65. _HELPERCODE ends
  66.  
  67. ;
  68. ; MANUAL VERSION of the automatic data segment declaration
  69. ;
  70. _DATA segment word public 'DATA' use16
  71. _DATA ends
  72.  
  73. _DATA segment use16
  74.  
  75. globalD         AddrOEMToANSI,0         ; Address of OEMToANSI helper function
  76. globalD         AddrDOSGetFreeSpace,0   ; Address of DOS Get disk Free space
  77.                                         ;    helper function
  78. globalD         U32RetVal,0             ; Return code from USE32 call
  79.  
  80. globalD         U16StackAlias,0         ; Alias for the stack
  81.  
  82. globalD         EntryStackSave,0        ; stack ptr save location
  83.  
  84. ;
  85. ; This FWORD forms the entry point for the USE32 code
  86. ;
  87. U32EntryPt      LABEL FWORD
  88. globalD         U32EntOff,00010000h     ; Entry assumed at offset 64K
  89. globalW         U32CodeSel,0            ; CODE alias for the BIG object
  90.  
  91. globalW         U32DataSel,0            ; DATA selector for the BIG object
  92.  
  93. _DATA ends
  94.  
  95. _HELPERCODE segment use16
  96.         assume  cs:_HELPERCODE
  97.  
  98. ;*****************************************************************************
  99. ;
  100. ; SetupCallUSE32
  101. ;
  102. ;       SetupCallUSE32(fName)
  103. ;
  104. ;       Setup and call into USE32 code
  105. ;
  106. ; ASSUMPTIONS:
  107. ;       The USE32 Image is a 0 ORGed 32 bit code image with NO HEADER.
  108. ;       The first 64k of the image (offsets 00000000-0000FFFFh) is reserved
  109. ;         for the stack. We put the stack here so that the required stack
  110. ;         switching (USE32<->USE16) is simply a matter of changing SS.
  111. ;
  112. ;       The entry point of the USE32 code is assumed to be right after the
  113. ;         stack at offset 00010000h in the image. We enter with DS, FS, GS
  114. ;         and SS set to the FLAT data segment, and CS set to the flat code
  115. ;         segment. It is the responsibility of the USE32 entry point to set
  116. ;         ES AND PRESERVE IT FOR US.
  117. ;
  118. ;       When this code wishes to call the two provided USE16 helper routines,
  119. ;         it looks up the call addresses in the AddrOEMToANSI and
  120. ;         AddrDOSGetFreeSpace variables in the _DATA segment.
  121. ;         This "loader" code actually needs to pass the selector for the
  122. ;         _DATA segment to the USE32 code so that it can access the data
  123. ;         segment, or it needs to copy the call addresses into the USE32
  124. ;         code/data segment. This detail of the implementation is NOT
  125. ;         included in this code.
  126. ;
  127. ; ENTRY:
  128. ;       FName - DWORD pointer to file name of USE32 image to load
  129. ;
  130. ; EXIT:
  131. ;       AX != 0 If an error occurs
  132. ;           AX = error code
  133. ;       Else
  134. ;           AX = 0 and U32RetVal contains the return code from the
  135. ;                   USE32 code.
  136. ; USES:
  137. ;       C Standard
  138. ;
  139. ;*****************************************************************************
  140. cProc  StartupCallUSE32,<FAR,PUBLIC>,<si,di>
  141.  
  142.         ParmD   fName
  143.  
  144.         LocalD  fSize                   ; Size of file
  145.         LocalD  U16RdAlias              ; Alias for reading image
  146.         LocalD  FileOff                 ; Current file offset for read
  147.         LocalW  fHand                   ; File handle
  148.         LocalV  OpnBuf,<SIZE OPENSTRUC> ; Open file struct for openfile call
  149.  
  150. cBegin
  151.     assume  ds:_DATA
  152.     assume  es:nothing
  153.     assume  ss:_DATA
  154.     ;
  155.     ; First check if we are running in enhanced mode
  156.     ;
  157.     ; NOTE THAT SINCE WE DO NOT KNOW AS YET WHAT MODE WE ARE IN WE NEED
  158.     ;   TO AVOID USING 386 SPECIFIC INSTRUCTIONS
  159.     ;
  160.         cCall   GetWinFlags
  161.  
  162.         and     ax,WF_PMODE + WF_ENHANCED
  163.         cmp     ax,WF_PMODE + WF_ENHANCED
  164.         je      short OKtoLoad                  ; MUST BE SHORT
  165.         mov     ax,error_wrong_mode
  166.         jmp     Done1
  167.  
  168.     ;
  169.     ; We now know we are in the proper mode and that 386 instructions
  170.     ;   are now OK.
  171.     ;
  172. OKtoLoad:
  173.     ;
  174.     ; Set up the addresses for the USE32 code to call the helper routines
  175.     ;
  176.         mov     ax,cs
  177.         mov     word ptr [AddrOEMToANSI+2],ax
  178.         mov     word ptr [AddrOEMToANSI],offset _HELPERCODE:U32OEMtoANSI
  179.         mov     word ptr [AddrDOSGetFreeSpace+2],ax
  180.         mov     word ptr [AddrDOSGetFreeSpace],offset _HELPERCODE:U32GetDskFree
  181.     ;
  182.     ; Open the file
  183.     ;
  184.         lea     bx,OpnBuf
  185.         regptr  ssbx,ss,bx
  186.         cCall   OpenFile,<fName,ssbx,OF_READ>
  187.         cmp     ax,-1                   ; Did we find it?
  188.         je      Done1FlErr              ; No, file error
  189.         mov     fHand,ax                ; Save file handle
  190.     ;
  191.     ; Get file size
  192.     ;
  193.         cCall   _llseek,<fHand,0,0,2>
  194.         shl     edx,16
  195.         mov     dx,ax
  196.         inc     edx
  197.         jz      Done1FlErr              ; seek failed, file error
  198.         dec     edx
  199.         mov     fSize,edx
  200.         cmp     edx,10000h              ; Image is at least 64k?
  201.         jbe     Done1FlErr              ; No, size is too small, file error
  202.     ;
  203.     ; Move file pointer back to start of file for read
  204.     ;
  205.         cCall   _llseek,<fHand,0,0,0>
  206.     ;
  207.     ; Allocate big USE32 object
  208.     ;
  209.         mov     si,dataOffset U32DataSel
  210.         regptr  Selpt,ds,si
  211.         cCall   Global32Alloc,<fSize,Selpt,fSize,0>
  212.         or      ax,ax                   ; Worked?
  213.         jnz     FcloseEr                ; No, return WINMEM32 error code
  214.     ;
  215.     ; Allocate USE16 stack alias for first 64K of object
  216.     ;
  217.         mov     si,dataOffset U16StackAlias
  218.         regptr  Alipt,ds,si
  219.         mov     ecx,00010000h           ; 64K
  220.         cCall   Global16PointerAlloc,<[U32DataSel],0,0,Alipt,ecx,0>
  221.         or      ax,ax                   ; Worked?
  222.         jnz     AliasErrF3              ; No, return WINMEM32 error code
  223.     ;
  224.     ; Allocate USE32 code alias
  225.     ;
  226.         mov     si,dataOffset U32CodeSel
  227.         regptr  Alipt,ds,si
  228.         cCall   Global32CodeAlias,<[U32DataSel],Alipt,0>
  229.         or      ax,ax                   ; Worked?
  230.         jnz     AliasErrF2              ; No, return WINMEM32 error code
  231.     ;
  232.     ; Now read in the image. We will do this in 32K hunks.
  233.     ;
  234.         mov     FileOff,0               ; Starting at file offset 0
  235. ReadLp:
  236.         mov     ecx,00008000h           ; 32k
  237.         cmp     ecx,fSize
  238.         jbe     short Read32k
  239.         mov     ecx,fSize
  240. Read32k:
  241.     ;
  242.     ; Make a USE16 alias for this region of the object
  243.     ;
  244.         push    ecx
  245.         lea     si,U16RdAlias
  246.         regptr  Alipt,ss,si
  247.         cCall   Global16PointerAlloc,<[U32DataSel],FileOff,Alipt,ecx,0>
  248.         pop     ecx
  249.         or      ax,ax
  250.         jnz     short AliasErrF1
  251.         push    ecx
  252.         cCall   _lread,<fHand,U16RdAlias,cx>
  253.         push    ax
  254.         cCall   Global16PointerFree,<[U32DataSel],U16RdAlias,0>
  255.         pop     ax
  256.         pop     ecx
  257.         inc     ax
  258.         jz      short FlRdErr
  259.         dec     ax
  260.         cmp     ax,cx
  261.         jne     short FlRdErr
  262.         add     FileOff,ecx
  263.         sub     fSize,ecx
  264.         ja      short ReadLp
  265.  
  266. ;
  267.     ; We are now ready to set up and call into the USE32 code
  268.     ;
  269.     ;   Save the current stack so we can switch to the USE32 stack
  270.     ;
  271.     ;   NOTE CAREFULLY THAT THIS MAKES THIS ROUTINE NON-REENTRANT
  272.     ;   SINCE IT SAVES THE CURRENT SS:SP IN A STATIC MEMORY LOCATION.
  273.     ;
  274.         mov     word ptr [EntryStackSave],sp
  275.         mov     word ptr [EntryStackSave+2],ss
  276.         mov     ax,[U32DataSel]
  277.         push    ds
  278.         pop     es
  279.     assume es:_DATA
  280.     ;
  281.     ; Set up all the segs, and call into USE32
  282.     ;
  283.     ; NOTE that we just leave the file open across the call.
  284.     ;
  285.         mov     ds,ax
  286.     assume ds:nothing
  287.         mov     fs,ax
  288.         mov     gs,ax
  289.         mov     ss,ax
  290.     assume ss:nothing
  291.         mov     esp,0000FFFCh
  292.         call    [U32EntryPt]
  293.     ;
  294.     ; Recover DS and stack.
  295.     ;
  296.         mov     bx,es
  297.         mov     ds,bx
  298.     assume ds:_DATA
  299.         mov     ss,word ptr [EntryStackSave+2]
  300.     assume ss:_DATA
  301.         mov     sp,word ptr [EntryStackSave]
  302.     ;
  303.     ; Set success return and clean up.
  304.     ;
  305.         mov     [U32RetVal],eax
  306.         xor     ax,ax                   ; Return success
  307.         jmp     short AliasErrF1
  308.  
  309. FlRdErr:
  310.         mov     ax,error_bad_file
  311. AliasErrF1:
  312.     ;
  313.     ; Free USE32 code alias
  314.     ;
  315.         push    ax                      ; Save error code
  316.         cCall   Global32CodeAliasFree,<[U32DataSel],[U32CodeSel],0>
  317.         pop     ax
  318. AliasErrF2:
  319.     ;
  320.     ; Free USE16 stack alias
  321.     ;
  322.         push    ax                      ; Save error code
  323.         cCall   Global16PointerFree,<[U32DataSel],[U16StackAlias],0>
  324.         pop     ax
  325. AliasErrF3:
  326.     ;
  327.     ; Free the object
  328.     ;
  329.         push    ax                      ; Save error code
  330.         cCall   Global32Free,<[U32DataSel],0>
  331.         pop     ax
  332. FcloseEr:
  333.     ;
  334.     ; Close the file
  335.     ;
  336.         push    ax                      ; Save error code
  337.         cCall   _lclose,<fHand>
  338.         pop     ax
  339.         jmp     short Done1
  340.  
  341. Done1FlErr:
  342.         mov     ax,error_bad_file
  343. Done1:
  344. cEnd
  345.  
  346. ;*****************************************************************************
  347. ;
  348. ; U32OEMtoANSI - Call OemToANSI from USE32 segment
  349. ;
  350. ;    Assumes PASCAL calling convention
  351. ;
  352. ; ENTRY:
  353. ;       U32OEMtoANSI(lpOemStr,lpAnsiStr)
  354. ;
  355. ;       NOTE that these pointer arguments are NOT really LPSTRs. They
  356. ;       are near pointers into the USE32 data object (implied segment
  357. ;       is U32DataSel)
  358. ;
  359. ; EXIT:
  360. ;       EAX is return code
  361. ;
  362. ; USES:
  363. ;       32 bit C Standard
  364. ;
  365. ;
  366. ;*****************************************************************************
  367. PUBLIC U32OEMtoANSI
  368.  
  369. U32OEMtoANSI proc far
  370.     assume  ds:nothing
  371.     assume  es:nothing
  372.     assume  ss:nothing
  373.     ;
  374.     ; First switch to the USE16 stack
  375.     ;
  376.         mov     cx,ds           ; Save entry DS in cx till we get the 
  377. stack switched
  378.         mov     ax,SEG _DATA
  379.         mov     ds,ax
  380.     assume ds:_DATA
  381.         mov     ss,word ptr [U16StackAlias+2]
  382.         push    ecx             ; Entry DS, as DWORD to keep stack aligned
  383.         push    ebp
  384.         mov     bp,sp
  385.     ;
  386.     ; Frame now looks like this:
  387.     ;
  388.     ;   dword ptr [bp + 20]  -->  First arg to OEMToANSI  lpOemStr 
  389. (actually a 32 bit near pointer)
  390.     ;   dword ptr [bp + 16]  -->  Second arg to OEMToANSI lpAnsiStr 
  391. (actually a 32 bit near pointer)
  392.     ;   dword ptr [bp + 12]  -->  Return CS
  393.     ;   dword ptr [bp + 8]   -->  Return EIP
  394.     ;   dword ptr [bp + 4]   -->  Entry DS pushed as DWORD
  395.     ;   dword ptr [bp + 0]   -->  Entry EBP
  396.     ;
  397. lpOemStr        equ     dword ptr [bp+20]
  398. lpAnsiStr       equ     dword ptr [bp+16]
  399.  
  400.         sub     sp,8            ; Need two LPSTRs for the aliases
  401.  
  402. AlsOemStr       equ     dword ptr [bp-4]        ; Alias for lpOemStr
  403. AlsAnsiStr      equ     dword ptr [bp-8]        ; Alias for lpAnsiStr
  404.  
  405.         push    esi
  406.         push    edi
  407.         push    ebx
  408.         push    es              ; Preserve "flat" ES, FS, GS
  409.         push    fs
  410.         push    gs
  411.     ;
  412.     ; There is a ?, how BIG is lpOemStr? Need to know this to set the
  413.     ;   size of the alias(s). What we will do is "cheat". We will set
  414.     ;   the size to 64k (or size to end of USE32 object, whichever is
  415.     ;   smaller). NOTE that this assumes that the string is <= 64K which
  416.     ;   is a reasonable assumption since we can't alias something larger
  417.     ;   than that anyway.
  418.     ;
  419.         lsl     eax,dword ptr [U32DataSel]  ; Get limit of USE32 object
  420.         inc     eax             ; Limit -> size
  421.         mov     edx,eax
  422.         sub     eax,lpOemStr    ; Number of bytes to end of USE32 object
  423.         jc      SkipCall        ; Bad string ptr
  424.         sub     edx,lpAnsiStr   ; Number of bytes to end of USE32 object
  425.         jc      short SkipCall  ; Bad string ptr
  426.         cmp     eax,edx
  427.         jbe     short UseSrcLim
  428.         mov     eax,edx         ; lpAnsiStr is closer to end of object
  429. UseSrcLim:
  430.         mov     ecx,00010000h   ; 64k
  431.         cmp     ecx,eax
  432.         jbe     short Use64k
  433.         mov     ecx,eax         ; Limited by size to end of object
  434. Use64k:
  435.     ;
  436.     ; Create Alias for lpOemStr
  437.     ;
  438.         push    ecx
  439.         lea     bx,AlsOemStr
  440.         regptr  AlsPt,ss,bx
  441.  
  442.         cCall   Global16PointerAlloc,<[U32DataSel],lpOemStr,AlsPt,ecx,0>
  443.  
  444.         pop     ecx
  445.         or      ax,ax
  446.         jnz     short SkipCall
  447.     ;
  448.     ; Create Alias for lpAnsiStr
  449.     ;
  450.         lea     bx,AlsAnsiStr
  451.  
  452.         cCall   Global16PointerAlloc,<[U32DataSel],lpAnsiStr,AlsPt,ecx,0>
  453.  
  454.         or      ax,ax
  455.         jnz     short FreeOemAls
  456.     ;
  457.     ; Call OemToAnsi
  458.     ;
  459.         cCall   OemToAnsi,<AlsOemStr,AlsAnsiStr>
  460.     ;
  461.     ; Free the aliases
  462.     ;
  463.         push    ax              ; Save RET code
  464.  
  465.         cCall   Global16PointerFree,<[U32DataSel],AlsAnsiStr,0>
  466.  
  467.         pop     ax              ; Restore RET code
  468. FreeOemAls:
  469.         push    ax              ; Save RET code
  470.  
  471.         cCall   Global16PointerFree,<[U32DataSel],AlsOemStr,0>
  472.  
  473.         pop     ax              ; Restore RET code
  474. SkipCall:
  475.         pop     gs
  476.         pop     fs
  477.         pop     es
  478.         pop     ebx
  479.         pop     edi
  480.         pop     esi
  481.         add     sp,8
  482.         pop     ebp
  483.         pop     ecx             ; Entry DS in CX
  484.     ;
  485.     ; Sign extend the return to make it 32 bit
  486.     ;
  487.         movsx   eax,ax
  488.     ;
  489.     ; Switch back to the USE32 stack MAKING SURE TO SET HIGH 16 BITS OF ESP.
  490.     ;
  491.         mov     ss,[U32DataSel]
  492.         movzx   esp,sp
  493.         mov     ds,cx
  494.     assume  ds:nothing
  495.         db      66h             ; USE32 override on far ret so it 
  496. returns to EIP
  497.         ret     (2 * 4)
  498.  
  499. U32OEMtoANSI endp
  500.  
  501. ;*****************************************************************************
  502. ;
  503. ; U32GetDskFree - Issue DOS call to get disk free space
  504. ;
  505. ;    Assumes PASCAL calling convention
  506. ;
  507. ; ENTRY:
  508. ;       U32GetDskFree(drvnum)
  509. ;
  510. ; EXIT:
  511. ;       EAX = Disk free space in bytes
  512. ;       EAX == 0FFFFFFFFh if error
  513. ;
  514. ; USES:
  515. ;       32 bit C Standard
  516. ;
  517. ;
  518. ;*****************************************************************************
  519. PUBLIC U32GetDskFree
  520.  
  521. U32GetDskFree proc far
  522.     assume  ds:nothing
  523.     assume  es:nothing
  524.     assume  ss:nothing
  525.     ;
  526.     ; First switch to the USE16 stack
  527.     ;
  528.         mov     cx,ds           ; Save entry DS in cx till we get the 
  529. stack switched
  530.         mov     ax,SEG _DATA
  531.         mov     ds,ax
  532.     assume ds:_DATA
  533.         mov     ss,word ptr [U16StackAlias+2]
  534.         push    ecx             ; Entry DS, as DWORD to keep stack aligned
  535.         push    ebp
  536.         mov     bp,sp
  537.     ;
  538.     ; Frame now looks like this:
  539.     ;
  540.     ;   dword ptr [bp + 16]  -->  Drive # argument (0 = default, A = 1 ...)
  541.     ;   dword ptr [bp + 12]  -->  Return CS
  542.     ;   dword ptr [bp + 8]   -->  Return EIP
  543.     ;   dword ptr [bp + 4]   -->  Entry DS pushed as DWORD
  544.     ;   dword ptr [bp + 0]   -->  Entry EBP
  545.     ;
  546. ArgDrv          equ     dword ptr [bp+16]
  547.  
  548.         push    esi
  549.         push    edi
  550.         push    ebx
  551.         push    es              ; Preserve "flat" ES, FS, GS
  552.         push    fs
  553.         push    gs
  554.  
  555.         mov     edx,ArgDrv      ; Drive # to DL
  556.         mov     ah,36h
  557.         int     21h             ; Make DOS call
  558.  
  559. movsx   eax,ax          ; Sign extend AX for error
  560.         cmp     ax,0FFFFh       ; Error?
  561.         je      short BadDrv    ; Yes, return 0FFFFFFFFh
  562.         movzx   eax,ax          ; Convert sectors/cluster to 32 bit
  563.         movzx   ebx,bx          ; Convert Available clusters to 32 bit
  564.         movzx   ecx,cx          ; Convert bytes/sector to 32 bit
  565.         mul     ecx             ; EAX = sectors/cluster * bytes/sector =
  566.                                 ;       bytes/cluster
  567.         mul     ebx             ; EAX = bytes/cluster * Available clusters =
  568.                                 ;       free bytes
  569. BadDrv:
  570.         pop     gs
  571.         pop     fs
  572.         pop     es
  573.         pop     ebx
  574.         pop     edi
  575.         pop     esi
  576.         pop     ebp
  577.         pop     ecx             ; Entry DS in CX
  578.     ;
  579.     ; Switch back to the USE32 stack MAKING SURE TO SET HIGH 16 BITS OF ESP.
  580.     ;
  581.         mov     ss,[U32DataSel]
  582.         movzx   esp,sp
  583.         mov     ds,cx
  584.     assume  ds:nothing
  585.         db      66h             ; USE32 override on far ret so it 
  586. returns to EIP
  587.         ret     (1 * 4)
  588.  
  589. U32GetDskFree endp
  590.  
  591. _HELPERCODE ends
  592.  
  593.         end
  594.