;       SCCSID = @(#)d_sfinfo.asm	6.1 91/02/15
;	SCCSID = @(#)d_sfinfo.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_SFINFO.ASM - API stub routine DosSetFileInfo
;
;	Member of API library
;	Bill Mershon
;	Copyright MicroSoft Corporation, 1986
;	16-Jun-1986
;
;	library routine for API simulator
;
;	Called from dos 2.x,3.x compatible dos 5.x applications
;
;	Special Information
;		none
;
;	Modification History
;
;	09-Oct-86 (billme) remove code to copy date and time to
;	table - date/time are no longer kept there (see also
;	d_qfinfo.asm)
;
;	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.
;
;
;	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)
;
;	25-June-87 (robertc): P5770 & P5800 fix parm checking
;

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

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

LEVEL1			equ	1	; passed value for level 1 info
LEVEL1_INFO_SIZE	equ	4	; bytes needed in FileInfoBuf for info
;/********************** START OF SPECIFICATIONS *********************/
;/*								     */
;/* SUBROUTINE NAME: DosSetFileInfo				     */
;/*								     */
;/* DESCRIPTIVE NAME: Dos Set File Information			     */
;/*								     */
;/* FUNCTION: Specifies information for a file			     */
;/*								     */
;/*								     */
;/*								     */
;/* NOTES:    Real Mode Only					     */
;/*	      Simulates OS/2 call from DOS 2.x,3.x environment	     */
;/*								     */
;/* ENTRY POINT: DosSetFileInfo					     */
;/*								     */
;/*    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 -  retrieval area for 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:						     */
;/*								     */
;/* 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	     */
;/*								     */
;/*********************** END OF SPECIFICATIONS **********************/


;***	DOSSETFILEINFO
;
;	simulates DOS 5.0 call from DOS 2.x,3.x environment
;
;	errorcode = unsigned far pascal
;	DosSetFileInfo(FileHandle, FileInfoLevel, FileInfoBuf, FileInfoBufSize)
;
;	ENTRY:
;		FileHandle - file handle
;		FileInfoLevel - level of file information required
;		FileInfoBuf -  retrieval area for 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.
;		Get data from FileInfoBuf and use it to set the date
;		   and time for the file with the given handle.
;		restore registers
;		return
;
;	WARNING:
;		may return error code from Dos 2.x, 3.x (see dos manuals)
;
;	EFFECTS:
;		none
;

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

; In this code, we must both make a DOS 2/3 call (function 57h) to set
; the file info AND, if DosQFileInfo is installed, revise the table
; owned by DosOpen (see also d_qfinfo.asm).  We revise the table ONLY IF
; the call to DOS is successful (thus the DOS call is done first).
;
; The reason for this duplicity is that DosQFileInfo uses DosOpen's table
; as a resource for information (date, time, allocation, etc) so that
; the information in the table should be kept up to date.

DOFIND	segment byte common 'CODE'

	extrn	__api_do_find:byte		; DosSetFileInfo linked flag

DOFIND	ends


_TEXT	segment byte public 'CODE'

	assume	CS:_TEXT, DS:nothing

	public	DOSSETFILEINFO

	EXTRN	__api_dev_table : WORD


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

DOSSETFILEINFO	proc	far

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

	mov	ax,FileHandle	;
	cmp	ax,MAX_HANDLES	; is handle in range for real mode?
	jb	fChkVersion	; handle is ok
	mov	ax,ERROR_INVALID_HANDLE ;handle out of range error
	jmp	NormalExit ; quit

fChkVersion:
	call	_api_getvrsn	; get the DOS version
	cmp	ax,0A14h	;
	jb	finfo0		; 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) + 03 ; 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

finfo0:
	mov	ax, error_invalid_level		; AX <- error code
	cmp	word ptr [FileInfoLevel], LEVEL1 ; if req info level not valid
	jne	finfo5				; then go to exit point
finfo1:
	; is the size of FileInfoBuf big enough?

	mov	ax, error_insufficient_buffer  ; AX <- error code
	cmp	word ptr [FileInfoBufSize], LEVEL1_INFO_SIZE ; if size too small
	jl	finfo5				; then go to exit point

tstdev:
	mov	ax,FileHandle			;
	call	__api_devtab_ptr		; check the device table
	mov	ax,error_invalid_handle		; prepare error
	test	cs:[bx].hi_attrdev,testdev_mask ; is it a device
	jz	finfo2				;

	jmp	NormalExit			; then return error


finfo2:
	mov	ax,ERROR_INVALID_PARAMETER
	lds	bx, [FileInfoBuf]		; DS:BX <- pointer to date/time
	mov	cx,ds:[bx].fi_cdate		; @@create date must be 0
	or	cx,ds:[bx].fi_ctime		; @@create time must be 0
	or	cx,ds:[bx].fi_adate		; @@access date must be 0
	or	cx,ds:[bx].fi_atime		; @@access time must be 0
	or	cx,cx
	jnz	finfo5


	xor	ax,ax				; @@ no error
	mov	dx, ds:[bx].fi_wdate		; DX <- write date
	mov	cx, ds:[bx].fi_wtime		; CX <- write time
	or	dx,dx				; @@ is date 0
	jnz	DoIt				; @@ no so go set
	or	cx,cx				; @@ are both 0
	jz	finfo5				; @@ yes, exit


DoIt:
	mov	bx, [FileHandle]		; BX <- file handle
	mov	ah, D2_GetSetFileDT		; AH <- get/set date/time fcn
	mov	al, 1				; AL <- function code 'set'
	int	21h
					;@@ Added support for DOSErrorClass
	jc	ErrorExit			; if error, then exit
finfo4:
	xor	ax,ax				; clear error
finfo5:
	jmp	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)

DOSSETFILEINFO	endp

_TEXT	ends

	end
