windows-nt/Source/XPSP1/NT/base/mvdm/wow16/kernel31/diag.asm
2020-09-26 16:20:57 +08:00

226 lines
6.8 KiB
NASM

;***************************************************************************
;* DIAG.ASM
;*
;* Diagnostic-mode routines used to log interesting output to a log
;* file. Diagnostic mode is enabled/disabled through a command line
;* switch.
;*
;* Created by JonT starting 19 July 1991
;*
;***************************************************************************
TITLE LOG - Diagnostic mode logging routines
.xlist
include kernel.inc
.list
.386p
DataBegin
externD lpWindowsDir
externW cBytesWinDir
externB szDiagStart
externB szCRLF
globalW fDiagMode,0 ;Set in LDBOOT.ASM
szLogFileName DB 'BOOTLOG.TXT', 0
szPath DB 128 DUP(0) ;Entire pathname to file
IF KDEBUG
externB szInitSpew
ENDIF
DataEnd
externFP Int21Handler
externFP OutputDebugString
;** Note that this goes in the fixed code segment
sBegin CODE
assumes CS,CODE
; DiagQuery
;
; Exported entry point that can be called to determine if in
; diagnostic mode. Returns TRUE iff in diagnostic mode.
cProc DiagQuery, <FAR,PUBLIC>, <si,di,ds>
cBegin
SetKernelDS
mov ax,fDiagMode ;Return the flag
cEnd
; DiagOutput
;
; Exported entry point to allow a string to be written to the
; log file. The file is flushed after writing the string
; guaranteeing that it always gets in there in case we abort
; immediately after the call.
cProc DiagOutput, <FAR,PUBLIC>, <si,di,ds>
parmD lpstr
localW wHandle
cBegin
SetKernelDS
;** Check for diag mode
cmp fDiagMode,1 ;Diag mode?
jne SHORT DO_End ;Nope, get out
;** Reopen the log file
mov ah,3dh ;Create file call
mov al,22h ;R/W, Deny W to others
mov dx,dataOFFSET szPath ;File name pointer
DOSCALL
jc SHORT DO_Error ;Error, get out
mov wHandle,ax ;Save the handle
;** Seek to the end
mov ax,4202h ;Seek to end of file call
mov bx,wHandle ;Get the file handle
xor cx,cx ;0 bytes before end of file
xor dx,dx
DOSCALL
jc SHORT DO_Error ;Error, get out
;** Get the length of the string
xor cx,cx ;Get max length
dec cx ; (0xffff)
les di,lpstr ;Point to the string
xor al,al ;Zero byte
repnz scasb ;Find the zero byte
neg cx ;Get the length
dec cx
dec cx
IF KDEBUG
;** Spit to debug terminal in debug KERNEL
push cx
push WORD PTR lpstr[2]
push WORD PTR lpstr[0]
call OutputDebugString
pop cx
ENDIF
;** Write the string
push ds ;Save our DS
mov ah,40h ;Write file call
mov bx,wHandle ;Get the handle
lds dx,lpstr ;Get the buffer pointer
UnsetKernelDS
DOSCALL
pop ds
ResetKernelDS
jnc SHORT DO_Close ;No problem
DO_Error:
mov fDiagMode,0 ;Clear diagnostic mode and close file
;** Close the file
DO_Close:
mov bx,wHandle ;Handle in BX
or bx,bx ;File open?
jz SHORT DO_End ;Nope, just get out
mov ah,3eh ;Close file call
DOSCALL
DO_End:
cEnd
; DiagInit
;
; Called from Bootstap (LDBOOT.ASM) and is used to create the log file
; and write the startup message to it.
cProc DiagInit, <FAR,PUBLIC>, <ds,si,di>
localW wHandle
cBegin
SetKernelDS
smov es,ds ;Point to kernel DS with ES
;** Get the full path name
mov di,dataOFFSET szPath ;Point to destination path
mov cx,cBytesWinDir ;Get the length of the directory
lds si,lpWindowsDir ;Point to the Windows directory
UnsetKernelDS
rep movsb ;Copy it
smov ds,es ;Get DS back to kernel DS
ResetKernelDS
mov si,dataOFFSET szLogFileName ;Point to log file name
cmp BYTE PTR [di - 1],'/' ;Check for trailing separator
je SHORT DI_NoSeparator ;No separator needed
mov al,'\' ;Get the other separator
cmp [di - 1],al ;Check for other separator
je SHORT DI_NoSeparator ;None needed
stosb ;Put a '\' in
DI_NoSeparator:
lodsb ;Get the char
stosb ;Write it
or al,al ;Zero byte?
jnz DI_NoSeparator ;No, loop for next char
IF KDEBUG
;** Spit to debug terminal in debug KERNEL
push ds
push dataOFFSET szInitSpew
call OutputDebugString ;Spit out the message
push ds
push dataOFFSET szPath ;Spit out log filename
call OutputDebugString
push ds
push dataOFFSET szCRLF ;Write a CR/LF
call OutputDebugString
ENDIF
;** Try to open the file. If it exists, we use it as it
mov ah,3dh ;Open file call
xor cx,cx ;Normal file
mov al,22h ;R/W, Deny W to others
mov dx,dataOFFSET szPath ;File name pointer
DOSCALL
jc SHORT DI_Create ;Error, need to create file
mov wHandle,ax ;Save the handle
;** Seek to the end
mov ax,4202h ;Seek to end of file call
mov bx,wHandle ;Get the file handle
xor cx,cx ;0 bytes before end of file
xor dx,dx
DOSCALL
jmps DI_CloseIt ;Close file now
;** Create the log file
DI_Create:
mov ah,3ch ;Create file call
xor cx,cx ;Normal file
mov dx,dataOFFSET szPath ;File name pointer
DOSCALL
mov wHandle,ax ;Save the handle
;** On error, disable logging
jc SHORT DI_End ;Error, get out without enabling
DI_CloseIt:
mov fDiagMode,1 ;We're in diag mode now
;** Close the file (we reopen it on each call to DiagOutput)
mov bx,wHandle ;Handle in BX
mov ah,3eh ;Close file call
DOSCALL
;** Now start the log file
mov ax,dataOFFSET szDiagStart ;Point to the string
cCall DiagOutput, <ds,ax> ;Start the file
DI_End:
cEnd
sEnd
END