;       SCCSID = @(#)iniproc1.asm       6.17 92/03/24
        page    78,132
        title   Iniproc1, System Initialization Process - Part 1

SCCSID  equ     "@(#)iniproc1.asm       6.17 92/03/24"

;                 IBM/Microsoft Confidential
;
;           Copyright (c) IBM Corporation  1987, 1990
;           Copyright (c) Microsoft Corp.  1987, 1990
;                     All Rights Reserved

;
; SOURCE FILE NAME: Iniproc1
;
; DESCRIPTIVE NAME: System Initialization Process - Part 1
;
; FUNCTION: To complete initialization of the CP/DOS system
;
; NOTES:
;   DEPENDENCIES: None
;   RESTRICTIONS: None
;
; ENTRY POINTS:
;             syiAbortR3         - Display a message and halt
;             syiDisplayMessageR3 - Display a message
;             syiProcess         - Complete system initialization
;
; EXTERNAL REFERENCES:
;                DosAllocSeg     - Allocate a segment
;                DosClose        - Close a file
;                DosDupHandle    - Duplicate a file handle
;                DosError        - Suspend hard error processing
;                DosExit         - Terminate a thread
;                DosGetMessage   - Retrieve a message
;                DosGetProcAddr  - Get the address of a module
;                DosCreateThread - Create a thread
;                DosIRead        - Read via handle
;                DosIWrite       - Write via handle
;                DosLoadModule   - Load a module
;                DosMakePipe     - Create a pipe
;                DosOpen         - Open a file
;                DosDevIOCtl     - Issue DosDevIOCtl
;                DosMove         - Move a file
;                DosDelete       - Delete a file
;                DosPutMessage   - Display a message
;                DosSetPrty      - Set thread's priority
;                DosSetMaxFH     - Set Max file handles
;                DosSetRelMaxFH  - Set Relative Max file handles
;                KbdFlushBuffer  - Flush the keyboard buffer
;                KbdStringIn     - Read a string from the keyboard
;                PanicWrite      - Display a message
;                SICG            - Perform initialization function
;                syicpActivate - Activate primary code page
;                syicpInit       - Build codepage data information block
;                syiInitEnvironment - initialize the SysInit
;                                  environment from CONFIG.SYS
;                syiInstallDeviceDrivers - Install all user specified
;                                          device drivers
;                syiFATAutoCheck - Run autocheck on dirty fat partitions
;;F74378 Remove  syiResetINIFiles - Check to see if we should reset
;                                   the .INI files and the CONFIG.SYS
;                syiStartDaemonProcesses - Start all user
;                                  specified asynchronous processes
;                                  (except PM apps)
;                syiStartAltF1Process - Start ALT-F1 process if needed ;F74378
;                syi2StartDaemonProcesses - Start all user       ;80080
;                                  specified asynchronous processes
;                                  (PM apps)
;                syiStartShell - Start the protected mode shell
;                syiStartDOSMode - Start DOS mode
;
;
;       Change History
;
;       55163   10/02/92        Change to explicity load OS2CHAR during sysinit
;       86005   06/15/94   ANK  Display meaningful message when the floppy/DASD
;                               device support failed to initialize
;       86950   06/17/94   TPL  Use CONFIG.SYS instead of OS2LDR for confirmation
;       90474   07/22/94   ACW  Add UNILOCK support
;       90611   07/25/94   CRS  Enhance syiCheckFileSys to support RIPL
;       76643   08/15/95   EMC  Display error if unable to allocate all Fatcache
;

        subttl  Data Structures
        page
        .xlist
        .xcref
        .sall
        include basemid.inc           ; Message IDs
        include basemaca.inc          ; CP/DOS macros
        include fnoinit.inc
        include osmaca.inc            ; CP/DOS macros
        include dosseg.inc            ; CP/DOS segments
        include error.inc             ; CP/DOS error codes
        include inisms.inc            ; SysInit Message Segment
        include infoseg.inc           ; System Information Segment
        include inicfg.inc            ; CONFIG.SYS data structures
        include mi.inc
        include pmode.inc             ; Protected mode data structures
;MDLL   include kbdord.inc
;MDLL   include msgord.inc
        include ordinals.inc
;MDLL   include sesmgord.inc
;MDLL   include vioord.inc
        include sicg.inc              ; SICG packets
        include struc.inc             ; Structured assembler macros
        include doshlp.inc
        include bsedev.inc
        .list
        .cref

        ModName  , FNO_INIPROC1_ASM
        CpuMode 386

        extrn   syiAbortR3:near
        extrn   syiDisplaySavedMessagesR3:near
        extrn   syiFATAutoCheck:near
;F74378 Remove extrn   syiResetINIFiles:near
        extrn   syiInitEnvironment:near
        extrn   syiInstallDeviceDrivers:near
        extrn   syiPauseOnErrorR3:near
        extrn   syiShowMessageR3:near
        extrn   syiStartDOSMode:near
        extrn   syiStartDaemonProcesses:near
        extrn   syi2StartDaemonProcesses:near        ;80080
        extrn   syiStartAltF1Process:near        ;Feature 74378
        extrn   syiStartShell:near
        extrn   syiWordToDecR3:near
        extrn   syicpActivate:near
        extrn   syicpInit:near
        extrn   syiDisplayMessageR3:near             ;76643

        ReferGDT        GDT_DOSALLOCSEG,WORD
        ReferGDT        GDT_DOSCHGFILEPTR,WORD
        ReferGDT        GDT_DOSCLOSE,WORD
        ReferGDT        GDT_DOSCREATETHREAD,WORD
        ReferGDT        GDT_DOSDUPHANDLE,WORD
        ReferGDT        GDT_DOSERROR,WORD
        ReferGDT        GDT_DOSEXIT,WORD
        ReferGDT        GDT_DOSFREEMODULE,WORD
        ReferGDT        GDT_DOSFREESEG,WORD
        ReferGDT        GDT_DOSGETPROCADDR,WORD
        ReferGDT        GDT_DOSGLOBALSEG,WORD
        ReferGDT        GDT_DOSIQAPPTYPE,WORD
        ReferGDT        GDT_DOSIREAD,WORD
        ReferGDT        GDT_DOSISEMWAIT,WORD
        ReferGDT        GDT_DOSIWRITE,WORD
        ReferGDT        GDT_DOSLOADMODULE,WORD
        ; ReferGDT        GDT_DOSLOGMODE,WORD  removed by CP20 DCR 1152
        ReferGDT        GDT_DOSMAKEPIPE,WORD
        ReferGDT        GDT_DOSOPEN,WORD
        ReferGDT        GDT_DOSDEVIOCTL,WORD
ifdef TRYBUY
        ReferGDT        GDT_DOSDEVIOCTL2,WORD           ;UniLock
endif
        ReferGDT        GDT_DOSMOVE,WORD
        ReferGDT        GDT_DOSDELETE,WORD
        ReferGDT        GDT_DOSREALLOCSEG,WORD
        ReferGDT        GDT_DOSSETCP,WORD
        ReferGDT        GDT_DOSSETPRTY,WORD
        ReferGDT        GDT_DOSSICG,WORD
        ReferGDT        GDT_PANICWRITE,WORD
        ReferGDT        GDT_DOSSETMAXFH,WORD
        ReferGDT        GDT_DOSISETRELMAXFH,WORD

        ReferInitGlobal CFG_AutoCheck,BYTE                    ;### AC DCR 1520
        ReferGlobal     initfatchkdsk,BYTE  ; init chkdsk of fat boot partition ;### AC DCR 1520
        ReferGlobal     SISData
        ReferFlat       _smDelaySwap,BYTE       ; if true don't start swapper


INITDATA segment

public _CacheToAlloc            ;76643 - used as flag in init code, and as the
_CacheToAlloc    dd         0   ;76643   amount of cache to alloc in filesys

;       SICG packet to initialize Kernel DBCS support

sicg_packet_1   dw         SICGFUN1

;       SICG packet to remove SICG and do final initialization

sicg_packet_2   dw         SICGFUN2

;       SICG packet to call ring 0 message routine

        public sicg_packet_6, sicg_packet_6_d
sicg_packet_6   dw         SICGFUN6
sicg_packet_6_d sicg_pkt6  <>

sicg_packet_9   dw         SICGFUN9
sicg_packet_9_d sicg_pkt9  <>

;       SICG packet to call ring 0 Panic routine

        public sicg_packet_D, sicg_packet_D_d
sicg_packet_D   dw         SICGFUND
sicg_packet_D_d sicg_pktD  <>

;       SICG packet to reinitialize swapper

sicg_packet_E   dw         SICGFUNE

;       SICG packet to initialize DLL emulator

sicg_packet_14  dw         SICGFUN14

;       SICG packet to query pipe

sicg_packet_15  dw         SICGFUN15
sicg_packet_15_d sicg_pkt15  <>

;       SICG packet to call DosHelpProtGetMessage service

        public sicg_packet_16, sicg_packet_16_d
sicg_packet_16          dw         SICGFUN16
sicg_packet_16_d        sicg_pkt16 <>

        public sicg_packet_1A, sicg_packet_1A_d
sicg_packet_1A          dw         SICGFUN1A
sicg_packet_1A_d        sicg_pkt1A <>

;       Addresses of dynamic link entry points within the Kernel

                public pDosAllocSeg
pDosAllocSeg    label  dword
                dw     0,GSEL GDT_DOSALLOCSEG+RPL_RING3

                public pDosClose
pDosClose       label  dword
                dw     0,GSEL GDT_DOSCLOSE+RPL_RING3

                public pDosChgFilePtr
pDosChgFilePtr  label  dword
                dw     0,GSEL GDT_DOSCHGFILEPTR+RPL_RING3

                public pDosCreateThread
pDosCreateThread label   dword
                dw     0,GSEL GDT_DOSCREATETHREAD+RPL_RING3

pDosDupHandle   label  dword
                dw     0,GSEL GDT_DOSDUPHANDLE+RPL_RING3

pDosError       label  dword
                dw     0,GSEL GDT_DOSERROR+RPL_RING3

                public pDosExit
pDosExit        label  dword
                dw     0,GSEL GDT_DOSEXIT+RPL_RING3

                public pDosFreeModule
pDosFreeModule  label  dword
                dw     0,GSEL GDT_DOSFREEMODULE+RPL_RING3

                public pDosFreeSeg
pDosFreeSeg     label  dword
                dw     0,GSEL GDT_DOSFREESEG+RPL_RING3

                public pDosGetProcAddr
pDosGetProcAddr label  dword
                dw     0,GSEL GDT_DOSGETPROCADDR+RPL_RING3

                public pDosGlobalSeg
pDosGlobalSeg   label  dword
                dw     0,GSEL GDT_DOSGLOBALSEG+RPL_RING3

                public pDosLoadModule
pDosLoadModule  label  dword
                dw     0,GSEL GDT_DOSLOADMODULE+RPL_RING3

;               Removed by CP20 DCR 1152
;                public pDosLogMode
;pDosLogMode     label  dword
;                dw     0,GSEL GDT_DOSLOGMODE+RPL_RING3

pDosMakePipe    label  dword
                dw     0,GSEL GDT_DOSMAKEPIPE+RPL_RING3

                public pDosOpen
pDosOpen        label  dword
                dw     0,GSEL GDT_DOSOPEN+RPL_RING3

                public pDosDevIOCtl
pDosDevIOCtl    label  dword
                dw     0,GSEL GDT_DOSDEVIOCTL+RPL_RING3
ifdef TRYBUY
                public pDosDevIOCtl2                     ;UniLock
pDosDevIOCtl2   label  dword                             ;UniLock
                dw     0,GSEL GDT_DOSDEVIOCTL2+RPL_RING3 ;UniLock
endif

                public pDosMove
pDosMove        label  dword
                dw     0,GSEL GDT_DOSMOVE+RPL_RING3

                public pDosDelete
pDosDelete      label  dword
                dw     0,GSEL GDT_DOSDELETE+RPL_RING3

                public pDosReallocSeg
pDosReallocSeg  label  dword
                dw     0,GSEL GDT_DOSREALLOCSEG+RPL_RING3

                public pDosRead
pDosRead        label  dword
                dw     0,GSEL GDT_DOSIREAD+RPL_RING3

                public pDosWrite
pDosWrite       label  dword
                dw     0,GSEL GDT_DOSIWRITE+RPL_RING3

                public pDosSemWait              ;80080
pDosSemWait     label  dword
                dw     0,GSEL GDT_DOSISEMWAIT+RPL_RING3

                public pDosSetCp
pDosSetCp       label  dword
                dw     0,GSEL GDT_DOSSETCP+RPL_RING3

pDosSetPrty     label  dword
                dw     0,GSEL GDT_DOSSETPRTY+RPL_RING3

                public  pPanicWrite
pPanicWrite     label  dword
                dw     0,GSEL GDT_PANICWRITE+RPL_RING3

                public pDosIQAppType
pDosIQAppType   label   dword
                dw     0,GSEL GDT_DOSIQAPPTYPE+RPL_RING3

                public pSICG
pSICG           label  dword
                dw     0,GSEL GDT_DOSSICG+RPL_RING3

pDosSetMaxFH    label  dword
                dw     0,GSEL GDT_DOSSETMAXFH+RPL_RING3

pDosSetRelMaxFH label  dword
                dw     0,GSEL GDT_DOSISETRELMAXFH+RPL_RING3

;       Table of dynamic link entry points within loadable modules
;       needed by System Initialization

dynamic_link_table equ $              ; pointers to table entries
        dw      pDosExecPgm
        dw      pDosGetMessage        ; must be near the front of the
                                      ;   list so we can retrieve
                                      ;   messages if any of the other
                                      ;   entry points are not found
        dw      pDosPutMessage
        dw      pDosCloseMessageFile
        dw      pKbdFlushBuffer
        dw      pKbdStringIn
        dw      pKbdCharIn
        dw      pKbdSetCp
        dw      pVioSetCp
        dw      pDosSMRegisterDD      ; PTR B705349 - DOSSMREGISTERDD
        dw      pDosSemSet
        dw      pDosSemClear
        dw      pDosSMSysInitSem
no_dynamic_links equ ($-dynamic_link_table)/2

;       Data structures defining each entry point needed

entry_struc     struc                 ; entry point structure
entry_address   dd     ?              ; address of entry point
entry_module    dw     ?              ; address of module structure
entry_ordinal   dw     ?              ; entry point ordinal
entry_struc     ends

        public  pDosExecPgm, pDosGetMessage, pDosPutMessage
        public  pKbdSetCp, pVioSetCp, pKbdFlushBuffer, pKbdStringIn
        public  pDosSMSysInitSem, pKbdCharIn
        public  pDosCloseMessageFile
pDosExecPgm      entry_struc<?, hDosCalls, ORD_DOSEXECPGM>
pDosGetMessage   entry_struc<?, hDosCalls, ORD_MSGTRUEGETMESSAGE>       ;MDLL
pDosPutMessage   entry_struc<?, hDosCalls, ORD_MSGPUTMESSAGE>           ;MDLL
pDosCloseMessageFile entry_struc<?, hDosCalls, ORD_MSGCLOSEMESSAGEFILE> ;MDLL
pKbdFlushBuffer  entry_struc<?, hDosCalls, ORD_KBDDOSFLUSHBUFFER>       ;MDLL
pKbdStringIn     entry_struc<?, hDosCalls, ORD_KBDDOSSTRINGIN>          ;MDLL
pKbdCharIn       entry_struc<?, hDosCalls, ORD_KBDDOSCHARIN>            ;MDLL
pKbdSetCp        entry_struc<?, hDosCalls, ORD_KBDDOSSETCP>             ;MDLL
pVioSetCp        entry_struc<?, hDosCalls, ORD_VIODOSSETCP>             ;MDLL
pDosSMRegisterDD entry_struc<?, hDosCalls, ORD_SMGDOSSMREGISTERDD>      ;MDLL
pDosSemSet       entry_struc<?, hDosCalls, ORD_DOSSEMSET>
pDosSemClear     entry_struc<?, hDosCalls, ORD_DOSSEMCLEAR>
pDosSMSysInitSem entry_struc<?, hDosCalls, ORD_SMGDOSSMSYSINIT>         ;MDLL

;       Data structures defining each load module needed

module_struc    struc                 ; module structure
module_handle   dw     ?              ; module handle
module_name     db     ?              ; name of module
module_struc    ends

;MDLL hKbdCalls       dw     ?
;MDLL                 db     'KBDCALLS',0
;MDLL hMsgCalls       dw     ?
;MDLL                 db     'MSG',0
;MDLL hVioCalls       dw     ?
;MDLL                 db     'VIOCALLS',0
hDosCalls       dw     ?
                db     'DOSCALL1',0
;MDLL hSesMgr         dw     ?                        ; PTR B705349 - DOSSMREGISTERDD
;MDLL                 db     'SESMGR',0               ; PTR B705349 - DOSSMREGISTERDD
;MDLL hOS2Char        dw     ?                        ;55163
;MDLL                 db     'OS2CHAR',0              ;55163

;       Data structures defining messages issued

get_cache_failed        SMT     <MSG_SYSINIT_CANT_GET_CACHE,0> ;76643

tbl_more_mem            SMT     <MSG_SYSINIT_MORE_MEM,0>
tbl_cant_open_con       SMT     <MSG_SYSINIT_CANT_OPEN_CON,0>
tbl_wrong_handle        SMT     <MSG_SYSINIT_WRONG_HANDLE,0>

tbl_cannot_load         SMT     <MSG_SYSINIT_CANT_LOAD_MOD,1>
                        SMT_Var <object_name>

tbl_ept_missing         SMT     <MSG_SYSINIT_EPT_MISSING,2>
var_library             SMT_Var <>
var_entry_point         SMT_Var <>

        public tbl_prompt
tbl_prompt              SMT     <MSG_SYSINIT_PRESS_ENTER,0>

        public tbl_lost_messages
tbl_lost_messages       SMT     <MSG_SYSINIT_MSG_LOST,1>
                        SMT_Var <decimalascii>

        public tbl_system_stopped
tbl_system_stopped      SMT     <MSG_SYSINIT_SYS_STOPPED,0>

        public  tbl_mFSD_failure
tbl_mFSD_failure        SMT     <MSG_SYSINIT_START_NO_LOAD,0>

        public  tbl_mFSD_failure_2
tbl_mFSD_failure_2      SMT     <MSG_SYSINIT_START_NO_INIT,0>

        public  tbl_syi_boot_err
tbl_syi_boot_err        SMT     <MSG_SYSINIT_BOOT_ERROR,0>

        public  tbl_filesys_unavail
tbl_filesys_unavail     SMT     <MSG_BOOT_DRIVE_NOT_ACCESSIBLE,0> ; ANK- 86005

;       Miscellaneous data fields
fatdriveletter        db  'D:',0     ; name of drive          ;### AC DCR 1520
fatdrive_handle       dw  ?                                   ;### AC DCR 1520
fatdrive_buffer       db  512 dup(?)                          ;### AC DCR 1520
fatdrive_length       dw  512                                 ;### AC DCR 1520
console_file          db  'CON',0     ; name of console file

        public open_action
open_action           dw  ?           ; action taken by DosOpen
standard_input_handle dw  ?           ; handle for Standard Input File
        public standard_output_handle
standard_output_handle dw -1          ; handle for Standard Output File
                                      ; NOTE: this field must be initialized
                                      ;       to -1 so DosDupHandle will
                                      ;       create a new handle
standard_error_handle dw  -1          ; handle for Standard Error File
                                      ; NOTE: this field must be initialized
                                      ;       to -1 so DosDupHandle will
                                      ;       create a new handle
stderr_handle         dw 2            ;handle for dupping

stderr_buf       db 0dh,0ah
stderr_buflen    dw 0
        public message_file_name
message_file_name db   'OSO001.MSG',0 ; name of message file
sysinit_maxfh         dd 100
sysinit_negminfh      dd -80          ; b723814
        public clock_name
clock_name      db     'CLOCK$  ',0 ; name of clock device driver

StartDrive    db     'C:',0
OS2Loader     db     '?:\OS2LDR', 0
ConfigDotSys  db     '?:\CONFIG.SYS', 0
Doscall1DotDll db     '?:\DOSCALL1.DLL', 0      ;149691

GT16MBParmPacket db     2 dup(0) ; Command Information = 0, Drive Unit = 0

GT16MBDataPacket db    31 dup(0) ;Extended BPB
                 dw    0         ;Number of cylinders
                 db    0         ;Device type
GT16MBDevAttr    dw    0         ;Last word of data packet

public _DDwith24BitDMA
_DDwith24BitDMA db   0          ; non-zero if a block device has 24bit DMA

device_handle   dw   0

INITDATA ends


INITBSS segment

StdErr_Intercept_ID   dw  ?           ;thread ID of inteceptor
StdErr_Intercept_Die  db  ?           ;signal for thread to die
StdErr_Intercept_Stack dw 512 dup(?)  ;stack for interceptor

pipe_read_handle      dw  ?           ;handle for reading pipe
pipe_write_handle     dw  ?           ;handle for writing pipe

        public error_messages_displayed
error_messages_displayed db 0         ; 1 = error message has been
                                      ;     displayed
        public MESSAGE_BUFFER_LENGTH
MESSAGE_BUFFER_LENGTH   equ     2048
        public tmp_msg_buffer, message_buffer, message_length
tmp_msg_buffer  db     1048 dup(?)    ; non expanded message buffer
message_buffer  db     MESSAGE_BUFFER_LENGTH dup(?)    ; message buffer
message_length  dw     ?              ; message length

object_name     db     64 dup(0)      ; name of missing module
object_name_len equ    $-object_name

        public decimalascii
decimalascii     db     6 dup(?)      ; decimal ASCII count buffer
stderr_sem       dd     0
stderr_sleep_sem dd     0
INITBSS ends

;       Structure of a double word

double_word     struc
lsw             dw     ?              ; least significant word
msw             dw     ?              ; most significant word
double_word     ends


;
; SUBROUTINE NAME: syiProcess
;
; DESCRIPTIVE NAME: System Initialization Process
;
; FUNCTION:      To open the Standard Input, Output, and Error files,
;                load the device drivers,
;                create DOS mode, start daemon processes, start
;                the program selector, and finish system
;                initialization
;
;                  in User Mode.
;                syiProcess does not return to its caller. It
;                  exits by calling SICG for the last time.
;
; ENTRY POINT: syiProcess
;    LINKAGE:    Call (far)
;
; INPUT:         None
;
; EXIT-NORMAL: Call SICG, which calls DosExit
;
; EXIT-ERROR:    None
;
; EFFECTS:       None
;
; INTERNAL REFERENCES:
;    ROUTINES:
;                syiDisplaySavedMessages - Display all saved
;                                  messages
;                syiGetLoadableEntries - Find dynamic link
;                                  points in loadable modules
;                syiInstallDeviceDrivers - Install device drivers
;                syiQuery16MBDevices
;                syiOpenFiles - Open standard files
;                syiStartDaemonProcesses - Start daemon procs
;                syi2StartDaemonProcesses - Start daemon PM procs   ;80080
;                syiStartAltF1Process - Start AltF1 proc   ;Feature 74378
;                syiStartShell - Start the program selector
;                syiStartDOSMode - Start DOS mode
;
; EXTERNAL REFERENCES:
;    ROUTINES:
;                SICG            - Perform initialization function
;                syicpActivate - Activate primary code
;                                  page
;                syicpInit - Build Codepage Data Information
;                                  Block segment
;                syiInitEnvironment - Initialize the SysInit
;                                  environment
;
;
; Procedure syiProcess(System Initialization Call Gate)
;
; Call syiOpenFiles to open the standard input, standard output,
;     and standard error files
; Call syiInitStdErrIntercept to create a pipe for intercepting
;     writes to standard error
; Call syicpInit(CONFIG.SYS data segment) to build the Codepage
;     Data Information Block
; Call SICG(1) to initialize the Kernel DBCS functions
; Call syiGetLoadableEntries to get the addresses of all
;     dynamic link entry points in loadable modules needed by the
;     System Initialization Process
; Call syicpActivate to activate the primary codepage
; Call syiDisplaySavedMessages to display any messages generated
;     during System Initialization
; Call syiInitEnvironment to fill in the environment
; Call syiBeginStdErrIntercept to begin interception
; Call syiInstallDeviceDrivers(CONFIG.SYS data segment)
;     to load and install all installable device drivers
; Call syiEndStdErrIntercept to terminate interception
; Call syiQuery16MBDevices to see if ALL drives support > 16 MB
; Call syiFATAutoCheck to clean dirty partitions
; Call syiStartDOSMode(CONFIG.SYS data segment) to start
;     DOS mode and install all installable DOS mode device drivers
; Call syiBeginStdErrIntercept to begin interception
; Call syiEndStdErrIntercept to terminate interception
; Call syiBeginStdErrIntercept to begin interception
; Call syiStartAltF1Process                                ;Feature 74378
; Call syiStartDaemonProcesses(CONFIG.SYS data segment) to
;     start the Daemon processes
; Call syiEndStdErrIntercept to terminate interception
; Call syiTerminateStdErrIntercept to close the intercept pipe
; Call syiStartShell(CONFIG.SYS data segment) to start the
;     program selector
;    ;Start 80080 changes
; Call syiInitStdErrIntercept to create a pipe for intercepting
;     writes to standard error
; Call syiBeginStdErrIntercept to begin interception
; Call syi2StartDaemonProcesses(CONFIG.SYS data segment) to
;     start the Daemon processes
; Call syiEndStdErrIntercept to terminate interception
; Call syiTerminateStdErrIntercept to close pipe and kill thread
;    ;End 80080 changes
; Call SICG(2) to remove the System Initialization Call Gate, free
;     the System Initialization Process segments, and terminate
;     the System Initialization Process
;
; End syiProcess

        FARCODE INITR3
INITR3CODE segment

Procedure syiProcess,faronly
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing

        DosInitContext ds

;       Open the Standard Input, Standard Output, and Standard Error files

        call    syiOpenFiles

;       Open pipe for intercepting writes to standard error.

        call    syiInitStdErrIntercept

;       Fill in the SysInit environment

        call    syiInitEnvironment

;       Check availability of file system by opening "config.sys" file using
;       DosOpen() ;  fail - exit.               86005

        call    syiCheckFileSys

        .if <nonzero  ax>

           mov    si,offset tbl_filesys_unavail
           call   syiAbortR3

        .endif

;       Build the Codepage Data Information Block

        call    syicpInit

;       Get the addresses of all loadable dynamic link entry points

        call    syiGetLoadableEntries

;       Display any error messages generated during base DD load

        call    syiDisplaySavedMessagesR3

;       Initialize the Kernel DBCS functions

        push    ds
        push    offset DOSINITDATA:sicg_packet_1
        call    pSICG

;       Initialize FP emulator

        push    ax
        smsw    ax
        test    ax,CR0_EM               ; if emulating NPX
        .if <nz> near
           push    ds
           push    offset DOSINITDATA:sicg_packet_14
           call    pSICG
           .if <c> near
              mov    si,offset tbl_more_mem
              call   syiAbortR3
           .endif
        .endif
        pop     ax

;       Activate the primary codepage

        call    syicpActivate

        push    ds:[sysinit_maxfh]
        call    [pDosSetMaxFH]

;       Load and install all user specified device drivers

        call    syiBeginStdErrIntercept
        call    syiInstallDeviceDrivers
        call    syiEndStdErrIntercept

;       Run AutoCheck on dirty FAT partitions         ;### AC DCR 1520
        .if <DOSINITDATA:CFG_AutoCheck[0] ne 0>       ; Do fat autocheck if AC token present
             call    syiFATAutoCheck                  ;### AC DCR 1520
        .else
             push  es                       ; We must make sure initfatchkdsk is 0
             DosContext es                  ; If we don't call syifatautocheck
             mov     initfatchkdsk,0        ; Zero out value
             pop   es                       ; Return es
        .endif

;       Make sure all drives are attached to adapters that support > 16 MB

        call    syiQuery16MBDevices

;F74378 Remove;       See if we should reset the .INI files and CONFIG.SYS
;F74378 Remove
;F74378 Remove        call    syiResetINIFiles
;F74378 Remove

;       Reinitialize the swapper, now that FSDs are loaded

        push    ds
        push    offset DOSINITDATA:sicg_packet_E
        call    pSICG
;check to see if install is running if so do not display msg
        push  es                       ;149422
        FlatContext es                 ;149422
        ; if DELAYSWAP in effect skip for now
        .if <es:_smDelaySwap e 0>      ;149422
; 76643 - If "ALL" FAT cache was not allocated, display an error message
        .if <DOSINITDATA:_CacheToAlloc ne 0>    ;76643
           push  si                             ;76643
           mov   si,offset get_cache_failed     ;76643
           call  syiDisplayMessageR3            ;76643
           pop   si                             ;76643
        .endif                                  ;76643
      .endif                                    ;149422
      pop es                                    ;149422

;       Display any error messages generated since base DD load

        call    syiDisplaySavedMessagesR3

        call    syiCloseFiles

        push    ds
        push    offset DOSINITDATA:[sysinit_negminfh]
        push    ds
        push    offset DOSINITDATA:[sysinit_maxfh]
        call    [pDosSetRelMaxFH]

;       Create the 3.x Box (if required)

        call    syiStartDOSMode

;       Close any message files (CALL= or RUN= statement might try to
;                                replace message files)

        call    [pDosCloseMessageFile].entry_address

;       Start the Daemon processes (if any)

        call    syiBeginStdErrIntercept
        ; Start Alt-F1 Process before DaemonProcesses      ;Feature 74378
        call    syiStartAltF1Process                       ;Feature 74378
        call    syiStartDaemonProcesses
        call    syiEndStdErrIntercept

;       Close pipe for intercepting writes to standard error.
        ; We must close the pipes before starting the shell   ;80080
        ; so that the handles won't be inherited.             ;80080

        call    syiTerminateStdErrIntercept

;       Close any message files again, just before starting shell

        call    [pDosCloseMessageFile].entry_address

;       Start the program selector

        call    syiStartShell

;Begin 80080 changes

;       syi2StartDaemonProcesses will wait for PM to come up
;

;       Open pipe for intercepting writes to standard error

        call    syiInitStdErrIntercept

;       Start the Daemon processes (if any)

        call    syiBeginStdErrIntercept
        call    syi2StartDaemonProcesses
        call    syiEndStdErrIntercept

;       Close pipe for intercepting writes to standard error.

        call    syiTerminateStdErrIntercept

;End 80080 changes
;       Resume hard error processing (for FAT threads)

        push    1                     ; resume hard error processing
        call    [pDosError]


;       Remove the System Initialization Call Gate, free all unneeded
;       segments, and terminate the System Initialization Process

        push    ds
        push    offset DOSINITDATA:sicg_packet_2
        call    pSICG

EndProc syiProcess

CpuMode 286

;
; SUBROUTINE NAME: syiOpenFiles
;
; DESCRIPTIVE NAME: Open system files
;
; FUNCTION:      To open the Standard Input, Output, and Error files
;
; NOTES:         This is an internal subroutine within syiProcess
;
; ENTRY POINT: syiOpenFiles
;    LINKAGE:    Call (near) from syiProcess
;
; INPUT:         None
;
; EXIT-NORMAL: Return to caller (no values returned)
;
; EXIT-ERROR:    None
;
; EFFECTS:       All registers are preserved
;                The following handles are assigned:
;                  0000 = Standard Input File
;                  0001 = Standard Output File
;                  0002 = Standard Error File
;
; INTERNAL REFERENCES:
;    ROUTINES: syiAbortR3 - Halt the system
;
; EXTERNAL REFERENCES:
;    ROUTINES:
;                DosDupHandle    - Duplicate a file handle
;                DosError        - Suspend hard error processing
;                DosOpen         - Open a file
;
;
; Procedure syiOpenFiles
;
; Call DosError(0) to suspend hard error processing
; Call DosOpen('CON:',handle) to assign handle 0000 for the Standard
;     Input file
; If open fails
;   Call syiAbortR3('Cannot open CON')
; endif
; If handle is not 0
;   Call syiAbortR3('Handle 0 not CON')
; endif
;
; Call DosDupHandle(handle,new handle) to assign handle 0001 for
;     Standard Output file
; Call DosDupHandle(handle,new handle) to assign handle 0002 for
;     Standard Error file
;
; End syiOpenFiles

Procedure syiOpenFiles
    assume ds:DOSINITDATA, es:nothing, fs:nothing, gs:nothing, ss:nothing

        SaveReg <ds,es>
        pusha

;       Suspend hard error processing

        push    0                     ; suspend hard error processing
        call    [pDosError]

;       Open the Standard Input File

        push    ds                    ; address of file name
        push    offset DOSINITDATA:console_file
        push    ds                    ; address of file handle
        push    offset DOSINITDATA:standard_input_handle
        push    ds                    ; address of action taken word
        push    offset DOSINITDATA:open_action
        push    0                     ; initial file size
        push    0
        push    0                     ; file attribute
        push    0000000000000001b     ; open flag
;               rrrrrrrrffffeeee      ;   ffff=0000 fail if file doesn't exist
                                      ;   eeee=0001 open if file exists
        push    0000000001000010b     ; open mode
;               dwfrrrrbisssraaa      ;   d = 0 file open
                                      ;   w = 0 write through
                                      ;   f = 0 fail through daemon
                                      ;   b = 0 do not bypass cache
                                      ;   i = 0 inheritable file
                                      ;   sss = 100 deny none
                                      ;   aaa = 010 read/write access
        push    0                     ; reserved double word
        push    0
        call    pDosOpen
        .if     <nonzero ax>
          mov   si,offset tbl_cant_open_con
          call  syiAbortR3
        .endif

;       Verify that the handle for the Standard Input File is 0000
;       and abort if not

        .if     <standard_input_handle ne 0>
          mov   si,offset tbl_wrong_handle
          call  syiAbortR3
        .endif

;       Open the Standard Output File

        push    standard_input_handle ; existing file handle
        push    ds                    ; address of new file handle
        push    offset DOSINITDATA:standard_output_handle
        call    pDosDupHandle

;       Open the Standard Error File

        push    standard_input_handle ; existing file handle
        push    ds                    ; address of new file handle
        push    offset DOSINITDATA:standard_error_handle
        call    pDosDupHandle

;       Return to caller

        popa
        RestoreReg <es,ds>
        ret

EndProc syiOpenFiles

;                                                                             ;### AC DCR 1520
; Procedure syiCheckFatDrive                                                  ;### AC DCR 1520
;                                                                             ;### AC DCR 1520
; Call DosOpen('Drive letter', handle)                                        ;### AC DCR 1520
; DosRead(handle)                                                             ;### AC DCR 1520
;    Check for fat id                                                         ;### AC DCR 1520
;    Check for dirty bit set                                                  ;### AC DCR 1520
; Call DosClose( handle)                                                      ;### AC DCR 1520
;                                                                             ;### AC DCR 1520
; End syiCheckFatDrive                                                        ;### AC DCR 1520
                                                                              ;### AC DCR 1520
Procedure syiCheckFatDrive,near                                               ;### AC DCR 1520
    assume ds:DOSINITDATA, es:nothing, fs:nothing, gs:nothing, ss:nothing     ;### AC DCR 1520
                                                                              ;### AC DCR 1520
        SaveReg <ds,es>                                                       ;### AC DCR 1520
        pusha                                                                 ;### AC DCR 1520

        mov     fatdriveletter,al     ; get drive letter
                                                                              ;### AC DCR 1520
;       Suspend hard error processing                                         ;### AC DCR 1520
                                                                              ;### AC DCR 1520
        push    0                     ; suspend hard error processing         ;### AC DCR 1520
        call    [pDosError]                                                   ;### AC DCR 1520
                                                                              ;### AC DCR 1520
;       Open the volume                                                       ;### AC DCR 1520
                                                                              ;### AC DCR 1520
        push    ds                    ; address of file name                  ;### AC DCR 1520
        push    offset DOSINITDATA:fatdriveletter                             ;### AC DCR 1520
        push    ds                    ; address of file handle                ;### AC DCR 1520
        push    offset DOSINITDATA:fatdrive_handle                            ;### AC DCR 1520
        push    ds                    ; address of action taken word          ;### AC DCR 1520
        push    offset DOSINITDATA:open_action                                ;### AC DCR 1520
        push    0                     ; initial file size                     ;### AC DCR 1520
        push    0                                                             ;### AC DCR 1520
        push    0                     ; file attribute                        ;### AC DCR 1520
        push    0000000000000001b     ; open flag                             ;### AC DCR 1520
;               rrrrrrrrffffeeee      ;   ffff=0000 fail if file doesn't exist;### AC DCR 1520
                                      ;   eeee=0001 open if file exists       ;### AC DCR 1520
        push    1000000000100000b     ; open mode                             ;### AC DCR 1520
;               dwfrrrrbisssraaa      ;   d = 0 file open                     ;### AC DCR 1520
                                      ;   w = 0 write through                 ;### AC DCR 1520
                                      ;   f = 0 fail through daemon           ;### AC DCR 1520
                                      ;   b = 0 do not bypass cache           ;### AC DCR 1520
                                      ;   i = 0 inheritable file              ;### AC DCR 1520
                                      ;   sss = 100 deny none                 ;### AC DCR 1520
                                      ;   aaa = 000 read access               ;### AC DCR 1520
        push    0                     ; reserved double word                  ;### AC DCR 1520
        push    0                                                             ;### AC DCR 1520
        call    pDosOpen                                                      ;### AC DCR 1520
        .if     <ax ne 0>             ;for some reason DosOpen failed
             popa
             mov  ah,2                ;return "2" (not fat)
             jmp  scfd_x
        .endif
                                                                              ;### AC DCR 1520
        push    fatdrive_handle                                               ;### AC DCR 1520
        push    ds                                                            ;### AC DCR 1520
        push    offset fatdrive_buffer                                        ;### AC DCR 1520
        push    size fatdrive_buffer                                          ;### AC DCR 1520
        push    ds                                                            ;### AC DCR 1520
        push    offset fatdrive_length                                        ;### AC DCR 1520
        call    pDosRead                                                      ;### AC DCR 1520
        push    fatdrive_handle                                               ;### AC DCR 1520
        call    pDosClose                                                     ;### AC DCR 1520
        popa
        DosContext <es>                                                       ;### AC DCR 1520
        .if     <fatdrive_buffer+54 eq 'F'> and                                  ;### AC DCR 1520
        .if     <fatdrive_buffer+55 eq 'A'> and                                  ;### AC DCR 1520
        .if     <fatdrive_buffer+56 eq 'T'>                                   ;### AC DCR 1520
             .if     <fatdrive_buffer+37 eq 0>                                   ;### AC DCR 1520
                     mov  ah,0
             .else
                     mov  ah,1
             .endif
        .else                                                                 ;### AC DCR 1520
                     mov  ah,2
        .endif                                                                ;### AC DCR 1520
                                                                              ;### AC DCR 1520
;       Return to caller                                                      ;### AC DCR 1520
scfd_x:                                                                       ;### AC DCR 1520
        RestoreReg <es,ds>                                                    ;### AC DCR 1520
        ret                                                                   ;### AC DCR 1520
                                                                              ;### AC DCR 1520
EndProc syiCheckFatDrive                                                      ;### AC DCR 1520
                                                                              ;### AC DCR 1520
;
; SUBROUTINE NAME: syiCloseFiles
;
; DESCRIPTIVE NAME: Close sysinit files
;
; FUNCTION:      Close file handles 3-sysinit_maxfh
;
; NOTES:         This is an internal subroutine within syiProcess
;
; ENTRY POINT: syiCloseFiles
;    LINKAGE:    Call (near) from syiProcess
;
; INPUT:         None
;
; EXIT-NORMAL: Return to caller (no values returned)
;
; EXIT-ERROR:    None
;
; EFFECTS:       All registers are preserved
;
; INTERNAL REFERENCES:
;    ROUTINES:
;
; EXTERNAL REFERENCES:
;    ROUTINES:
;                DosClose         - Close a file
;
;
; Procedure syiCloseFiles
; for i = 3 to sysinit_maxfh
;   Call DosClose(i)
; endfor
;
; End syiCloseFiles

Procedure syiCloseFiles
    assume ds:DOSINITDATA, es:nothing, fs:nothing, gs:nothing, ss:nothing

        SaveReg <ds,es>
        pusha
        mov     bx,20
        mov     cx,word ptr ds:[sysinit_maxfh]
        sub     cx,bx

sclf1:  push    bx
        call    pDosClose
        inc     bx
        loop    sclf1

;       Return to caller

        popa
        RestoreReg <es,ds>
        ret

EndProc syiCloseFiles

;
; SUBROUTINE NAME: syiGetLoadableEntries
;
; DESCRIPTIVE NAME: Get loadable dynamic link entry point addresses
;
; FUNCTION:      To load the required dynamic link libraries and
;                get the addresses of all entry points needed by the
;                System Initialization Process
;
; NOTES:         This is an internal subroutine within syiProcess
;                This subroutine must be called after the standard
;                  input, standard output, and standard error files
;                  are opened so they get the proper handles
;
; ENTRY POINT: syiGetLoadableEntries
;    LINKAGE:    Call (near) from syiProcess
;
; INPUT:         (DS) = DOSINITDATA
;
; EXIT-NORMAL: pDosxxxx contains the address of the associated
;                         DOSCALLS entry point
;
; EXIT-ERROR:    None
;
; EFFECTS:
;
; INTERNAL REFERENCES:
;    ROUTINES: syiAbortR3 - Halt the system
;
; EXTERNAL REFERENCES:
;    ROUTINES: DosGetProcAddr    - Get the address of a module
;                DosLoadModule   - Load a module
;
;
; Procedure syiGetLoadableEntries
;
; For each of the dynamic link routines needed by the System
;     Initialization Process
;   If the entry point is in a module which has not been loaded yet
;     Call DosLoadModule(library name,module handle) to load the
;         module into memory
;     If DosLoadModule fails
;       Call syiAbortR3(cannot load module xxxxx)
;     endif
;   endif
;   Call DosGetProcAddr(module handle,entry point name,address) to
;       get the address of the entry point
;   If DosGetProcAddr fails
;     Call syiAbortR3(cannot find entry point xxxxx)
;   endif
; endfor
;
; Return
;
; End syiGetLoadableEntries

Procedure syiGetLoadableEntries,near
    assume ds:DOSINITDATA, es:nothing, fs:nothing, gs:nothing, ss:nothing

        SaveReg <ds,es>
        pusha
        EnterProc

;       Find all the dynamic link entry points needed

        mov     si,offset dynamic_link_table
        mov     cx,no_dynamic_links

        .repeat
          SaveReg <si>
          mov   si,[si]

;         See if this entry point is in a module which has not been
;         loaded yet

          mov di,[si].entry_module
          lea ax,ds:[di].module_name  ; save module name for error
          mov var_library.SMT_Var_Ptr.msw,ds ; message
          mov var_library.SMT_Var_Ptr.lsw,ax
          .if <[di].module_handle eq 0>

;           This module must be loaded first

            push ds                 ; address of object name buffer
            push offset DOSINITDATA:object_name
            push object_name_len      ; length of object name buffer
            push ds                   ; address of module name string
            lea ax,ds:[di].module_name
            push ax
            push ds                   ; address of handle word
            lea ax,ds:[di].module_handle
            push ax
            call pDosLoadModule
            .if <nonzero ax>
              mov si,offset tbl_cannot_load
              call syiAbortR3
            .endif
          .endif

;         Get the entry point address

          push  [di].module_handle    ; module handle
          push  0                     ; 0:ordinal of entry point
          push  [si].entry_ordinal
          push  ds                    ; address of address dword
          lea   ax,[si].entry_address
          push  ax
          call  [pDosGetProcAddr]
          .if <nonzero ax>
            mov   [si].entry_address.msw,0
            mov   [si].entry_address.lsw,0
            push  ds
            pop   es
            mov   di,offset DOSINITDATA:decimalascii
            mov   var_entry_point.SMT_Var_Ptr.msw,ds ; save name of entry
            mov   var_entry_point.SMT_Var_Ptr.lsw,di ; point for error
            call  syiWordToDecR3        ; *(es:di) = decimal ascii(AX)
            mov   si,offset tbl_ept_missing
            call  syiAbortR3
          .endif

;         Point to next table entry and loop until all entry points found

          RestoreReg <si>
          add   si,2
        .loop

        ; 55163 - workaround for chkdsk
        ; Load OS2CHAR explicitly                                       ;55163
;MDLL   lea di,hOS2Char                                                 ;55163
;MDLL   lea ax,ds:[di].module_name  ; save module name for error        ;55163
;MDLL   mov var_library.SMT_Var_Ptr.msw,ds ; message                    ;55163
;MDLL   mov var_library.SMT_Var_Ptr.lsw,ax                              ;55163
;MDLL   .if <[di].module_handle eq 0>                                   ;55163
;MDLL     push ds                 ; address of object name buffer       ;55163
;MDLL     push offset DOSINITDATA:object_name                           ;55163
;MDLL     push object_name_len      ; length of object name buffer      ;55163
;MDLL     push ds                   ; address of module name string     ;55163
;MDLL     lea ax,ds:[di].module_name                                    ;55163
;MDLL     push ax                                                       ;55163
;MDLL     push ds                   ; address of handle word            ;55163
;MDLL     lea ax,ds:[di].module_handle                                  ;55163
;MDLL     push ax                                                       ;55163
;MDLL     call pDosLoadModule                                           ;55163
;MDLL     .if <nonzero ax>                                              ;55163
;MDLL       mov si,offset tbl_cannot_load                               ;55163
;MDLL       call syiAbortR3                                             ;55163
;MDLL     .endif                                                        ;55163
;MDLL   .endif                                                          ;55163

;       Return to caller

        LeaveProc
        popa
        RestoreReg <es,ds>
        ret

EndProc syiGetLoadableEntries


; SUBROUTINE NAME: syiInitStdErrIntercept
;
; DESCRIPTIVE NAME: Init standard error intercept mechanism
;
; FUNCTION:      Init the standard error intercept mechanism.
;
; NOTES:         This is an internal subroutine within syiProcess
;
; ENTRY POINT: syiInitStdErrIntercept
;    LINKAGE:    Call (near)
;
; INPUT:         DS = DOSINITDATA
;
; EXIT-NORMAL: Return to caller (no values returned)
;
; EXIT-ERROR:    None
;
; EFFECTS:       None
;
; INTERNAL REFERENCES:
;    ROUTINES: None
;
; EXTERNAL REFERENCES:
;    ROUTINES: DosMakePipe - create a pipe
;
;
; Procedure syiInitStdErrIntercept
;
; Call DosMakePipe to create a pipe
;
; Return
;
; End syiInitStdErrIntercept

Procedure syiInitStdErrIntercept,near,local
    assume ds:DOSINITDATA, es:nothing, fs:nothing, gs:nothing, ss:nothing

;       Create a pipe

        push    ds
        push    offset pipe_read_handle
        push    ds
        push    offset pipe_write_handle
        push    256
        call    pDosMakePipe
        .if     <nonzero ax>
          Panic <"Error creating stderr intercept pipe">
        .endif

;       Return

        ret
EndProc syiInitStdErrIntercept


;
; SUBROUTINE NAME: syiBeginStdErrIntercept
;
; DESCRIPTIVE NAME: Start standard error intercept
;
; FUNCTION:      Start the standard error intercept.
;
; NOTES:         This is an internal subroutine within syiProcess
;
; ENTRY POINT: syiBeginStdErrIntercept
;    LINKAGE:    Call (near)
;
; INPUT:         DS = DOSINITDATA
;
; EXIT-NORMAL: Return to caller (no values returned)
;
; EXIT-ERROR:    None
;
; EFFECTS:       None
;
; INTERNAL REFERENCES:
;    ROUTINES: None
;
; EXTERNAL REFERENCES:
;    ROUTINES: DosCreateThread - create a thread
;                DosSetPrty - set threads priority
;                DosDupHandle - duplocate a handle
;
;
; Procedure syiBeginStdErrIntercept
;
; Call DosDupHandle(pipe_write_handle,standard_error) to redirect standard
;       error to the pipe
; Call DosCreateThread to create the intercept thread
; Call DosSetPrty to change the intercept thread's prioity to time critical
;
; Return
;
; End syiBeginStdErrIntercept

Procedure syiBeginStdErrIntercept,near,local
    assume ds:DOSINITDATA, es:nothing, fs:nothing, gs:nothing, ss:nothing

;       Redirect standard error to the pipe

        push    pipe_write_handle
        push    ds
        push    offset stderr_handle
        call    pDosDupHandle
        .if     <nonzero ax>
          Panic <"Error beginning stderr intercept">
        .endif

;       Clear the error message displayed flag

        mov     error_messages_displayed,0

;       Clear the intercept die flag

        mov     StdErr_Intercept_Die,0

;       Create the intercept thread

        push    cs
        push    offset syiStdErrIntercept
        mov     ax,ds
        or      ax,3
        push    ax
        push    offset StdErr_Intercept_ID
        push    ax
        push    offset StdErr_Intercept_Stack + size StdErr_Intercept_Stack
        call    pDosCreateThread
        .if <zero ax>

;         Change his priority to time critical

          push    2
          push    3
          push    0
          push    StdErr_Intercept_ID
          call    pDosSetPrty
          .if     <nonzero ax>
            Panic <"Error making stderr intercept thread time-critical">
          .endif
        .else
          Panic <"Error creating stderr intercept thread">
        .endif

;       Return

        ret
EndProc syiBeginStdErrIntercept


;
; SUBROUTINE NAME: syiInitStdErrIntercept
;
; DESCRIPTIVE NAME: Standard error intercept
;
; FUNCTION:      Recognize an error message has been issued. This is
;                done by copying message(s) from standard error to
;                standard output and setting a flag.
;
; NOTES:         This is an internal subroutine within syiProcess
;
; ENTRY POINT: syiInitStdErrIntercept
;    LINKAGE:    Jump (near)
;
; INPUT:         DS = DOSINITDATA
;
; EXIT-NORMAL: DosExit
;
; EXIT-ERROR:    None
;
; EFFECTS:       None
;
; INTERNAL REFERENCES:
;    ROUTINES: syiShowMessageR3 - display message
;
; EXTERNAL REFERENCES:
;    ROUTINES: DosRead - read a message
;                DosExit - terminate a thread
;
;
; Procedure syiStdErrIntercept
;
; Loop
;   Call DosRead to get message written to standard error
;   IF die flag is true Call DosExit to terminate the thread
;   Call syiShowMessageR3 to display the message
; Forever
;
; End syiStdErrIntercept

Procedure syiStdErrIntercept,near,local
    assume ds:DOSINITDATA, es:nothing, fs:nothing, gs:nothing, ss:nothing

;       Read an error message

        push    pipe_read_handle
        push    ds
        push    offset message_buffer
        push    size message_buffer
        push    ds
        push    offset message_length
        call    pDosRead
        .if     <nonzero ax>
          Panic <"Error reading stderr intercept data">
        .endif

        .if     <StdErr_Intercept_Die ne 0>

;         Kill me, please

          push    ds
          push    offset stderr_sem
          call    [pDosSemClear].entry_address

          .if     <nonzero ax>
            Panic <"Error clearing stderr semaphore">
          .endif

          push    0     ;return code = 0
          push    0     ;kill only this thread
          call    pDosExit
        .endif

;       Set flag to indicate an error message has been issued

        mov     error_messages_displayed,1

;       Display the message

        call    syiShowMessageR3
        .if     <nonzero ax>
          Panic <"Error writing stderr intercept data">
        .endif

;       Loop forever

        jmp     syiStdErrIntercept
EndProc syiStdErrIntercept


;
; SUBROUTINE NAME: syiEndStdErrIntercept
;
; DESCRIPTIVE NAME: End standard error intercept
;
; FUNCTION:      End the standard error intercept.
;
; NOTES:         This is an internal subroutine within syiProcess
;
; ENTRY POINT: syiEndStdErrIntercept
;    LINKAGE:    Call (near)
;
; INPUT:         DS = DOSINITDATA
;
; EXIT-NORMAL: Return to caller (no values returned)
;
; EXIT-ERROR:    None
;
; EFFECTS:       None
;
; INTERNAL REFERENCES:
;    ROUTINES: syiPauseOnErrorR3 - print pause message if necessary
;
; EXTERNAL REFERENCES:
;    ROUTINES: DosDupHandle - duplicate a handle
;                DosWrite - write to a handle
;
;
; Procedure syiEndStdErrIntercept
;
; Call DosDupHandle(standard_output,standard_error) to redirect standard
;       error to standard output
; Call syiPauseOnErrorR3 to print the pause message if necessary
; Set the intercept die flag
; Call DosWrite(message_buffer) to force the intercept thread to run and
;       kill its self
;
; Return
;
; End syiEndStdErrIntercept

Procedure syiEndStdErrIntercept,near,local
    assume ds:DOSINITDATA, es:nothing, fs:nothing, gs:nothing, ss:nothing

;       Redirect standard error to the standard output

        push    standard_output_handle
        push    ds
        push    offset stderr_handle
        call    pDosDupHandle
        .if     <nonzero ax>
          Panic <"Error ending stderr intercept">
        .endif

        push    ds
        push    offset stderr_sem
        call    [pDosSemSet].entry_address
        .if     <nonzero ax>
          Panic <"Error setting stderr semaphore">
        .endif

este:
        mov     ax,pipe_read_handle
        mov     sicg_packet_15_d.si15_pipehdl,ax
        push    ds
        push    offset DOSINITDATA:sicg_packet_15
        call    pSICG
        .if     <nonzero ax>
          push  ds
          push  offset stderr_sleep_sem
          call  [pDosSemSet].entry_address
          push  ds
          push  offset stderr_sleep_sem
          push  0
          push  0500
          call  pDosSemWait
          jmp   short este
        .endif

;       Set the intercept die flag

        mov     StdErr_Intercept_Die,1

;       Force the intercept thread to run and kill its self

        push    pipe_write_handle
        push    ds
        push    offset stderr_buf
        push    2
        push    ds
        push    offset stderr_buflen
        call    pDosWrite
        .if     <nonzero ax>
          Panic <"Error writing stderr intercept data">
        .endif

        push    ds
        push    offset stderr_sem
        push    -1
        push    -1
        call    pDosSemWait
        .if     <nonzero ax>
          Panic <"Error semwaiting on stderr semaphore">
        .endif

;       Print the pause message if necessary

        call    syiPauseOnErrorR3

;       Return

        ret
EndProc syiEndStdErrIntercept


;
; SUBROUTINE NAME: syiTerminateStdErrIntercept
;
; DESCRIPTIVE NAME: Terminate standard error intercept mechanism
;
; FUNCTION:      Terminate the standard error intercept mechanism.
;
; NOTES:         This is an internal subroutine within syiProcess
;
; ENTRY POINT: syiTerminateStdErrIntercept
;    LINKAGE:    Call (near)
;
; INPUT:         DS = DOSINITDATA
;
; EXIT-NORMAL: Return to caller (no values returned)
;
; EXIT-ERROR:    None
;
; EFFECTS:       None
;
; INTERNAL REFERENCES:
;    ROUTINES: None
;
; EXTERNAL REFERENCES:
;    ROUTINES: DosClose - close a handle
;
;
; Procedure syiTerminateStdErrIntercept
;
; Call DosClose(pipe_read_handle) to close the pipe read handle
; Call DosClose(pipe_write_handle) to close the pipe write handle
;
; Return
;
; End syiTerminateStdErrIntercept

Procedure syiTerminateStdErrIntercept,near,local
    assume ds:DOSINITDATA, es:nothing, fs:nothing, gs:nothing, ss:nothing

;       Close the pipe read handle

        push    pipe_read_handle
        call    pDosClose
        .if     <nonzero ax>
          Panic <"Error closing stderr intercept read handle">
        .endif

;       Close the pipe write handle

        push    pipe_write_handle
        call    pDosClose
        .if     <nonzero ax>
          Panic <"Error closing stderr intercept write handle">
        .endif

;       Return

        ret
EndProc syiTerminateStdErrIntercept

CpuMode 386

;
; SUBROUTINE NAME: syiQuery16MBDevices
;
; DESCRIPTIVE NAME:  Check to see if any hardfiles are attached to
;                    an adapter that does not support > 16 MB
;
; FUNCTION:
;
; NOTES:         This is an internal subroutine within syiProcess
;
; ENTRY POINT: syiQuery16MBDevices
;    LINKAGE:    Call (near)
;
; INPUT:         nothing
;
; EXIT-NORMAL: Return to caller (no values returned)
;
; EXIT-ERROR:    None
;
; EFFECTS:       None
;
; INTERNAL REFERENCES:
;    ROUTINES: syiQuery16MBDevice
;
; EXTERNAL REFERENCES:
;    ROUTINES: none
;
;
; Notes:  We could use NumIO, NumIORIPL, and SIS_BootDrive to compute
;         which drives to check, but that would be overly complicated
;         and would ignore the case of an IFS mounting drives during
;         it's initialization (e.g. VDISK.IFS with user-specified
;         drive letter).
;         If we check C: through Z:, we catch all cases.
;
;

Procedure syiQuery16MBDevices,near
    assume ds:nothing,es:nothing,ss:nothing
        EnterProc <>
            pusha
            push    ds
            push    es

            DosInitContext ds

            mov      StartDrive,'C'

DoNextDrive:

             call    syiQuery16MBDevice

             .if     <ax ne 0>
                jmp   Q16M_x    ;Found one, no need to check others
             .endif
             inc     StartDrive       ; setup for next drive letter
             cmp     StartDrive,'Z'   ; Are we finished (did C-Z)
             ja      Q16M_x           ; yes, exit

             jmp     DoNextDrive      ; else, do next drive

Q16M_x:

            pop     es
            pop     ds
            popa
        LeaveProc
        ret
EndProc syiQuery16MBDevices

;
; SUBROUTINE NAME: syiQuery16MBDevice
;
; DESCRIPTIVE NAME:  Check to see if a specific hardfile is attached to
;                    an adapter that does not support > 16 MB
;
; FUNCTION:
;
; NOTES:         This is an internal subroutine within syiProcess
;
; ENTRY POINT: syiQuery16MBDevice
;    LINKAGE:    Call (near)
;
; INPUT:         DosInitData:StartDrive setup for call
;
; EXIT NORMAL:  Device supports > 16 MB
;               or Device not found
;                  AX == 0
;
; EXIT ERROR:   Device does not support > 16 MB
;                  AX != 0
;                  _DDwith24BitDMA set to non-zero
;
; EFFECTS:       None
;
; INTERNAL REFERENCES:
;    ROUTINES: None
;
; EXTERNAL REFERENCES:
;    ROUTINES: pDosOpen
;              pDosDevIOCtl
;              pDosClose
;
;

Procedure    syiQuery16MBDevice, near
    assume ds:nothing,es:nothing,ss:nothing
        EnterProc <>
             push           ds
             push           es
             DosContext es
             DosInitContext ds

             push    ds                    ; address of file name
             push    offset DOSINITDATA:StartDrive
             push    ds                    ; address of file handle
             push    offset DOSINITDATA:device_handle
             push    ds                    ; address of action taken word
             push    offset DOSINITDATA:open_action
             push    0                     ; initial file size
             push    0
             push    0                     ; file attribute
             push    0000000000000001b     ; open flag
;                    rrrrrrrrffffeeee      ;  ffff=0000 fail if file doesn't exist
                                           ;  eeee=0001 open if file exists
             push    1111000011000010b     ; open mode
;                    dwfbrrrrisssraaa      ;  d = 1 drive open
                                           ;  w = 1 no write through
                                           ;  f = 1 fail with rc
                                           ;  b = 1 bypass cache
                                           ;  i = 1 not inheritable file
                                           ;  sss = 100 deny none
                                           ;  aaa = 010 read/write access
             push    0                     ; reserved double word
             push    0
             call    pDosOpen

             .if     <ax ne 0>               ;for some reason DosOpen failed
                xor    ax,ax                 ; Fake > 16MB support
             .else
                push    ds
                push    offset DOSINITDATA:GT16MBDataPacket
                push    ds
                push    offset DOSINITDATA:GT16MBParmPacket
                push    DSK_GETDEVICEPARAMS               ;Function
                push    IOCTL_DISK                        ;Category
                push    device_handle
                call    pDosDevIOCtl

                .if     <ax ne 0>      ;for some reason DosDevIOCtl failed
                     mov    GT16MBDevAttr, 0ffffh ; Fake > 16MB support
                .endif


                push    device_handle
                call    pDosClose            ; Don't check for fail on close

                mov     ax,GT16MBDevAttr
                test    ax, 01h              ; test for removable media-77697

                .if <nz>

                    ; bit is set - not a removable media
                    test    ax,04h        ;(check bit 2 if set-> > 16Meg)
                    .if     <z>
                        ;bit is off
                        mov     ax,0ffffh             ; return AX non-zero
                        inc     _DDwith24BitDMA       ; set flag to non-zero
                    .else
                        xor     ax,ax
                    .endif  ; check > 16 Meg

                .else
                    xor   ax, ax                      ; Fake OK if removable
                .endif                                ; test removable media

             .endif

             pop     es
             pop     ds
        LeaveProc
        ret
EndProc syiQuery16MBDevice


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SUBROUTINE NAME:  syiCheckFileSys
;
; DESCRIPTIVE NAME:  Check to see if a specific hardfile is available
;                    and there by deducing availability of FS support
;
; NOTES:         This is an internal subroutine within syiProcess
;                The test is done by opening (and then closing) the specified
;                file using pDosOpen() call.
;                See defect 86005  Feature 83134
;
; ENTRY POINT:   check_file_sys
;    LINKAGE:    Call (near)
;
; INPUT:        ds: DOSINITDATA
;
; EXIT NORMAL:  AX == 0
;
; EXIT ERROR:   AX != 0
;
; EFFECTS:       None
;
; INTERNAL REFERENCES:
;    ROUTINES: None
;
; EXTERNAL REFERENCES:
;    ROUTINES: pDosOpen
;              pDosClose
;

Procedure    syiCheckFileSys, near
    assume ds:nothing,es:nothing,ss:nothing
        EnterProc <>
             push           ds
             push           es
             DosContext     es
             DosInitContext ds

             mov     cx,SISData.SIS_BootDrv   ; get the boot drive from
             add     cl,'A' - 1               ; the system infoseg

             mov     StartDrive,cl
             mov     byte ptr OS2Loader, cl
             mov     byte ptr ConfigDotSys, cl
             mov     byte ptr Doscall1DotDll, cl  ;149691

             push    ds                    ; address of file name
             push    offset DOSINITDATA:StartDrive                      ; 86950
             push    ds                    ; address of file handle
             push    offset DOSINITDATA:device_handle
             push    ds                    ; address of action taken word
             push    offset DOSINITDATA:open_action
             push    0                     ; initial file size
             push    0
             push    0                     ; file attribute
             push    0000000000000001b     ; open flag
;                    rrrrrrrrffffeeee      ;ffff=0000 fail if file doesn't exist
                                           ;  eeee=0001 open if file exists
             push    1111000011000000b     ; open mode
;                    dwfbrrrrisssraaa      ;  d = 1 Is a drive
                                           ;  w = 1 no write through
                                           ;  f = 1 fail with rc
                                           ;  b = 1 bypass cache
                                           ;  i = 1 not inheritable file
                                           ;  sss = 100 deny none
                                           ;  aaa = 000 read access
             push    0                     ; reserved double word
             push    0
             call    pDosOpen
             push    ax
             .if     <zero ax>            ; DosOpen() succeeded
                push    device_handle     ; Now close the file
                call    pDosClose
             .endif
             pop      ax                   ; retrieve DosOpen() result

; On a RIPL machine the open of the networl device will have failed so
; check for either OS2LDR or CONFIG.SYS as well. @90611
; For D1 Space problem, we now need to check for Doscall1.DLL  ;149691

; OS2Loader

             push    ds                    ; address of file name
             push    offset DOSINITDATA:OS2Loader
             push    ds                    ; address of file handle
             push    offset DOSINITDATA:device_handle
             push    ds                    ; address of action taken word
             push    offset DOSINITDATA:open_action
             push    0                     ; initial file size
             push    0
             push    0                     ; file attribute
             push    0000000000000001b     ; open flag
;                    rrrrrrrrffffeeee      ;ffff=0000 fail if file doesn't exist
                                           ;  eeee=0001 open if file exists
             push    0111000011000000b     ; open mode
;                    dwfbrrrrisssraaa      ;  d = 0 Is NOT a drive
                                           ;  w = 1 no write through
                                           ;  f = 1 fail with rc
                                           ;  b = 1 bypass cache
                                           ;  i = 1 not inheritable file
                                           ;  sss = 100 deny none
                                           ;  aaa = 000 read access
             push    0                     ; reserved double word
             push    0
             call    pDosOpen
             .if     <zero ax>            ; DosOpen() succeeded
                push    ax
                push    device_handle     ; Now close the file
                call    pDosClose
                pop      ax               ; retrieve DosOpen() result
                jmp short CFS_Done
             .endif

; ConfigDotSys

             push    ds                    ; address of file name
             push    offset DOSINITDATA:ConfigDotSys
             push    ds                    ; address of file handle
             push    offset DOSINITDATA:device_handle
             push    ds                    ; address of action taken word
             push    offset DOSINITDATA:open_action
             push    0                     ; initial file size
             push    0
             push    0                     ; file attribute
             push    0000000000000001b     ; open flag
;                    rrrrrrrrffffeeee      ;ffff=0000 fail if file doesn't exist
                                           ;  eeee=0001 open if file exists
             push    0111000011000000b     ; open mode
;                    dwfbrrrrisssraaa      ;  d = 0 Is NOT a drive
                                           ;  w = 1 no write through
                                           ;  f = 1 fail with rc
                                           ;  b = 1 bypass cache
                                           ;  i = 1 not inheritable file
                                           ;  sss = 100 deny none
                                           ;  aaa = 000 read access
             push    0                     ; reserved double word
             push    0
             call    pDosOpen
             .if     <zero ax>            ; DosOpen() succeeded
                push    ax
                push    device_handle     ; Now close the file
                call    pDosClose
                pop      ax               ; retrieve DosOpen() result
                jmp short CFS_Done        ; 149691
             .endif

; Doscall1DotDll                          ; 149691 start

             push    ds                    ; address of file name
             push    offset DOSINITDATA:Doscall1DotDll
             push    ds                    ; address of file handle
             push    offset DOSINITDATA:device_handle
             push    ds                    ; address of action taken word
             push    offset DOSINITDATA:open_action
             push    0                     ; initial file size
             push    0
             push    0                     ; file attribute
             push    0000000000000001b     ; open flag
;                    rrrrrrrrffffeeee      ;ffff=0000 fail if file doesn't exist
                                           ;  eeee=0001 open if file exists
             push    0111000011000000b     ; open mode
;                    dwfbrrrrisssraaa      ;  d = 0 Is NOT a drive
                                           ;  w = 1 no write through
                                           ;  f = 1 fail with rc
                                           ;  b = 1 bypass cache
                                           ;  i = 1 not inheritable file
                                           ;  sss = 100 deny none
                                           ;  aaa = 000 read access
             push    0                     ; reserved double word
             push    0
             call    pDosOpen
             .if     <zero ax>            ; DosOpen() succeeded
                push    ax
                push    device_handle     ; Now close the file
                call    pDosClose
                pop      ax               ; retrieve DosOpen() result
;               jmp short CFS_Done
             .endif
                                          ; 149691 end
CFS_Done:
             pop     es
             pop     ds
             LeaveProc
             ret

EndProc  syiCheckFileSys


INITR3CODE ends

        end
