PAGE    ,132
NAME    pdfile

;       SCCSID = @(#)pdfile.asm

TITLE   PDFILE - Process Dump Utility File Service Routines

;**     PDFILE.ASM - Process Dump Utility File Service Routines
;
;       SCCSID = @(#)pdfile.asm
;
;       THIS IS AN OS/2 VERSION 2.x SPECIFIC FILE
;
;       IBM Confidential
;
;       Copyright (c) IBM Corporation 1992, 1992
;
;       All Rights Reserved
;
;       Description:
;
;       This module contains routines for Process Dump file functions
;       that cannot possibly be written in C due to the 0:32/16:16
;       interface conflict.
;
;       Public routines:
;
;           PDOpen
;           PLDClose
;           PDWrite
;
;   Change                                                               Chg
;   Activity      Date    BY   Reason                                    Num
;   --------      ----    ---  -------                                   ---
;   DEF 0058586 12/12/92  ARJ  Put in Changes for protected file handles 001
;
;**********************************************************************

INCL_NONE       equ     1                       ; don't include everything
INCL_TYPES      equ     1                       ; include basic types
INCL_DEF        equ     1                       ; include typedef macros
DoRead          equ     0
DoWrite         equ     1

.xlist
        include dosseg.inc
        include osmaca.inc
        include osconst.inc
        include fnotask.inc
        include infoseg.inc
        include dossymc.inc
        include sigdef.inc
        include except.inc
        include pgexport.inc
        include vmexport.inc
        include selxport.inc
        include argframe.inc
        include tkexport.inc
        include dirent.inc
        include curdir.inc
        include find.inc
        include screen.inc
        include sft.inc
        include sem.inc
        include tkptda.inc
        include kmode.inc
        include seldesc.inc
        include mi.inc
        include mvdm.inc
        include sysentry.inc
        include opncreat.inc
        include filemode.inc
        include inbuf.inc
        include error.inc
.list

        ModName ,FNO_PDFILE_ASM

        CpuMode 386

        ReferFlat       _pPTDACur,DWORD
        ReferGlobal     Header,byte

        EXTRN16         w_OpenCreate
        EXTRN16         w_Write
        EXTRN16         w_Read
        EXTRN16         w_Close
        EXTRN16         w_LSeek
        EXTRN16         w_Unlink
        EXTRN16         w_EnterCritSec
        EXTRN16         w_ExitCritSec
        EXTRN           SISData:BYTE
        extrn           HeaderLen:abs

DefData IMPORT, GLOBAL, C
PVOID   pPTDACur
EndData

DefCode IMPORT, GLOBAL, C
DefFn   SELLdrDesc
DefFn   SELFreeGDT
EndCode


DefCode EXPORT, SWAP, PASCAL
DefFn   PDOpen
DefFn   PLDClose
DefFn   PDWrite
DefFn   PDRead
DefFn   PDSeek
DefFn   PDDel
DefFn   PLDGetVerString
DefFn   PLDEnterCritSec
DefFn   PLDExitCritSec
EndCode

DefCode EXPORT, SWAP, C
DefFn   PLDGetDateTime
EndCode

        FARCODE HIGH32
DefCode PRIVATE, SWAP, PASCAL

;***LP+ PDOpen - Open the a file or device
;
;      Open a file/device and return a handle.  This handle can be
;      used with PDWrite, and PLDClose
;
;      PDMP front end to the file system worker routine for 32 bit DosOpen.
;      Refer to documentation for 32 bit DosOpen API for complete
;      specification of each parameter.
;
;      ENTRY
;          FileName (PSZ) - Filename is the ASCIIZ path name of the file
;                           or device name to be opened.
;
;          FileHandle (PHFILE) - FileHandle is where the system returns the
;                                file handle.
;
;          ActionTaken (PULONG) - ActionTaken is where the system returns a
;                                 description of the action taken as a result
;                                 of this function call. Possible actions
;                                 actions taken:
;                                                 1 - file existed
;                                                 2 - file created
;                                                 3 - file replaced
;
;          FileSize (ULONG) - FileSize is the new file's logical size (EOD)
;                             in bytes.
;
;          FileAttribute (ULONG) - FileAttribute is the file attribute bits,
;                                  used on file creation.
;
;          OpenFlag (ULONG) - OpenFlag specifies the action to be taken
;                             depending on whether or not the file exists.
;
;          OpenMode (ULONG) - OpenMode describes the mode of the open function.
;
;          EABuf (PEAOP2) - EABuf is the address of an EAOP2 structure or NULL.
;
;
;      EXIT-SUCCESS
;          returns TRUE (non-zero)
;
;      EXIT-FAILURE
;          returns FALSE (zero)
;              ERROR_DISK_FULL
;              ERROR_OPEN_FAILED
;              ERROR_FILE_NOT_FOUND
;              ERROR_INVALID_PARAMETER
;              ERROR_PATH_NOT_FOUND
;              ERROR_ACCESS_DENIED
;              ERROR_DRIVE_LOCKED
;              ERROR_NOT_DOS_DISK
;              ERROR_SHARING_BUFFER_EXCEEDED
;              ERROR_SHARING_VIOLATION
;              ERROR_INVALID_ACCESS
;              ERROR_CANNOT_MAKE
;              ERROR_TOO_MANY_OPEN_FILES
;              ERROR_NOT_ENOUGH_MEMORY
;          System Halt
;              If called other than at PDMP task time, or if pszFileName
;              ptr is invalid
;
;      PDMP TERMINATION IMPLICATIONS
;          Any handles the PDMP opened must be closed with PDMPClose.
;
;      NOTE
;          Using PDOpen does not interfere in any way with the
;          handle space available via INT 21h,
;          except that it does count against the system wide limit
;          on the number of open file handles.
;
;          The handles returned from INT 21h $Open and these PDOpen
;          handles can not be used interchangably.
;
;          If pointers passed on this call are allocated from the stack
;          then you must use the SSToDS macro to make the pointer DS
;          relative.
;
;

        ASSUME  DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING

Procedure PDOpen,NEAR

        ArgVar    pszFile,DWORD
        ArgVar    pFileHandle,DWORD
        ArgVar    ActionTaken,DWORD
        ArgVar    FileSize,DWORD
        ArgVar    FileAttribute,DWORD
        ArgVar    OpenFlag,DWORD
        ArgVar    OpenMode,DWORD
        ArgVar    EABuf,DWORD

        LocalVar  pdmpopen_sel,DWORD
        LocalVar  eabuf_sel,DWORD
        LocalVar  errCode,DWORD
        LocalVar  pdmpopen_ArgFrame,<size Open2Struc>
        LocalVar  pdmpopen_CurrentPDB,WORD

        EnterProc
        SaveReg <ebx,esi,edi,ds,es,fs,gs>
        push    ds
        pop     es

;       Changed all occurances of opn2s to opn3s                      A001

;       We must clear the current PDB field so the file handle opened
;       here is not automaticly closed during PDB or VDM process
;       termination.  (see DOS_Abort).

        mov     esi,[pPTDACur]          ; (ESI) = pointer to PTDA
        sub     eax,eax                 ; (AX) = 0 = no PDB for this open
        xchg    ax,[esi].CurrentPDB     ; (AX) = current PDB
        mov     [pdmpopen_CurrentPDB],ax ; save old PDB value

;       Get the length of the file name string for creating GDT Alias

        mov     edi,[pszFile]           ; by default, ES must equal DS already
        sub     al,al
        mov     ecx,-1
        repne   scasb
        not     ecx
        cmp     ecx,MAXPATHLEN
        mov     eax,ERROR_OPEN_FAILED
        mov     [errCode],eax
        ja      pdmpopen_exit

;       Arrange the argument frame for w_OpenCreate

        mov     eax,FileSize
        mov     [pdmpopen_ArgFrame].opn3s_Size,eax
        mov     eax,FileAttribute
        mov     [pdmpopen_ArgFrame].opn3s_Attrs,ax
        mov     eax,OpenFlag
        mov     [pdmpopen_ArgFrame].opn3s_Flag,ax
        mov     eax,OpenMode
        mov     [pdmpopen_ArgFrame].opn3s_Mode,ax      ; Mode is the Low word
        shr     eax,16
        mov     [pdmpopen_ArgFrame].opn3s_Mode2,ax     ; Mode2 is the High word

        xor     eax,eax
        mov     [pdmpopen_sel],eax
        mov     [eabuf_sel],eax
        mov     [errCode],eax
        mov     [pdmpopen_ArgFrame].opn3s_Reserved,eax
        mov     [pdmpopen_ArgFrame].opn3s_NamePtr,eax
        mov     [pdmpopen_ArgFrame].opn3s_HandlePtr,eax
        mov     [pdmpopen_ArgFrame].opn3s_ActionPtr,eax
        mov     [pdmpopen_ArgFrame].opn3s_EABufPtr,eax

;   Grow selector for pszFile

        lea     edx,[pdmpopen_sel]
        SSToDS  edx
        CCALL32 SELLdrDesc, <[pszFile], ecx, edx>
        mov     [errCode],eax                  ; if successful, errCode = 0
        or      eax,eax
        jnz     pdmpopen_exit                  ; on error, exit

        mov     eax,[pdmpopen_sel]                        ; move selector to
        shl     eax,16                                    ;  high word
        mov     [pdmpopen_ArgFrame].opn3s_NamePtr,eax

;   Grow selector for EABuf

        mov     eax,EABuf                     ; Check for null ptr
        or      eax,eax
        jz      short pdmpopen_yeseabufsel ; if null then do not create selector
        lea     edx,[eabuf_sel]
        SSToDS  edx
        CCALL32 SELLdrDesc, <[EABuf], 4, edx>
        mov     [errCode],eax
        or      eax,eax
        jnz     short freepszfile_sel         ; on error free up selectors

        mov     eax,[eabuf_sel]                             ; move selector to
        shl     eax,16                                      ;  high word
        mov     [pdmpopen_ArgFrame].opn3s_EABufPtr,eax

pdmpopen_yeseabufsel:
        mov     ah,attr_hidden+attr_system+attr_directory
        mov     al,OPCR_SATTR_INDIRECT
        lea     bx,[pdmpopen_ArgFrame]  ; ArgFrame in SS:[bx]
        push    ds                      ; protect ds from w_OpenCreate
        push    es                      ; protect es from w_OpenCreate
        mov     dl,IFaceLevel2          ; DL = Interface Level (DosOpen2)
        CALL16  w_OpenCreate
        pop     es                      ; restore es
        pop     ds                      ; restore ds
        jc      short pdmpopenerr1      ; on error save bad return code
        mov     ecx,[pFileHandle]       ; dword ptr to word value
        movzx   eax,ax
        mov     dword ptr [ecx],eax     ; save handle
        mov     ecx,[ActionTaken]       ; dword ptr to word value
        movzx   ebx,bx
        mov     dword ptr [ecx],ebx     ; save action taken
        jmp     freeeabuf_sel           ; free up selectors
pdmpopenerr1:
        movzx   eax,ax
        mov     [errCode],eax

;   Free selector for EABuf

freeeabuf_sel:
        mov     eax,EABuf                    ; Check for null ptr
        or      eax,eax
        jz      short freepszfile_sel        ; if null then no selector to free
        CCALL32 SELFreeGDT, <[eabuf_sel]>

;   Free selector for pszFile

freepszfile_sel:
        CCALL32 SELFreeGDT, <[pdmpopen_sel]>

        or      eax,eax
        jz      short pdmpopen_exit
        cmp     [errCode],0             ; do not overwrite
        jnz     short pdmpopen_exit     ;   preexisting nonzero errCode
        mov     [errCode],eax

pdmpopen_exit:
        mov     eax,[errCode]
        mov     esi,[pPTDACur]           ; (ESI) = pointer to PTDA
        mov     cx,[pdmpopen_CurrentPDB] ; (CX) = old PDB value
        mov     [esi].CurrentPDB,cx      ; restore PDB value
        RestoreReg  <gs,fs,es,ds,edi,esi,ebx>
        ExitProc
EndProc PDOpen

;***LP+ PLDClose - close a file or device
;
;       Call w_Close to close the file or device
;
;       INT PASCAL PLDClose(hFile);
;
;       ENTRY
;           hFile
;               handle to close
;
;       EXIT
;           SUCCESS
;               EAX = 0
;
;           FAILURE
;               Returns non-zero error code in EAX
;
;       STEPS
;           Call w_Close to close the file
;
;       NOTES
;           None
;
;       WARNINGS
;           None
;
;       CALLS
;           w_Close
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING

Procedure PLDClose,NEAR

ArgVar  PD_hFile,DWORD

        EnterProc
        SaveReg <esi, edi, ebx, ecx, edx, ds, es, fs, gs>
        xor     ecx,ecx                 ; also added to SAVEREG   A001
        xor     edx,edx                 ; and RESTOREREG          A001
        mov     ebx,[PD_hFile]          ; get the handle in BX
        CALL16  w_Close                 ; close it
        jc      short pdcl
        xor     eax,eax
pdcl:   movzx   eax,ax                  ; (EAX) = error code
        RestoreReg <gs, fs, es, ds, edx, ecx, ebx, edi, esi>
        ExitProc
EndProc PLDClose

;***LP+ PDWrite - write to a file or device
;
;       Call w_Write to write to the opened file or device
;
;       INT PASCAL PDWrite(hFile, pBuffer, cbWrite);
;
;       ENTRY
;           hFile
;               handle to write to
;           pBuffer
;               buffer from which to write
;           cbWrite
;               number of bytes to write
;
;       EXIT
;           SUCCESS
;               EAX = 0
;
;           FAILURE
;               Returns non-zero error code in EAX
;
;       STEPS
;           Call w_Write to write to the file
;
;       NOTES
;           None
;
;       CALLS
;           w_Write
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING

Procedure PDWrite,NEAR

ArgVar   PD_hFile,DWORD
ArgVar   PD_pBuffer,DWORD
ArgVar   PD_Size,DWORD
LocalVar w_sel, DWORD
LocalVar errCode, DWORD
LocalVar IOType, WORD

        mov     ax,DoWrite
RdIO:
        EnterProc
        mov     [IOType],ax
        SaveReg <esi, edi, ebx, ds, es, fs, gs>
        mov     ecx,[PD_Size]           ; (ECX) = transfer size
        mov     [w_sel],0
        lea     edx,[w_sel]             ; (EDX) = selector index
        SSToDS  edx
        CCALL32 SELLdrDesc, <[PD_pBuffer], ecx, edx>
        mov     [errCode],eax           ; save error code
        or      eax,eax
        jnz     wrtx
        mov     ds,[w_sel]
        ASSUME  ds:NOTHING
        xor     edx,edx                 ; (DS:DX) = buffer address

        mov     ecx,[PD_Size]           ; (CX) = transfer size
        mov     ebx,[PD_hFile]          ; (BX) = handle
        push    ebp
        cmp     [IOType],DoRead         ; want to read?
        jz      rdfunc
        xor     eax,eax                 ; A001
        CALL16  w_Write                 ; write to the file
        jmp     ioComplete
rdfunc:
        xor     eax,eax                 ; A001
        CALL16  w_Read                  ; read from file
ioComplete:
        ASSUME  ds:NOTHING,es:NOTHING
        pop     ebp
        jc      short wrtfree           ; skip if error

        xor     eax,eax
wrtfree:
        FlatContext <ds>
        mov     [errCode],eax
        CCALL32 SELFreeGDT, <[w_sel]>
        or      eax,eax
        jz      wrtx
        cmp     [errCode],0             ; do not overwrite
        jnz     wrtx                    ;   preexisting nonzero errCode
        mov     [errCode],eax

wrtx:
        mov     eax,[errCode]
        movzx   eax,ax                  ; (EAX) = error code
        RestoreReg <gs, fs, es, ds, ebx, edi, esi>
        ExitProc
EndProc PDWrite

;***LP+ PDRead - read from a file or device
;
;       Call w_Read to read the opened file or device
;
;       INT PASCAL PDWrite(hFile, pBuffer, cbWrite);
;
;       ENTRY
;           hFile
;               handle to write to
;           pBuffer
;               buffer from which to write
;           cbWrite
;               number of bytes to write
;
;       EXIT
;           SUCCESS
;               EAX = 0
;
;           FAILURE
;               Returns non-zero error code in EAX
;
;       STEPS
;           Call w_Read to read from the file
;
;       NOTES
;           None
;
;       CALLS
;           w_Read
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING

Procedure PDRead,NEAR

ArgVar   PD_hFile,DWORD
ArgVar   PD_pBuffer,DWORD
ArgVar   PD_Size,DWORD
LocalVar w_sel, DWORD
LocalVar errCode, DWORD
LocalVar IOType, WORD

        mov     ax,DoRead
        jmp     RdIO
EndProc PDRead

;***LP+ PDSeek - seek a file or device
;
;       Call w_LSeek to move the file position
;
;       INT PASCAL PDSeek(hFile, ulSeekType, ulPos, pulPos);
;
;       ENTRY
;           hFile
;               handle of file
;           ulSeekType
;               type of seek
;                 0 - FILE_BEGIN   - Move pointer from the beginning of file
;                 1 - FILE_CURRENT - Move pointer from the current location
;                 2 - FILE_END     - Move pointer from the end of the file
;           ulPos
;               position to move file pointer
;           pulPos
;               new position after seek
;
;       EXIT
;           SUCCESS
;               EAX = 0
;
;           FAILURE
;               Returns non-zero error code in EAX
;
;       STEPS
;           Call w_LSeek to change the file pointer
;
;       CALLS
;           w_LSeek
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING

Procedure PDSeek,NEAR

ArgVar  pd_hFile,DWORD
ArgVar  pd_ulPos,DWORD
ArgVar  pd_ulSeekType,DWORD
ArgVar  pd_pulPos,DWORD

        EnterProc
        SaveReg <esi, edi, ebx, ds, es>
        mov     eax,[pd_ulSeekType]
        mov     edx,[pd_ulPos]
        shld    ecx,edx,16              ; (CX:DX) = position
        mov     ebx,[pd_hFile]          ; get the handle in BX
        xor     esi,esi                 ;  A001
        xor     edi,edi                 ;  A001
        CALL16  w_LSeek                 ; (DX:AX) = new position
        jc      short seekx

        FlatContext <ds,es>
        mov     ebx,[pd_pulPos]         ; (EBX) = pointer to put new position
        or      ebx,ebx
        jz      short seekxs            ; if ptr is NULL, return
        mov     [ebx].loword,ax
        mov     [ebx].hiword,dx
seekxs:
        xor     eax,eax
seekx:
        movzx   eax,ax
        RestoreReg <es, ds, ebx, edi, esi>
        ExitProc
EndProc PDSeek

;***LP+ PDDel - delete a file
;
;       Call w_Unlink to delete the file
;
;       INT PASCAL PDDel(pFileName);
;
;       ENTRY
;          pFileName (PSZ) - Filename is the ASCIIZ path name of the file
;                            to be deleted.
;
;       EXIT
;           SUCCESS
;               EAX = 0
;
;           FAILURE
;               Returns non-zero error code in EAX
;
;       STEPS
;           Call w_Unlink to delete the file
;
;       CALLS
;           w_Unlink
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING

Procedure PDDel,NEAR

ArgVar    pszFile,DWORD
LocalVar  pddel_sel,DWORD
LocalVar  errCode,DWORD

        EnterProc
        SaveReg <esi, edi, ebx, ds, es>

        push    ds
        pop     es
        mov     edi,[pszFile]           ; get the asciiz file name
        sub     al,al
        mov     ecx,-1
        repne   scasb                   ; calculate the length
        not     ecx
        cmp     ecx,MAXPATHLEN
        mov     eax,ERROR_FILE_NOT_FOUND
        mov     [errCode],eax
        ja      delx                    ; name is too long

        xor     eax,eax                 ; zero the selector
        mov     [pddel_sel],eax
        lea     edx,[pddel_sel]
        SSToDS  edx
        CCALL32 SELLdrDesc, <[pszFile], ecx, edx>       ; grow a selector
        mov     [errCode],eax
        or      eax,eax
        jnz     delx

        push    ds                      ; save ds
        mov     ds,[pddel_sel]
        xor     edx,edx                 ; ds:dx points to filename

        CALL16  w_Unlink                ; delete the file
        pop     ds                      ; restore ds
        jnc     delfinis                ; no error
        xor     eax,eax
delfinis:
        mov     [errCode],eax           ; save error code

        CCALL32 SELFreeGDT, <[pddel_sel]>      ; free the selector

        or      eax,eax
        jz      short delx
        cmp     [errCode],0             ; do not overwrite
        jnz     short delx              ;   preexisting nonzero errCode
        mov     [errCode],eax

delx:
        mov     eax,[errCode]
        RestoreReg <es, ds, ebx, edi, esi>
        ExitProc
EndProc PDDel

;***LP+ PLDGetDateTime - Get the date and time
;
;       Get the date and time
;
;       Void PLDGetDateTime(pDateTime);
;
;       ENTRY  pDateTime - pointer to Date Time structure
;
;       EXIT   none
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING

Procedure PLDGetDateTime,NEAR

ArgVar   pDateTime, DWORD

        EnterProc
        SaveReg <esi, edi, ebx, ds, es>
        mov     edi,[pDateTime]         ; Date/Time structure offset
        DosContext ds
        cli                             ; disable interrupts
        cld
        lea     esi, SISData.SIS_HrsTime ; Top of time struct in GDT info seg
        movsw                           ; Block move for hours, minutes
        movsw                           ;    seconds, hundredths
        lodsw                           ; AX=TimeZone
        inc     esi                     ; Skip over the 'clock interval' word
        inc     esi
        movsw                           ; Block move for Day-of-month,
        movsw                           ;    month, and year
        stosw                           ; TimeZone
        movsb                           ; Day of week
        sti                             ; enable interrupts
        RestoreReg <es, ds, ebx, edi, esi>
        LeaveProc
        ret
EndProc PLDGetDateTime

LOAD_TUNEDOS4_SWP segment
;***LP+ PLDGetVerString - Get OS/2 Version String for Process Level Dump
;
;       Void PLDGetVerString(pVerStr, pVerLen)
;
;       ENTRY  pkPDPB - pointer to the Process Level Dump Structure
;
;       EXIT   0  - Successful
;              !0 - Error Code
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING

Procedure PLDGetVerString,NEAR

        ArgVar  pVerStr  DWORD
        ArgVar  pVerLen  DWORD

        EnterProc
        SaveReg    <ebx, ecx>

        mov        ecx,[pVerStr]           ; (ECX) = pointer to version str
        lea        ebx,[Header]
        mov        [ecx],ebx

        mov        ebx,[pVerLen]           ; (EBX) = pointer to version Len
        mov        ecx,HeaderLen
        mov        [ebx],ecx

        RestoreReg <ecx, ebx>
        LeaveProc
        ret

EndProc PLDGetVerString
LOAD_TUNEDOS4_SWP ENDS
LOAD_TUNEDOS12_SWP segment
;***LP+ PLDEnterCritSec - Enter a critical section
;
;       Call w_EnterCritSec to enter a critical section
;
;       ULONG    PLDEnterCritSec()
;
;       ENTRY
;           nothing
;       EXIT
;           SUCCESS
;               EAX = 0
;
;           FAILURE
;               Returns non-zero error code in EAX
;
;
;       CALLS
;           w_EnterCritSec
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING

Procedure PLDEnterCritSec

        EnterProc
        SaveReg    <esi, edi, ebx, ecx, edx, ds, es>
        CALL16     w_EnterCritSec

        RestoreReg <es, ds, edx, ecx, ebx, edi, esi>
        LeaveProc
        ret
EndProc PLDEnterCritSec
;***LP+ PLDExitCritSec - Exit a critical section
;
;       Call w_ExitCritSec to enter a critical section
;
;       ULONG    PLDExitCritSec()
;
;       ENTRY
;           nothing
;       EXIT
;           SUCCESS
;               EAX = 0
;
;           FAILURE
;               Returns non-zero error code in EAX
;
;
;       CALLS
;           w_ExitCritSec
;
        ASSUME  DS:FLAT,ES:FLAT,SS:NOTHING,FS:NOTHING,GS:NOTHING

Procedure PLDExitCritSec

        EnterProc
        SaveReg    <esi, edi, ebx, ecx, edx, ds, es>
        CALL16      w_ExitCritSec

        RestoreReg <es, ds, edx, ecx, ebx, edi, esi>
        LeaveProc
        ret
EndProc PLDExitCritSec
LOAD_TUNEDOS12_SWP ENDS

EndCode

        end
