%include "vxdn.inc"
%include "win32n.inc"
%include "util.mac"


global OpenFile32
global CloseFile32
global SeekFile32
global ReadFile32
global WriteFile32
global GetFileSize32
global SaveBufferToDisk
global AppendBufferToDisk
global GetSystemDirectory

bits 32


struc R0File
.r0handle:	resd 1
.seekoffset:	resd 1
.filesize:	resd 1
endstruc


segment _LTEXT

;HANDLE OpenFile32(char *FNAME, DWORD MODE, DWORD OPERATION);
;
;MODE  	   can be OPEN_EXISTING, CREATE, ...
;OPERATION can be GENERIC_READ, GENERIC_WRITE, ...
;
; return -1 on failure

OpenFile32:
	push	ebp
	mov	ebp,esp
	sub	esp, byte 4
	push	ebx
	push	ecx
	push	edx
	push	esi

%define FNAME ebp+8
%define MODE ebp+12
%define OPERATION ebp+16

%define handle ebp-4

	VMMCall	_HeapAllocate, byte R0File_size, dword HEAPZEROINIT
	or	eax,eax
	jz	near .error

	mov	[handle],eax

	mov	ebx,0x2040                 ; DENYNONE
	cmp	dword [OPERATION],GENERIC_READ
	jz	.parseMode

	mov	ebx,0x2021                 ; DENY WRITE
	cmp	dword [OPERATION],GENERIC_WRITE
	jz	.parseMode

	mov	ebx,0x2022                 ; DENY WRITE
	cmp	dword [OPERATION],GENERIC_READWRITE
	jz	.parseMode

	mov	ebx,0x2022                 ; DENY WRITE
	cmp	dword [OPERATION],GENERIC_ALL
	jnz	near .errorFree

.parseMode:
	mov	edx,0x10
	cmp	dword [MODE],byte CREATE_NEW
	jz	.open

	mov	edx,0x12
	cmp	dword [MODE],byte CREATE_ALWAYS
	jz	.open

	mov	edx,0x01
	cmp	dword [MODE],byte OPEN_EXISTING
	jz	.open

	mov	edx,0x11
	cmp	dword [MODE],byte OPEN_ALWAYS
	jz	.open

	mov	edx,0x02
	cmp	dword [MODE],byte TRUNCATE_EXISTING
	jnz	.errorFree

.open:
	mov	esi,[FNAME]
	mov	ecx,0x20		; archive
	mov	eax,R0_OPENCREAT_IN_CONTEXT
	VxDCall	IFSMgr_Ring0_FileIO
	jb	.errorFree

	mov	esi,[handle]
	mov	[esi+R0File.r0handle],eax
	mov	ebx,eax

	mov	eax,R0_GETFILESIZE
	VxDCall	IFSMgr_Ring0_FileIO
	jb	.errorClose

	mov	esi,[handle]
	mov	[esi+R0File.filesize],eax
	mov	eax,[handle]
	jmp	short .ret

.errorClose:
	mov	eax,R0_CLOSEFILE
	mov	ebx,[handle]
	mov	ebx,[ebx+R0File.r0handle]
	VxDCall	IFSMgr_Ring0_FileIO

.errorFree:
	VMMCall	_HeapFree, dword [handle], byte 0

.error:
	or	eax,byte -1

.ret:
	pop	esi
	pop	edx
	pop	ecx
	pop	ebx

	mov	esp,ebp
	pop	ebp

%undef FNAME
%undef MODE
%undef OPERATION

%undef handle

	retn	12


;CloseFile32(HANDLE hFILE);
;
; return TRUE on success

CloseFile32:
	push	ebp
	mov	ebp,esp
	push	ebx
	push	ecx
	push	edx

%define hFile ebp+8

	mov	ebx, [hFile]
	mov	ebx, [ebx+R0File.r0handle]
	mov	eax, R0_CLOSEFILE
	VxDCall	IFSMgr_Ring0_FileIO

	VMMCall	_HeapFree, dword [hFile], byte 0

	mov	eax,TRUE
	pop	edx
	pop	ecx
	pop	ebx
	pop	ebp

%undef hFile

	retn	4


;DWORD SeekFile32(HANDLE hFILE, DWORD OFFSET, DWORD START);
;
; START can be FILE_BEGIN, FILE_CURRENT, FILE_END
;
; Return Actual Offset after operation.
; return filesize as/on EOF

SeekFile32:
	push	ebp
	mov	ebp,esp
	push	ebx

%define hFILE ebp+8
%define OFFSET ebp+12
%define START ebp+16

	mov	eax,[hFILE]
	mov	ebx,[OFFSET]

	cmp	dword [START],byte FILE_BEGIN
	jnz	@F

	cmp	ebx,[eax+R0File.filesize]
	jbe	.seek

	mov	ebx,[eax+R0File.filesize]
	jmp	short .seek

@@
	cmp	dword [START],byte FILE_CURRENT
	jnz	@F

	add	ebx,[eax+R0File.seekoffset]
	cmp	ebx,[eax+R0File.filesize]
	jbe	.seek

	mov	ebx,[eax+R0File.filesize]
	jmp	short .seek

@@
	cmp	dword [START],byte FILE_END
	jnz	@F

	add	ebx,[eax+R0File.filesize]
	cmp	ebx,[eax+R0File.filesize]
	jbe	.seek

@@
	mov	ebx,[eax+R0File.filesize]
	jmp	short .seek

.seek:

	mov	[eax+R0File.seekoffset],ebx
	mov	eax,ebx

	pop	ebx
	pop	ebp

%undef hFILE
%undef OFFSET
%undef START

	retn	12


;BOOL ReadFile32(HANDLE hFile, HANDLE hBuf, DWORD size);
;
; Return 1 on success.

ReadFile32:
	push	ebp
	mov	ebp,esp
	push	ebx
	push	ecx
	push	edx
	push	esi

%define hFile ebp+8
%define hBuf ebp+12
%define size ebp+16

	mov	esi,[hBuf]
	mov	ebx,[hFile]
	mov	edx,[ebx+R0File.seekoffset]
	mov	ecx,[size]
	mov	ebx,[ebx+R0File.r0handle]
	mov	eax,R0_READFILE_IN_CONTEXT
	VxDCall IFSMgr_Ring0_FileIO

	sbb	eax,eax
	inc	eax

	pop	esi
	pop	edx
	pop	ecx
	pop	ebx
	pop	ebp

%undef hFile
%undef hBuf
%undef size

	retn	12


;BOOL WriteFile32(HANDLE hFile, HANDLE hBuf, DWORD size);
;
; Return 1 on success.

WriteFile32:
	push	ebp
	mov	ebp,esp
	push	ebx
	push	ecx
	push	edx
	push	esi

%define hFile ebp+8
%define hBuf ebp+12
%define size ebp+16

	mov	esi,[hBuf]
	mov	ebx,[hFile]
	mov	edx,[ebx+R0File.seekoffset]
	mov	ecx,[size]
	mov	ebx,[ebx+R0File.r0handle]
	mov	eax,R0_WRITEFILE_IN_CONTEXT
	VxDCall	IFSMgr_Ring0_FileIO

	sbb	eax,eax
	inc	eax

	pop	esi
	pop	edx
	pop	ecx
	pop	ebx
	pop	ebp

%undef hFile
%undef hBuf
%undef size

	retn	12


;DWORD GetFileSize32(char *FNAME);
;
; Return 0 on failure.

GetFileSize32:
	push	ebp
	mov	ebp,esp

%define FNAME ebp+8

	push	dword GENERIC_READ
	push	byte OPEN_EXISTING
	push	dword [FNAME]
	call	OpenFile32
	inc	eax
	jz	.ret

	dec	eax
	push	dword [eax+R0File.filesize]

	push	eax
	call	CloseFile32

	pop	eax

.ret:
	pop	ebp

%undef FNAME

	retn	4


;BOOL SaveBufferToDisk(HANDLE hBuf, DWORD size, char *FNAME);
;
; Return 0 on failure.

SaveBufferToDisk:
	push	ebp
	mov	ebp,esp

%define hBuf ebp+8
%define size ebp+12
%define FNAME ebp+16

	push	dword GENERIC_WRITE
	push	byte CREATE_ALWAYS
	push	dword [FNAME]
	call	OpenFile32
	inc	eax
	jz	.ret

	dec	eax
	push	eax			; handle for close

	push	dword [size]
	push	dword [hBuf]
	push	eax
	call	WriteFile32

	call	CloseFile32

.ret:
	pop	ebp

%undef hBuf
%undef size
%undef FNAME

	retn	12


;BOOL AppendBufferToDisk(HANDLE hBuf, DWORD size, DWORD offset, char *FNAME);
;
; Return 0 on failure.

AppendBufferToDisk:
	push	ebp
	mov	ebp,esp

%define hBuf ebp+8
%define size ebp+12
%define offset ebp+16
%define FNAME ebp+20

	push	dword GENERIC_WRITE
	push	byte OPEN_ALWAYS	; OPEN?
	push	dword [FNAME]
	call	OpenFile32
	inc	eax
	jz	.ret

	dec	eax
	push	eax			; handle for close
	push	eax			; handle for write

	push	byte FILE_BEGIN
	push	dword [offset]
	push	eax
	call	SeekFile32

	pop	eax

	push	dword [size]
	push	dword [hBuf]
	push	eax
	call	WriteFile32

	call	CloseFile32

.ret:
	pop	ebp

%undef hBuf
%undef size
%undef offset
%undef FNAME

	retn	16


; DWORD GetSystemDirectory(CHAR *Buffer, DWORD MAXPATH);
;
; Return length or 0 on failure.

GetSystemDirectory:
	push	ebp
	mov	ebp,esp

	push	ecx
	push	edx
	push	esi
	push	edi

%define Buffer ebp+8
%define MAXPATH ebp+12

	mov	esi,windir
	VMMCall	Get_Environment_String
	mov	eax,0
	jc	.ret

	mov	ecx,[MAXPATH]
	sub	ecx,byte 8
	mov	edi,edx
	repnz	scasb
	jnz	.ret

	sub	edi,edx			; length+1
	lea	eax,[edi-1+7]		; '\SYSTEM'
	lea	ecx,[edi-1]		; length

	mov	esi,edx
	mov	edi,[Buffer]
	rep	movsb

	mov	dword [edi],'\SYS'	; '\SYSTEM',0
	mov	dword [edi+4],'TEM'

.ret:
	pop	edi
	pop	esi
	pop	edx
	pop	ecx

	pop	ebp

%undef Buffer
%undef MAXPATH

	retn	8


segment _LDATA
windir:	db 'WINDIR',0
