;       SCCSID = @(#)d_qfinfo.asm	6.1 91/02/15
;	SCCSID = @(#)d_qfinfo.asm	1.4 90/01/22
; ****************************************************************************
; *									     *
; *			  IBM/Microsoft Confidential			     *
; *									     *
; *		    Copyright (c) IBM Corporation  1987, 1990		     *
; *		    Copyright (c) Microsoft Corp.  1987, 1990		     *
; *			      All Rights Reserved			     *
; *									     *
; ****************************************************************************
;***  D_QFINFO.ASM - API stub routine DosQFileInfo
;
;	Member of API library
;	David Silverstein
;	Copyright MicroSoft Corporation, 1986
;	21-May-1986
;
;	library routine for API simulator
;
;	Called from dos 2.x,3.x compatible dos 5.x applications
;
;	Special Information
;		none
;
;	Modification History
;
;	07-Oct-86 (billme) remove blocking factor according to DCR 301
;
;	09-Oct-86 (billme) begin process of pruning api_dev_table
;	by moving data from the table (date and time) to looking it
;	up on a per call basis - eventually we will be down to one
;	unavoidable byte
;
;	23-Oct-86 (billme) clean up code a bit (more to come later
;	when the api_table is reduced in size) and fix bug in which
;	bx (handle) was not being set before calling getdate/time
;	function
;
;	06-Jan-87 (billme): Replace initial pushes and final pops
;	with calls to __api_begin and __api_end resp.  This will
;	reduce the size of FAPI and allow support for signals.
;
;	15-Jan-87 (billme): Change reference to __api_dev_table to
;	call to __api_devtab_ptr ... to reduce code size.
;
;
;	04-May-87 (robertc): Install hooks for DOSErrorClass Support.
;	All int 21h errors are passed through api_get_extended to get the
;	extended errorcode and to provide the class, action, and locus for
;	the dynamic error FIFO queue.
;
;	17-June-87 (stevee): fix to insure that all FAPI file handles are
;	less than MAX_HANDLES (p5553)
;
;	17-Jun-87 (robertc): Check __api_dev_table to see if valid info avail
;	(PTM 5550)
;
;	6-22-87 (Tarng): Get file size by LSEEK instead of __api_dev_table.
;
;	7-1-87 (robertc): Add code to save and restore file pos for LSEEK
;
;	8-18-87 (robertc): test to assure handle is attached to a filep7047
;
;	8-24-87 (robertc): fix bug introduced by ptm7047, use hi_attribute
;	field instead of hi_attrdev.

include basemaca.inc
include realmac.inc
include dos2equ.inc
include api.inc
include error.inc

	EXTRN	api_get_extended:far	;@@ added support for DOSErrorClass
	EXTRN	__api_devtab_ptr:near
	EXTRN	__api_begin:near
	EXTRN	_api_getvrsn:near
	EXTRN	__api_end:near

LEVEL1			equ	1	; passed value for level 1 info
LEVEL1_INFO_SIZE	equ	22	; bytes needed in FileInfoBuf for info
;/********************** START OF SPECIFICATIONS *********************/
;/*								     */
;/* SUBROUTINE NAME: DosQFileInfo				     */
;/*								     */
;/* DESCRIPTIVE NAME: Dos Query File Information		     */
;/*								     */
;/* FUNCTION: Returns Information for a specified file.		     */
;/*								     */
;/*								     */
;/*								     */
;/* NOTES:    Real Mode Only					     */
;/*	      Simulates OS/2 call from DOS 2.x,3.x environment	     */
;/*								     */
;/* ENTRY POINT: DosQFileInfo					     */
;/*								     */
;/*    LINKAGE: Call Far					     */
;/*								     */
;/* INPUT: Stack Frame in form of:				     */
;/*								     */
;/*   PUSH   WORD  FileHandle - file handle			     */
;/*   PUSH   WORD  FileInfoLevel - level of file information required*/
;/*   PUSH@  OTHER FileInfoBuf -  storage area to return file info   */
;/*   PUSH   WORD  FileInfoBufSize - length of FileInfoBuf	     */
;/*								     */
;/*								     */
;/* EXIT-NORMAL:   AX = 0					     */
;/*								     */
;/* EXIT-ERROR:	   AX = Errorcode				     */
;/*	  may return error code from Dos 2.x, 3.x, OS/2		     */
;/*								     */
;/* EFFECTS:  AX, all other registers preserved			     */
;/*								     */
;/* INTERNAL REFERENCES: none					     */
;/*								     */
;/*    ROUTINES: __api_do_find					     */
;/*								     */
;/* EXTERNAL REFERENCES: __api_dev_table			     */
;/*								     */
;/*    ROUTINES: __api_begin					     */
;/*		 __api_end					     */
;/*		 __api_devtab_ptr				     */
;/*		 api_get_extended				     */
;/*		 _api_get_version				     */
;/*		 Int 21h - Get/Set File Date/Time Extended Info	     */
;/*		 Int 21h - Move File Ptr			     */
;/*								     */
;/*********************** END OF SPECIFICATIONS **********************/


;***	DOSQFILEINFO
;
;	simulates DOS 5.0 call from DOS 2.x,3.x environment
;
;	errorcode = unsigned far pascal
;	DosQFileInfo(FileHandle, FileInfoLevel, FileInfoBuf, FileInfoBufSize)
;
;	ENTRY:
;		FileHandle - file handle
;		FileInfoLevel - level of file information required
;		FileInfoBuf -  storage area to return file info
;		FileInfoBufSize - length of FileInfoBuf
;
;	RETURN:
;		AX = 0 if no error, else error code (see DOS 5 spec)
;
;	EXIT:
;
;	USES:
;		AX
;
;	Pseudo Code:
;		save registers
;		use BP as pointer to stack parameters
;		Checks if FileInfoBufSize is large enough
;		   and file handle is within range.
;		Gets data out of file handle state table (set up in d_open)
;		   and loads it into FileInfoBuf.
;		restore registers
;		return
;
;	WARNING:
;		may return error code from Dos 2.x, 3.x (see dos manuals)
;
;	EFFECTS:
;		none
;

	title	DOSQFILEINFO
;
;	EXTRN	DOSQFILEINFO:FAR
;
;	PUSH	WORD FileHandle
;	PUSH	WORD FileInfoLevel
;	PUSH	@ DWORD FileInfoBuf
;	PUSH	WORD FileInfoBufSize
;	CALL	DOSQFILEINFO
;

; This segment is defined to flag DosOpen that DosQFileInfo is being included
; in the link. It does so by initializing __api_do_find to 1 in this file, and
; '?' in a similarily defined segment is DosOpen. At run time DosOpen checks
; this variable.  If it is a 1, (DosQFileInfo linked) DosOpen calls FindFirst
; and fills the handle table (__api_dev_table) with file information data. If
; __api_do_find is a 0, it was not initialized, DosQfileInfo was not linked,
; and DosOpen skips calling FindFirst.  This results in a DosOpen preformance
; win whenever DosQFileInfo is not used.

DOFIND	segment byte common 'CODE'

	public	__api_do_find

	__api_do_find	db	1		; DosQFileInfo linked flag

DOFIND	ends


_TEXT	segment byte public 'CODE'

	assume	CS:_TEXT, DS:nothing

	public	DOSQFILEINFO

	EXTRN	__api_dev_table : WORD


FileHandle	equ	[BP+14]
FileInfoLevel	equ	[BP+12]
FileInfoBuf	equ	[BP+8]
FileInfoBufSize equ	[BP+6]

current_pos_hi	dw	?		;@@ current position in file
current_pos_lo	dw	?
testdev_mask	equ    0F0h


DOSQFILEINFO	proc	far

	call	__api_begin	; init bp and save bp,ds,bx,cx,dx,si,di,es
				; required to save: bp,es,bx,cx,dx,si,di

	mov	ax, error_invalid_handle	; if handle too large
	mov	bx,FileHandle			; BX <- file handle
	cmp	bx,MAX_HANDLES
	jb	fChkVersion
	jmp	NormalExit

fChkVersion:
	call	_api_getvrsn	; get the DOS version
	cmp	ax,0A14h	;
	jb	fChkLvl		; if < 10.2 do old style call

;;;;Version 10.2 or Greater. Use int 21 func 57 AL=2(Get Information)
	mov	ax,(D2_GetSetFileDT shl 8) + 02 ; get info
	mov	dx,[FileInfoLevel]	 ; Info level
	mov	bx,[FileHandle]		 ; File Handle
	les	di,[FileInfoBuf]	 ; Ptr to Info Buffer
	mov	cx,[FileInfoBufSize]	 ; Buffer size
	int	21h
	ljc	ErrorExit		; Error ?
	xor	ax,ax
	jmp	NormalExit		; Exit

fChkLvl:
	cmp	word ptr [FileInfoLevel],LEVEL1
	mov	ax, error_invalid_level		; if info level NOT legal
	je	finfo1
	jmp	finfo4				; then return error
finfo1:
	cmp	word ptr [FileInfoBufSize], LEVEL1_INFO_SIZE
	mov	ax, error_buffer_overflow	; if info buf size NOT legal
	jae	tstdev
	jmp	NormalExit			; then return error
tstdev:
	mov	ax,FileHandle			;@@PTM 7047
	call	__api_devtab_ptr		;@@ check the device table
	mov	ax,error_invalid_handle		;@@ prepare error
	test	cs:[bx].hi_attrdev,testdev_mask ;@@ tis it a device
	jz	finfo211			;@@

	jmp	NormalExit			; then return error

finfo211:
	mov	ax,FileHandle			      ;@@PTM 5550
	call	__api_devtab_ptr		      ;@@ check the device
	test	cs:[bx].hi_validity,HANDLE_INFO_VALID ;@@ table to see if we
	jnz	finfo21				      ;@@ have any valid info
	mov	ax,ERROR_INFO_NOT_AVAIL		      ;@@
	jmp	NormalExit			      ;@@
						      ;@@
finfo21:					      ;@@
	mov	bx,FileHandle			      ;@@ restore handle

finfo3:
	les	di, [FileInfoBuf]
	xor	ax,ax				; AL <- function code 'get'
	mov	ah, D2_GetSetFileDT		; AH <- get/set date/time fcn
	int	21h				; if error getting date/time
	jc	ErrorExit			; then exit
					;@@ added support for DOSErrorClass
	mov	es:[di].fi_wdate, dx		; date of last write
	mov	es:[di].fi_wtime, cx		; time of last write

	mov	ah,D2_MoveFilePtr		;@@ move a file pointer
	mov	al,1				;@@ mov from current
	xor	cx,cx				;@@ offset
	xor	dx,dx				;@@
	int	21h				;@@ if error getting pos
	jc	ErrorExit			;@@ then exit

	mov	current_pos_hi,dx		;@@ save current position
	mov	current_pos_lo,ax		;@@

	mov	ah,D2_MoveFilePtr		; move a file pointer
	mov	al,2				; mov to eof
	xor	cx,cx				; offset
	xor	dx,dx				;
	int	21h				; if error getting size
	jc	ErrorExit			; then exit

	mov	es:[di].fi_allochigh, dx	; file allocation (high word)
	mov	es:[di].fi_sizehigh, dx		; file end of data (high word)

	mov	es:[di].fi_alloclow, ax		; file allocation (low word)
	mov	es:[di].fi_sizelow, ax		; file end of data (low word)

	mov	ah,D2_MoveFilePtr		;@@ move a file pointer
	mov	al,0				;@@ mov from begin of file
	mov	cx,current_pos_hi		;@@ offset
	mov	dx,current_pos_lo		;@@
	int	21h				;@@ if error getting size
	jc	ErrorExit			;@@ then exit

	mov	al, bl				; AL <- file handle
	call	__api_devtab_ptr		; BX <- address of entry

	xor	ah, ah
	mov	al, byte ptr _TEXT:[bx].hi_attribute; get attr from table
	mov	es:[di].fi_attribute, ax	; file attribute

	xor	ax, ax
	mov	es:[di].fi_cdate, ax		; file creation date
	mov	es:[di].fi_ctime, ax		; file creation time
	mov	es:[di].fi_adate, ax		; date of last access
	mov	es:[di].fi_atime, ax		; time of last access

finfo4:
	jmp	short NormalExit	;@@ Added support for DOSErrorClass
ErrorExit:				;@@ added support for DOSErrorClass
	call	api_get_extended	;@@ added support for DOSErrorClass
NormalExit:				;@@ added support for DOSErrorClass
	call	__api_end	; check sigs & restore es,di,si,dx,cx,bx,ds,bp

	ret	10	; clear stack of entry parameters (bytes)

DOSQFILEINFO	endp

_TEXT	ends

	end
