// Loads a 32-bit integer from the file at the specified file offset. The saved value is assumed to have been
// processed by mputLong(). The lpResult is stored in *lpResult. Returns TRUE if successful (otherwise FALSE).
BOOL LoadInt32(LPCWSTR lpFilePath, uint32 *lpResult, int64 iFileOffset)
{
byte *lpBuffer = LoadFileBlock(lpFilePath, iFileOffset, sizeof(__int32));
if (lpBuffer != NULL)
{
byte *bufferPtr = (byte *)lpBuffer;
*lpResult = mgetLong(bufferPtr);
free(lpBuffer);
return TRUE;
}
return FALSE;
}
// Loads a 16-bit integer from the file at the specified file offset. The saved value is assumed to have been
// processed by mputWord(). The lpResult is stored in *lpResult. Returns TRUE if successful (otherwise FALSE).
BOOL LoadInt16(LPCWSTR lpFilePath, int *lpResult, int64 iFileOffset)
{
byte *lpBuffer = LoadFileBlock(lpFilePath, iFileOffset, sizeof(__int16));
if (lpBuffer != NULL)
{
byte *bufferPtr = (byte *)lpBuffer;
*lpResult = mgetWord(bufferPtr);
free(bufferPtr);
return TRUE;
}
return FALSE;
}
// Returns NULL if there's any error. Although the buffer can contain binary data, it is always null-terminated.
byte * LoadFileAlign(LPCWSTR lpFilePath, DWORD *lpSize, int iAlignSize)
{
byte * lpBuffer;
int iBufSize = 0;
HANDLE hFile = CreateFile(lpFilePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return NULL;
}
*lpSize = GetFileSize(hFile, NULL);
iBufSize = ((*lpSize - 1) / iAlignSize + 1)*iAlignSize + 1;
lpBuffer = (byte *)malloc(iBufSize);
if (lpBuffer == NULL)
{
CloseHandle(hFile);
return NULL;
}
memset(&lpBuffer[*lpSize], 0, iBufSize - *lpSize);
if (!ReadFile(hFile, lpBuffer, *lpSize, lpSize, NULL))
{
free(lpBuffer);
lpBuffer = NULL;
}
CloseHandle(hFile);
return lpBuffer;
}
// Returns NULL if there's any error. Although the buffer can contain binary data, it is always null-terminated.
byte * LoadFile(LPCWSTR lpFilePath, DWORD *lpSize)
{
byte * lpBuffer;
HANDLE hFile = CreateFile(lpFilePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return NULL;
}
*lpSize = GetFileSize(hFile, NULL);
lpBuffer = (byte *)malloc(*lpSize + 1);
if (lpBuffer == NULL)
{
CloseHandle(hFile);
return NULL;
}
lpBuffer[*lpSize] = 0;
if (!ReadFile(hFile, lpBuffer, *lpSize, lpSize, NULL))
{
free(lpBuffer);
lpBuffer = NULL;
}
CloseHandle(hFile);
return lpBuffer;
}
// Returns NULL if there's any error.
byte * LoadFileBlock(LPCWSTR lpFilePath, int64 iFileOffset, size_t count)
{
byte * lpBuffer;
DWORD dwBytesRead = 0;
LARGE_INTEGER iSeekOffset, iSeekOffsetNew;
HANDLE hFile = CreateFile(lpFilePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return NULL;
}
iSeekOffset.QuadPart = iFileOffset;
if (!SetFilePointerEx(hFile, iSeekOffset, &iSeekOffsetNew, FILE_BEGIN))
{
CloseHandle(hFile);
return NULL;
}
lpBuffer = (byte *)malloc(count);
if (lpBuffer == NULL)
{
CloseHandle(hFile);
return NULL;
}
if (!ReadFile(hFile, lpBuffer, count, &dwBytesRead, NULL) || dwBytesRead != count)
{
CloseHandle(hFile);
free(lpBuffer);
return NULL;
}
CloseHandle(hFile);
return lpBuffer;
}
// Returns -1 if there is an error, or the size of the file.
int64 GetFileSize64(LPCWSTR lpPath)
{
LARGE_INTEGER iSize;
HANDLE hFile = CreateFile(lpPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return -1;
}
if (GetFileSizeEx(hFile, &iSize) == 0)
{
return -1;
}
CloseHandle(hFile);
return iSize.QuadPart;
}
// Returns -1 if the specified string is not found in the buffer. Otherwise, returns the
// offset of the first occurrence of the string. The string and the buffer may contain zeroes,
// which do NOT terminate them.
int64 FindString(void* lpBuffer, const char* lpString, int64 iBufLen, size_t iStrLen, int64 iStartOffset)
{
if (lpBuffer == NULL || lpString == NULL || iStrLen > iBufLen || iBufLen < 1 || iStrLen < 1 || iStartOffset > iBufLen - iStrLen)
{
return -1;
}
for (int64 iIndex = iStartOffset; iIndex <= iBufLen - iStrLen; iIndex++)
{
if (memcmp((byte*)lpBuffer + iIndex, lpString, iStrLen) == 0)
{
return iIndex;
}
}
return -1;
}
// Returns TRUE if the file or directory exists (both may be enclosed in quotation marks).
BOOL FileExists(LPCWSTR lpFilePath)
{
WCHAR szFilePath[CC_LONG_PATH+1];
// Strip quotation marks (if any)
if (wcslen(lpFilePath) > 1 && lpFilePath[0] == '"')
{
wcscpy(szFilePath, lpFilePath + 1);
}
else
{
wcscpy(szFilePath, lpFilePath);
}
// Strip quotation marks (if any)
if (wcslen(szFilePath) > 1 && szFilePath[wcslen(szFilePath) - 1] == '"')
{
szFilePath[wcslen(szFilePath) - 1] = 0;
}
return (_waccess(szFilePath, 0) != -1);
}
// Searches the file from its end for the LAST occurrence of the string str.
// The string may contain zeroes, which do NOT terminate the string.
// If the string is found, its offset from the start of the file is returned.
// If the string isn't found or if any error occurs, -1 is returned.
int64 FindStringInFile(LPCWSTR lpFilePath, const char* lpString, int iStrLen)
{
int iBufSize = 64 * BYTES_PER_KB;
byte * lpBuffer = (byte *)err_malloc(iBufSize);
HANDLE hFile = NULL;
DWORD dwBytesRead;
BOOL bReadRetVal;
int64 iFilePos = GetFileSize64(lpFilePath);
int iBufPos = 0;
LARGE_INTEGER iSeekOffset, iSeekOffsetNew;
BOOL bExit = FALSE;
int iFilePosStep;
int64 iRetCode = -1;
if (iFilePos <= 0 || lpBuffer == NULL || iStrLen > iBufSize || iStrLen < 1)
{
return -1;
}
hFile = CreateFile(lpFilePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
free(lpBuffer);
return -1;
}
iFilePosStep = iBufSize - iStrLen + 1;
do
{
iFilePos -= iFilePosStep;
if (iFilePos < 0)
{
iFilePos = 0;
bExit = TRUE;
}
iSeekOffset.QuadPart = iFilePos;
if (!SetFilePointerEx(hFile, iSeekOffset, &iSeekOffsetNew, FILE_BEGIN))
{
goto fsif_end;
}
bReadRetVal = ReadFile(hFile, lpBuffer, iBufSize, &dwBytesRead, NULL);
if (!bReadRetVal || dwBytesRead == 0)
{
goto fsif_end;
}
iBufPos = dwBytesRead - iStrLen;
while (iBufPos > 0)
{
if (memcmp(lpBuffer + iBufPos, lpString, iStrLen) == 0)
{
// String found
iRetCode = iFilePos + iBufPos;
goto fsif_end;
}
iBufPos--;
}
} while (!bExit);
fsif_end:
CloseHandle(hFile);
free(lpBuffer);
return iRetCode;
}
// System CopyFile() copies source file attributes (like FILE_ATTRIBUTE_ENCRYPTED)
// so we need to use our own copy function
BOOL CCXCopyFile(LPCWSTR lpSrcFileName, LPCWSTR lpDstFileName)
{
byte * lpBuffer = NULL;
HANDLE hFileSrc = NULL, hFileDst = NULL;
FILETIME tFileTime;
DWORD dwBytesRead, dwBytesWritten;
BOOL bResult;
hFileSrc = CreateFile(lpSrcFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hFileSrc == INVALID_HANDLE_VALUE)
{
return FALSE;
}
hFileDst = CreateFile(lpDstFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (hFileDst == INVALID_HANDLE_VALUE)
{
CloseHandle(hFileSrc);
return FALSE;
}
lpBuffer = (byte *)malloc(64 * 1024);
if (lpBuffer == NULL)
{
CloseHandle(hFileSrc);
CloseHandle(hFileDst);
return FALSE;
}
while (bResult = ReadFile(hFileSrc, lpBuffer, 64 * 1024, &dwBytesRead, NULL))
{
if (dwBytesRead == 0)
{
bResult = 1;
break;
}
if (!WriteFile(hFileDst, lpBuffer, dwBytesRead, &dwBytesWritten, NULL) || dwBytesRead != dwBytesWritten)
{
bResult = 0;
break;
}
}
GetFileTime(hFileSrc, NULL, NULL, &tFileTime);
SetFileTime(hFileDst, NULL, NULL, &tFileTime);
CloseHandle(hFileSrc);
CloseHandle(hFileDst);
free(lpBuffer);
return bResult;
}
// If bAppend is TRUE, the buffer is appended to an existing file. If bAppend is FALSE, any existing file
// is replaced. If an error occurs, the incomplete file is deleted (provided that bAppend is FALSE).
BOOL SaveBufferToFile(LPCWSTR lpFilePath, void* lpBuffer, DWORD iBufLen, BOOL bAppend)
{
HANDLE hFile;
DWORD dwBytesWritten;
BOOL bResult = TRUE;
hFile = CreateFile(lpFilePath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, bAppend ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}
if (bAppend)
{
SetFilePointer(hFile, 0, NULL, FILE_END);
}
if (!WriteFile(hFile, lpBuffer, iBufLen, &dwBytesWritten, NULL) || iBufLen != dwBytesWritten)
{
bResult = FALSE;
}
//if (!bResult)
//{
// // If CREATE_ALWAYS is used, ERROR_ALREADY_EXISTS is returned after successful overwrite of an existing file (it's not an error)
// if (bAppend || GetLastError() != ERROR_ALREADY_EXISTS)
// {
// handleWin32Error(g_hMainDlg);
// }
//}
DWORD dwError = GetLastError();
CloseHandle(hFile);
if (!bResult && !bAppend)
{
_wremove(lpFilePath);
}
SetLastError(dwError);
return bResult;
}