// Common, groups Files and WinWrap
// Copyright Alexander Liss
#include "filewin.h"
File::File(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
LPSECURITY_ATTRIBUTES lpSA,
HANDLE hTemplateFile
)
{
handle=::CreateFile(lpFileName,dwDesiredAccess,dwShareMode,lpSA,dwCreationDisposition,dwFlagsAndAttributes,hTemplateFile);
}
BOOL File::get_type(DWORD& type)
{
if(!is_valid_handle(handle)) return FALSE;
type=GetFileType(handle);
return TRUE;
}
BOOL File::get_size( DWORD& FileSize)
{
if(!is_valid_handle(handle)) return FALSE;
FileSize=::GetFileSize(handle,0);
return TRUE;
}
BOOL File::get_size( ULARGE_INTEGER& FileSize)
{
if(!is_valid_handle(handle)) return FALSE;
FileSize.LowPart=::GetFileSize(handle,&FileSize.HighPart);
return TRUE;
}
BOOL File::set_pointer(
LONG DistanceToMove,
DWORD dwMoveMethod
)
{
if(!is_valid_handle(handle)) return FALSE;
::SetFilePointer(handle,DistanceToMove,0,dwMoveMethod);
DWORD g=GetLastError();
if(g!=NO_ERROR) return FALSE;
return TRUE;
}
// LONG - DWORD in 2nd parameter of SetFilePointer
BOOL File::set_pointer(
LARGE_INTEGER DistanceToMove,
DWORD dwMoveMethod
)
{
if(!is_valid_handle(handle)) return FALSE;
LARGE_INTEGER z=DistanceToMove;
::SetFilePointer(handle,*((LONG*)&z.LowPart),&z.HighPart,dwMoveMethod);
DWORD g=GetLastError();
if(g!=NO_ERROR) return FALSE;
return TRUE;
}
BOOL File::set_file_end()
{
if(!is_valid_handle(handle)) return FALSE;
return ::SetEndOfFile(handle);
}
BOOL File::current_pointer(DWORD& place)
{
if(!is_valid_handle(handle)) return FALSE;
place=::SetFilePointer(handle,0,0,FILE_CURRENT);
DWORD g=GetLastError();
if(g!=NO_ERROR) return FALSE;
return TRUE;
}
BOOL File::current_pointer(ULARGE_INTEGER& place)
{
if(!is_valid_handle(handle)) return FALSE;
LARGE_INTEGER z;
memset(&z,0,sizeof(z));
z.LowPart=::SetFilePointer(handle,0,&z.HighPart,FILE_CURRENT);
DWORD g=GetLastError();
if(g!=NO_ERROR) return FALSE;
place.LowPart=z.LowPart;
place.HighPart=z.HighPart;
return TRUE;
}
BOOL File::read(
DWORD& BytesActual,
LPVOID lpBuffer,
DWORD dwBytesLimit
)
{
if(!is_valid_handle(handle)) return FALSE;
return ::ReadFile(handle,lpBuffer,dwBytesLimit,&BytesActual,0);
}
BOOL File::write(
DWORD& BytesActual,
LPVOID lpBuffer,
DWORD dwBytesLimit
)
{
if(!is_valid_handle(handle)) return FALSE;
return ::WriteFile(handle,lpBuffer,dwBytesLimit,&BytesActual,0);
}
BOOL File::flush()
{
if(!is_valid_handle(handle)) return FALSE;
return ::FlushFileBuffers(handle);
}
BOOL File::lock(
DWORD dwFileOffsetLow,
DWORD dwFileOffsetHigh,
DWORD nNumberOfBytesToLockLow,
DWORD nNumberOfBytesToLockHigh
)
{
if(!is_valid_handle(handle)) return FALSE;
return ::LockFile(handle,dwFileOffsetLow,dwFileOffsetHigh,nNumberOfBytesToLockLow,nNumberOfBytesToLockHigh);
}
BOOL File::unlock(
DWORD dwFileOffsetLow,
DWORD dwFileOffsetHigh,
DWORD nNumberOfBytesToLockLow,
DWORD nNumberOfBytesToLockHigh
)
{
if(!is_valid_handle(handle)) return FALSE;
return ::UnlockFile(handle,dwFileOffsetLow,dwFileOffsetHigh,nNumberOfBytesToLockLow,nNumberOfBytesToLockHigh);
}
BOOL File::cancel()
{
if(!is_valid_handle(handle)) return FALSE;
return ::CancelIo(handle);
}
// AsyncFileOperation
void AsyncFileOperation::clear()
{
handle=0;
memset(&overlapped,0,sizeof(overlapped));
}
BOOL AsyncFileOperation::lock(
DWORD nNumberOfBytesToLockLow,
DWORD nNumberOfBytesToLockHigh,
DWORD dwFlags
)
{
if(!is_valid_handle(handle)) return FALSE;
return ::LockFileEx(handle,dwFlags,0,nNumberOfBytesToLockLow,nNumberOfBytesToLockHigh,&overlapped);
}
BOOL AsyncFileOperation::unlock(
DWORD nNumberOfBytesToLockLow,
DWORD nNumberOfBytesToLockHigh
)
{
if(!is_valid_handle(handle)) return FALSE;
return ::UnlockFileEx(handle,0,nNumberOfBytesToLockLow,nNumberOfBytesToLockHigh,&overlapped);
}
BOOL AsyncFileOperation::get_result(
DWORD& dwTransfer,
BOOL bWait
)
{
if(!is_valid_handle(handle)) return FALSE;
return ::GetOverlappedResult(handle,&overlapped,&dwTransfer,bWait);
}
// AsyncReadWrite
BOOL AsyncReadWrite::read(
DWORD& BytesActual,
LPVOID lpBuffer,
DWORD dwBytesLimit
)
{
if(!is_valid_handle(handle)) return FALSE;
return ::ReadFile(handle,lpBuffer,dwBytesLimit,&BytesActual,&overlapped);
}
BOOL AsyncReadWrite::write(
DWORD& BytesActual,
LPVOID lpBuffer,
DWORD dwBytesLimit
)
{
if(!is_valid_handle(handle)) return FALSE;
return ::WriteFile(handle,lpBuffer,dwBytesLimit,&BytesActual,&overlapped);
}
BOOL AsyncReadWrite::read_loop(DWORD& BytesActual,LPVOID lpBuffer, DWORD dwBytes,
DWORD timeout, DWORD wait_slice)
{
if(!is_valid_handle(handle)) return FALSE;
if(wait_slice<1 || timeout<1) return FALSE;
BytesActual=0;
BOOL success=FALSE,result=TRUE;
DWORD z=0;
DWORD period=0;
while(BytesActual<dwBytes)
{
z=0;
success=read(z,(char*)lpBuffer+BytesActual,dwBytes-BytesActual);
if(success)
{
BytesActual+=z;
continue;
}
if(!success)
{
BytesActual+=z;
result=FALSE;
break;
}
for(;;)
{
period+=wait_slice;
if(period>timeout)
{
result=FALSE;
break;
}
wait(wait_slice);
BOOL success=get_result(z,FALSE);
if(success) break;
}
BytesActual+=z;
}
return result;
}
BOOL AsyncReadWrite::write_loop(DWORD& BytesActual,LPVOID lpBuffer,DWORD dwBytes,
DWORD timeout, DWORD wait_slice)
{
if(!is_valid_handle(handle)) return FALSE;
if(wait_slice<1 || timeout<1) return FALSE;
BytesActual=0;
BOOL success=FALSE,result=TRUE;
DWORD z=0;
DWORD period=0;
while(BytesActual<dwBytes)
{
z=0;
success=write(z,(char*)lpBuffer+BytesActual,dwBytes-BytesActual);
if(success)
{
BytesActual+=z;
continue;
}
if(!success)
{
BytesActual+=z;
result=FALSE;
break;
}
for(;;)
{
period+=wait_slice;
if(period>timeout)
{
result=FALSE;
break;
}
wait(wait_slice);
BOOL success=get_result(z,FALSE);
if(success) break;
}
BytesActual+=z;
}
return result;
}
// AsyncReadWriteEx
BOOL AsyncReadWriteEx::read(LPVOID lpBuffer, DWORD dwBytesLimit )
{
if(!is_valid_handle(handle)) return FALSE;
return ::ReadFileEx(handle,lpBuffer,dwBytesLimit,&overlapped,completion_routine);
}
BOOL AsyncReadWriteEx::write(
LPVOID lpBuffer,
DWORD dwBytesLimit
)
{
if(!is_valid_handle(handle)) return FALSE;
return ::WriteFileEx(handle,lpBuffer,dwBytesLimit,&overlapped,completion_routine);
}