1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
/*
** Move the current position of the file handle passed as the first
** argument to offset iOffset within the file. If successful, return 0.
** Otherwise, set pFile->lastErrno and return non-zero.
*/
static int seekWinFile(HANDLE h, __int64 iOffset)
{
LONG upperBits; /* Most sig. 32 bits of new offset */
LONG lowerBits; /* Least sig. 32 bits of new offset */
DWORD dwRet; /* Value returned by SetFilePointer() */
upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
lowerBits = (LONG)(iOffset & 0xffffffff);
/* API oddity: If successful, SetFilePointer() returns a dword
** containing the lower 32-bits of the new file-offset. Or, if it fails,
** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
** whether an error has actually occured, it is also necessary to call
** GetLastError().
*/
dwRet = SetFilePointer(h, lowerBits, &upperBits, FILE_BEGIN);
if(dwRet==INVALID_SET_FILE_POINTER)
{
return 1;
}
return 0;
}
/*
** Close a file.
**
** It is reported that an attempt to close a handle might sometimes
** fail. This is a very unreasonable result, but windows is notorious
** for being unreasonable so I do not doubt that it might happen. If
** the close fails, we pause for 100 milliseconds and try again. As
** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before
** giving up and returning an error.
*/
static int winClose(HANDLE h)
{
int rc;
rc = CloseHandle(h);
return rc ? 0 : 1;
}
/*
** Read data from a file into a buffer. Return SQLITE_OK if all
** bytes were read successfully and SQLITE_IOERR if anything goes
** wrong.
*/
static int winRead(
HANDLE h, /* File to read from */
void *pBuf, /* Write content into this buffer */
int amt, /* Number of bytes to read */
__int64 offset /* Begin reading at this offset */
)
{
DWORD nRead; /* Number of bytes actually read from file */
if( seekWinFile(h, offset) ){
return 1;
}
if( !ReadFile(h, pBuf, amt, &nRead, 0) ){
return 1;
}
return 0;
}
/*
** Write data from a buffer into a file. Return SQLITE_OK on success
** or some other error code on failure.
*/
static int winWrite (
HANDLE h, /* File to write into */
const void *pBuf, /* The bytes to be written */
int amt, /* Number of bytes to write */
__int64 offset /* Offset into the file to begin writing at */
)
{
int rc; /* True if error has occured, else false */
rc = seekWinFile(h, offset);
if( rc==0 ){
unsigned char *aRem = (unsigned char *)pBuf; /* Data yet to be written */
int nRem = amt; /* Number of bytes yet to be written */
DWORD nWrite; /* Bytes written by each WriteFile() call */
while( nRem>0 && WriteFile(h, aRem, nRem, &nWrite, 0) && nWrite>0 ){
aRem += nWrite;
nRem -= nWrite;
}
}
if( rc ){
return 1;
}
return 0;
}
/*
** Truncate an open file to a specified size
*/
static int winTruncate(HANDLE h, __int64 nByte)
{
int rc = 0; /* Return code for this function */
/* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
if( seekWinFile(h, nByte) ){
rc = 1;
}else if( 0==SetEndOfFile(h) ){
rc = 1;
}
return rc;
}
/*
** Determine the current size of a file in bytes
*/
static int winFileSize(HANDLE h, __int64 *pSize){
DWORD upperBits;
DWORD lowerBits;
DWORD error;
lowerBits = GetFileSize(h, &upperBits);
if(lowerBits == INVALID_FILE_SIZE)
{
return 1;
}
*pSize = (((__int64)upperBits)<<32) + lowerBits;
return 0;
}
Пример использования:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HANDLE file=CreateFile("c:\\test.dat",GENERIC_WRITE,FILE_ SHARE_READ | FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,0,0);
winTruncate(file, (__int64)10737418240);
unsigned char buff[256];FillMemory(buff,256,'1');
winWrite(file, buff, 256, (__int64)0);
CloseHandle(file);
}
|