;	SCCSID = @(#)qapptype.asm	6.3 91/08/19
;      SCCSID = @(#)qapptype.asm	6.3 91/08/19
	TITLE	qapptype - DOSQAPPTYPE interface

;***	qapptype.asm - implement the visible API for DOSQAPPTYPE
;
;	 IBM/Microsoft Confidential
;
;	 Copyright (c) IBM Corporation 1987, 1989
;	 Copyright (c) Microsoft Corporation 1987, 1989
;
;	 All Rights Reserved
;
;	DOSQAPPTYPE is used to return the type of the executable file
;	specified. If an absolute path has been specified, then only
;	that path is searched for the file (see IsPathAbsolute in
;	dosexec.asm for details), otherwise the PATH environment variable
;	is searched explicitly for the file. The headers of the file are
;	read and examined to ensure that it is a valid file.
;	An appropriate error is returned if is not, otherwise the flag
;	fields that indicate the type of executable file are returned.
;
;
;***	Modification History
;
;	11/18/93	noto	Define which segment for Page Tuning DLL



page	,132
.386p

.xlist
include basemaca.inc
include realmac.inc			; for conditional longjumps
include error.inc
include curdir.inc
include mi.inc
include ldrxport.inc
include dc1segs.inc
include infoseg.inc
include dc1mmpha.inc
.list

DATA	SEGMENT

PathStr DB	'PATH',0                ; path env. var.

DATA	ENDS


	EXTRN	DOSSEARCHPATH:FAR
	EXTRN	DOSIQAPPTYPE:FAR
	EXTRN	IsPathAbsolute:NEAR	; In dosexec.asm


CODE16C_TUNE2  SEGMENT DWORD USE16 PUBLIC 'CODE'
CODE16C_TUNE2  ENDS



CODE16C_TUNE2  SEGMENT

	ASSUME CS:CODE16C_TUNE2

; ** WARNING
;	    The value of MTESIZE **MUST** be the smaller of
;	    SIZE mte_s and PMPATHLEN.

IF <(SIZE mte_s) GT (PMPATHLEN)>
   %OUT ERROR: New EXE header larger than buffer
   .ERR
ENDIF

SEARCHCTRL	EQU	3		; search cur. dir. first & interpret



;**	DOSQAPPTYPE - Return the type of executable file
;
;	ENTRY		DWORD	ASCIIZ ExecutableFileName
;			DWORD	Address to return EXE file type
;		SS:SP ->DWORD	Far return to caller
;
;	EXIT	AX = error code
;
;	USES	FLAGS
;
;	NOTES
;
;

Procedure   DOSQAPPTYPE,FAR
	ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING

ArgVar	    AppTypePtr,DWORD
ArgVar	    FilePtr,DWORD

; 5 bytes will be clobbered but keep 6 bytes for safety
LocalVar    HeaderBuf,PMPATHLEN+6	; file header buffer, used temporarily
					;  for processing file path
LocalVar    PathBuf,PMPATHLEN		; path building buffer
LocalVar    NamePtr,WORD		; pointer past last '.' in name

	EnterProc
	SaveReg <ds, es, di, si, cx, dx>

	cld
	lds	si,FilePtr		; (ds:si) -> path
	push	ss
	pop	es			; (es) = (ss)
	lea	di,HeaderBuf		; (es:di) -> buffer
	xor	dx,dx			; (dx) = null pointer to last '.'
	mov	cx,PMPATHLEN

dqat00: lodsb				; copy path and save ptr to last '.'
	stosb
	cmp	al,'.'
	jne	dqat01			; not a '.',  don't save pointer

	mov	dx,si			; (dx) = pointer one past last '.'

dqat01: or	al,al
	loopnz	dqat00			; not end of path, continue copy
	jz	dqat02
	mov	ax,ERROR_INVALID_NAME
	jmp	dqat90

dqat02: mov	[NamePtr],dx		; save ptr one past last '.'

;***DT	preDOSQAPPTYPE - DosQAppType pre-invocation trace point
;
;    TRACE MINOR = <RAS_DC1_PRE_DOSQAPPTYPE>,
;	   TP	 = .preDOSQAPPTYPE,
;	   TYPE  = (PRE,API),
;	   GROUP = LDR,
;	   DESC  = "(OS) DosQAppType Pre-Invocation",
;	   ASCIIZ= (RDS+SI, D, <MAXPATHLEN>),
;	   FMT	 = "File = <FMT_ASCIIZ>"

;	Now that the filename is likely to be present, we use DynTrc.
;	We need the nop - otherwise the tracepoint would be in the loop!

	mov	si,word ptr FilePtr	; (ds:si) -> filename, for RAS
	PUBLIC	preDOSQAPPTYPE
preDOSQAPPTYPE: 			; RAS pre-invocation trace
	nop				; Don't remove this!  It's for RAS.
	MMPHPreDOSQAppType		; Performance Hook (1409h)

; try finding file first without checking for an extension

dqat06: lds	si,FilePtr		; (ds:si) -> filename
	ASSUME	DS:NOTHING
	call	IsPathAbsolute		; check if absolute path is specified.
	jc	dqat10			; if so, do not search PATH
	push	SEARCHCTRL		; DOSSEARCHPATH control word
	push	DATA
	push	OFFSET DATA:PathStr	; -> "PATH", env. var. name
	push	WORD PTR FilePtrh
	push	WORD PTR FilePtrl	; -> file name
	push	ss
	lea	ax,PathBuf
	push	ax			; -> path buffer
	push	PMPATHLEN		; length of path buffer
	call	DOSSEARCHPATH
	or	ax,ax
	jnz	dqat30			; There was an error - jump to exit

; We have found the file.

	push	ss
	lea	ax,PathBuf
	push	ax
	jmp	short dqat20

; An absolute path name was specified

dqat10: push	[FilePtrh]		; Set up path specified by user
	push	[FilePtrl]

; The address of the path of the file is on the stack. We now go ahead and
; set up the rest of the stack for the call to DOSIQAPPTYPE.

dqat20: push	word ptr [AppTypePtr+2] ; Push caller's buffer address
	push	word ptr [AppTypePtr]
	CALL	DOSIQAPPTYPE
	cmp	ax,ERROR_INVALID_EXE_SIGNATURE	; did we get a bad signature?
	je	dqat35			; yes, it could be a .COM file

dqat30: cmp	ax,ERROR_FILE_NOT_FOUND ; If not found, try adding .EXE
	jne	dqat90			; else exit with error

; OK, we couldn't find file as supplied, if it hasn't got an
; extension add default .EXE and try again. We're only going to try
; this once because the next time we try, it WILL have an extension

; scan forward from last '.' looking for '/' or '\'

dqat35: push	ax			; save possible error
	mov	si,[NamePtr]		; (si) -> one past last '.' in path
	or	si,si
	jz	dqat50			; no '.' in path, go add .EXE
dqat40: lodsb				; (al) = next char
	or	al,al
	jz	dqat60			; end of path, path HAS extension
	cmp	al,'/'
	je	dqat50			; '/' after last '.', no extension
	cmp	al,'\'
	jne	dqat40			; not '\', try next char
					; '\' after last '.', no extension

; path does NOT contain an extension, add the default '.exe'
; but first check if there is space

dqat50: pop	ax			; clean stack
	mov	[NamePtr],di		; update ptr to be 1 past last '.'
	dec	di			; (es:di) -> null at end of path

	mov	ax,di
	lea	dx,HeaderBuf
	sub	ax,dx
	add	ax,4			; ax has length of buffer + '.EXE'
	cmp	ax,PMPATHLEN
	mov	ax,ERROR_INVALID_NAME
	ja	dqat90

	push	ss
	pop	es			; address stack buffer
	lea	ax,HeaderBuf		; FilePtr = HeaderBuf
	mov	WORD PTR FilePtrl,ax
	mov	WORD PTR FilePtrh,es
	mov	eax,'EXE.'
	stosd				; append '.exe' to path
	mov	byte ptr es:[di],0	; NULL terminate string
	jmp	dqat06			; go check again


dqat60: pop	ax			; restore error code
	cmp	ax,ERROR_INVALID_EXE_SIGNATURE	; did we get a bad signature?
	jne	dqat90			; yes, it could be a .COM file

	mov	si,[NamePtr]
	lodsb
	mov	ah,'C'                  ; Could the extention be .COM?
	call	CharIComp		; Is the first character equal?
	jnz	dqat70			; no, not equal

	lodsb
	mov	ah,'O'                  ; Could the extention be .COM?
	call	CharIComp		; Is the second character equal?
	jnz	dqat70			; no, not equal

	lodsb
	mov	ah,'M'                  ; Could the extention be .COM?
	call	CharIComp		; Is the third character equal?
	jnz	dqat70			; no, not equal

	lodsb
	or	al,al			; Is the extention exactly .COM0?
dqat70: mov	ax,ERROR_INVALID_EXE_SIGNATURE	; assume error
	jnz	dqat90			; no, not a .COM extention

	xor	ax,ax			; .COM extention
	lds	si,AppTypePtr		; ds:si -> word for return value
	mov	word ptr [si],QAT_DOSEXE; set return value for "DOS" app

dqat90:

;***DT	postDOSQAPPTYPE - DosQAppType post-invocation trace point
;
;    TRACE MINOR = <RAS_DC1_POST_DOSQAPPTYPE>,
;	   TP	 = .postDOSQAPPTYPE,
;	   TYPE  = (POST,API),
;	   GROUP = LDR,
;	   DESC  = "(OS) DosQAppType Post-Invocation",
;	   MEM	 = (RDS+SI, D, 2),
;	   REGS  = (AX),
;	   FMT	 = "Type = <FMT_C_WORD>  Return Code = <FMT_WORD>"

	lds	si,AppTypePtr		; ds:si -> word for Type, for RAS
	PUBLIC	postDOSQAPPTYPE
postDOSQAPPTYPE:			; RAS post-invocation trace
	MMPHPostDOSQAppType		; Performance Hook (1489h)

	RestoreReg	<dx, cx, si, di, es, ds>
	ASSUME	DS:NOTHING
	LeaveProc
	ret	?aframe

EndProc DOSQAPPTYPE




;**	CharIComp - Do a case insensitive compare (a-zA-Z) character
;
;	NOTE:	This procedure assumes that all codepages are a superset
;		of 7 bit ASCII.  This routine only works on characters
;		in the a-z and A-Z range
;
;
;	ENTRY	AL - character to compare
;		AH - A-Z range
;
;	EXIT	ZR - characters are equal
;		NZ - not equal
;
;	USES	AH,FLAGS
;
;
Procedure   CharIComp,NEAR
	ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING

ifdef	CPSTRICT
	cmp	ah,'A'                  ; Is the character above 'A'?
	jb	cicerr

	cmp	ah,'Z'                  ; Is it below 'Z'?
	jbe	cic10

cicerr: mov	ah,-1
	or	ah,ah
	jmp	short cicx

cic10:
endif	; CPSTRICT

	cmp	ah,al			; Are they equal?
	je	cicx			; yes, return zero

	or	ah,20h			; upper case the letter
	cmp	ah,al
cicx:	ret


EndProc CharIComp


CODE16C_TUNE2	ENDS


END
