Why are these 2 sectors different? - c++

i tried to read ntfs partition.
main function:
int main(int argc, char** argv)
{
BYTE sector[512];
ReadSector(L"\\\\.\\E:", 0, sector);
PrintBPB(ReadBPB(sector));
BYTE sector2[512];
ReadSector(L"\\\\.\\E:", 0, sector2);
PrintBPB(ReadBPB(sector2));
return 0;
}
ReadSector function:
int ReadSector(LPCWSTR drive, long readPoint, BYTE sector[Sector_Size])
{
int retCode = 0;
DWORD bytesRead;
HANDLE device = NULL;
device = CreateFile(drive, // Drive to open
GENERIC_READ, // Access mode
FILE_SHARE_READ | FILE_SHARE_WRITE, // Share Mode
NULL, // Security Descriptor
OPEN_EXISTING, // How to create
0, // File attributes
NULL); // Handle to template
if (device == INVALID_HANDLE_VALUE) // Open Error
{
printf("CreateFile: %u\n", GetLastError());
return 1;
}
SetFilePointer(device, readPoint, NULL, FILE_BEGIN);//Set a Point to Read
if (!ReadFile(device, sector, 512, &bytesRead, NULL))
{
printf("ReadFile: %u\n", GetLastError());
}
else
{
printf("Success!\n");
}
CloseHandle(device);
}
I think the way I copy those bytes into my BPB bpb is fine.
So what happend? Why they are different?
I can figure out that its relate to winapi, readfile, createfile but I still dont understand it :(
sorry for my bad english.

The bug is in the code we cannot see: PrintBPB. Apparently it switches to hexadecimal output (for the "Volume serial number") and then fails to switch back to decimal until later.
When the code calls PrintBPB a second time the output mode is still in hexadecimal format, and printing "Bytes per Sector" now displays 200 (0x200 is the same value as 512).
If you need to know whether two chunks of memory hold identical values, just memcmp them. This avoids introducing a bug in a transformation (such as console output).

Related

Why the file could be written after changing the attribute to readonly under windows?

Given one normal file, it could be read and written. Then I change this file attribute to Read-only through
However, this file still could be written through file handler. Here are my codes
#define CREATE_FILE_OPT FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS
std::string name("test.txt");
HANDLE hfile = ::CreateFile(name.c_str(),
GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, CREATE_FILE_OPT, NULL);
if (hfile == INVALID_HANDLE_VALUE) {
hfile = ::CreateFile(name.c_str(),
GENERIC_READ | GENERIC_WRITE, NULL, NULL, CREATE_NEW, CREATE_FILE_OPT, NULL);
if (hfile == INVALID_HANDLE_VALUE) {
printf("so sad, invalid file handler....");
return -1;
}
}
int i = 0;
char rbuf[] = "you are";
DWORD bytesWritten;
do {
Sleep(5000);
++i;
bytesWritten = 0;
BOOL bret = ::WriteFile(hfile, rbuf, strlen(rbuf), &bytesWritten, NULL);
if (bret == FALSE) {
printf("Cannot write bytes into file.....");
DWORD err = GetLastError();
printf("The error code is %d\n", err);
}
else
printf("write %d bytes to file\n", bytesWritten);
DWORD ret = GetFileAttributes(name.c_str());
printf("The file attribute is %d\n", ret);
} while (i < 10000);
The file attribute is 32 before I change it to Read-only, but it will be 33 after this file is Read-only.
I want to know why the file could be written after change it to Read-only? Is there any issue in my test codes?
PS: test it in VS2015 under windows 7.
Sorry, I get your meaning finally. I guess you are talking about creating a file first, setting it readonly without closing the program. The READONLY attribute check only happens in CreateFile routine.
In Windows kernel, every object is assigned a temporary access right list once created, unless explicitly refreshed, a thing seldom happens on actual files on fixed disks. So even if you deny all rights after CreateFile using NTFS access control, your program will behave just as when CreateFile is called.
In conclusion, it is natural your program can still write to the file, after your hot-changing it into READONLY, which only writes information onto disk, not changing kernel access table.

Fastest way to write raw data to hard drive (PhysicalDrive) on Windows 7

My company is developing a "fancy" USB Mass Storage Device running under Windows 7. The Mass Storage Client Driver that handles the reading and writing to the actual storage media on the client side is being written in C++. The problem we are having is very, very slow write speeds. About 30 times slower than expected. We are using calls to WriteFile() to write blocks of data to the storage media (specifically the physical drive 'PhysicalDrive2') as they are received from the Host device. I have read in many other forums that people have experience very slow write speeds using WriteFile() especially on Windows 7. So I am trying to figure out if I am using the best method and function calls for this particular task.
Below are two blocks of code. One for LockVolume() function that gets called one time by the program during initialization and actually just unmounts the volume. The other block of code is WriteSector() which is used to write the actual data to the physical drive when its received by the USB Client controller driver. I am hoping that someone can shed some light on what I might be doing wrong or provided suggestions on a better way to implement this.
short WriteSector
(LPCWSTR _dsk, // disk to access
char *&_buff, // buffer containing data to be stored
unsigned int _nsect, // sector number, starting with 0
ULONG Blocks
)
{
DWORD bytesWritten;
wchar_t errMsg[256];
//attempt to get a handle to the specified volume or physical drive
HANDLE hDisk = CreateFile(_dsk, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
//make sure we have a handle to the specified volume or physical drive
if(hDisk==INVALID_HANDLE_VALUE)
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
OutputDebugString(errMsg);
printf("Error attempting to get a handle to the device! (%s)\n", errMsg);
goto exit;
}
// set pointer to the sector on the disk that we want to write to
SetFilePointer(hDisk, (_nsect * SIZE_OF_BLOCK), 0, FILE_BEGIN);
//write the data
if (!WriteFile(hDisk, _buff, (Blocks * SIZE_OF_BLOCK), &bytesWritten, NULL))
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
printf("WriteFile failed! (%s)\n", errMsg);
goto exit;
}
exit:
CloseHandle(hDisk);
writeMutex.unlock();
return 0;
}
UINT Disk_LockVolume(LPCWSTR _dsk)
{
HANDLE hVol;
LPWSTR errMsg;
DWORD status;
bool success = false;
//now try to get a handle to the specified volume so we can write to it
hVol = CreateFile(_dsk, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
//check to see if we were able to obtain a handle to the volume
if( hVol == INVALID_HANDLE_VALUE )
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
printf("Disk_LockVolume() - CreateFile failed (%s)\n", errMsg);
goto exit;
}
// now lock volume
if (!DeviceIoControl(hVol, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &status, NULL))
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
printf("Disk_LockVolume() - Error attempting to lock device! (%s)\n", errMsg);
goto exit;
}
//dismount the device
if (!DeviceIoControl(hVol, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &status, NULL))
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
printf("Disk_LockVolume() - Error attempting to dismount volume. (%s)\n", errMsg);
goto exit;
}
exit:
CloseHandle(hVol);
return 1;
}
EDIT #1 (2/10/2015)
So I incorporated the suggestions made by Ben Voigt and found that calling CreateFile and CloseHandle only once (instead of every time we want to write data to the drive) significantly improved write speed. 80% increase. Even with that increase, the write speed was still much slower than expected. Around 6 times slower. So I then incorporated his other suggested change which included eliminating the original call to SetFilePointer() and replace it with and OVERLAPPED structure that now gets passed to WriteFile. After I made that change, I now get and error that states "stack around the variable 'MyOverLappedStructure' was corrupted". Below is the updated version of my SectorWrite function along with the new Disk_GetHandle() function which gets the initial handle to the Physical Drive. Also, I am still calling Disk_LockVolume(), one time, after I call Disk_GetHandle(). However, I have modified the Disk_LockVolume() function so that the handle to the volume (in this case) does not get closed at the end of the function. Ultimately that would be closed at the end of the program, prior to closing the handle on the Physical Drive. Any thoughts on this new error would be greatly appreciated. Oh, the FILE_FLAG_NO_BUFFERING had no impact on performance that I could see.
UINT WriteSector(HANDLE hWriteDisk, PBYTE Buf, ULONG Lba, ULONG Blocks)
{
DWORD bytesWritten;
LPTSTR errMsg = "";
//setup overlapped structure to tell WriteFile function where to write the data
OVERLAPPED overlapped_structure;
memset(&overlapped_structure, 0, (Blocks * SIZE_OF_BLOCK));
overlapped_structure.Offset = (Lba * SIZE_OF_BLOCK);
overlapped_structure.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
//write the data
if (!WriteFile(hWriteDisk, Buf, (Blocks * SIZE_OF_BLOCK), &bytesWritten, &overlapped_structure))
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
printf("WriteSector() - WriteFile failed (%s)\n", errMsg);
}
if (bytesWritten != (Blocks * SIZE_OF_BLOCK))
{
printf("WriteSector() - Bytes written did not equal the number of bytes to be written\n");
return 0;
}
else
{
return Blocks;
}
}
HANDLE Disk_GetHandle(UINT Lun)
{
HANDLE hVol;
LPTSTR errMsg = "";
bool success = false;
//now try to get a handle to the specified volume so we can write to it
hVol = CreateFile(MassStorageDisk[Lun].PhysicalDisk, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED|FILE_FLAG_NO_BUFFERING, 0);
//check to see if we were able to obtain a handle to the volume
if( hVol == INVALID_HANDLE_VALUE )
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
printf("Disk_WriteData() - CreateFile failed (%s)\n", errMsg);
}
return hVol;
}
EDIT #2 (2/10/2015)
So I eliminated the FILE_FLAG_OVERLAPPED from CreateFile() call per Ben's comment. I also modified part of the WriteSector() function to include a check to see if IO is pending after call to WriteFile(). If so, I call WaitForSingleObject() which waits indefinitely until the IO operation is complete. Lastly, I call CloseHandle() on the OVERLAPPED structure hEvent. Even with these changes I still get the error "stack around the variable 'osWrite' was corrupted", where osWrite is the OVERLAPPED structure. Below is a code snippet illustrating the changes.
OVERLAPPED osWrite;
memset(&osWrite, 0, (Blocks * SIZE_OF_BLOCK));
osWrite.Offset = (Lba * SIZE_OF_BLOCK);
osWrite.hEvent = 0;
//write the data
if (!WriteFile(hWriteDisk, Buf, (Blocks * SIZE_OF_BLOCK), &bytesWritten, &osWrite))
{
DWORD Errorcode = GetLastError();
if (Errorcode == ERROR_IO_PENDING)
{
WaitForSingleObject(osWrite.hEvent, INFINITE);
}
else
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errMsg, 255, NULL);
printf("WriteSector() - WriteFile failed (%s)\n", errMsg);
goto exit;
}
}
EDIT #3 (2/10/2015)
So the code is now working with Ben's inputs. The code above has been modified to reflect those changes. I need to mention that up until this afternoon, all of my testing was done where the storage media on the client side was a USB flash drive. I have since changed that so the client now writes to an attached SSD. With the USB flash drive setup, the speed at which I can write data to the client over the USB connection is virtually identical now to the speed at which the client SBC can transfer the same file directly from itself to the storage media (without the host connected). However, with the SSD now being used, this is not the case. The test file I am using which is 34MB takes 2.5 seconds when transferred directly from the client SBC to the SSD. It takes 2.5 MINUTES from host to client over the USB. Other than changing the volume letter and physical drive number, no other changes were made to the code
You should not call CreateFile and CloseHandle for each sector overwritten. CreateFile is a very expensive operation that has to do security checks (evaluate group membership, walk SIDs, etc).
Open the handle once, pass it to WriteFile many times, and close it once. This means changing your _dsk parameter from a volume path to a HANDLE.
You probably also want to lose the call to SetFilePointer, and use an OVERLAPPED structure instead, which lets you supply the position to write to as part of the write call. (The operation won't be overlapped unless you use FILE_FLAG_OVERLAPPED, but non-overlapped I/O respects the position information in the OVERLAPPED structure).

Crash when calling ReadFile after LockFileEx

I have several processes that try to read and write the same file. I want each of them to lock the file so that only one of them accesses it at a time.
I tried this (edit: this is a complete test code this time):
#include "stdafx.h"
#include "Windows.h"
bool test()
{
const char* path = "test.txt";
HANDLE hFile = CreateFileA(path,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("ERROR: Cannot open file %s\n", path);
return false;
}
// Lock the file
{
OVERLAPPED overlapped = {0};
BOOL res = LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, ~0, ~0, &overlapped);
if (!res)
{
printf("ERROR: Cannot lock file %s\n", path);
return false;
}
}
DWORD fileSize = GetFileSize(hFile, NULL);
if (fileSize > 0)
{
char* content = new char[fileSize+1];
// Read the file
BOOL res = ReadFile(hFile, content, fileSize, NULL, NULL);
if (!res)
{
printf("ERROR: Cannot read file %s\n", path);
}
delete[] content;
}
const char* newContent = "bla";
int newContentSize = 3;
// Write the file
BOOL res = WriteFile(hFile, newContent, newContentSize, NULL, NULL);
if (!res)
{
//int err = GetLastError();
printf("ERROR: Cannot write to file\n");
}
// Unlock the file
{
OVERLAPPED overlapped = {0};
UnlockFileEx(hFile, 0, ~0, ~0, &overlapped);
}
CloseHandle(hFile);
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
bool res = test();
return 0;
}
This works fine on my computer, which has Windows 8. But on my colleague's computer, which has Windows 7, it crashes. Specifically, the calls to ReadFile and WriteFile crash, always.
Note that it never enters the code paths with the error printfs. This code triggers no error except for a write at location 0x00000000 in ReadFile (when run on Windows 7).
We tried to also pass the overlapped struct to the ReadFile and WriteFile calls. It prevents the crash but the lock doesn't work anymore, the file is all scrambled (not with this test code, with the real code).
What am I doing wrong?
Looks like your problem is:
lpNumberOfBytesRead [out, optional] argument is null in your call.
This parameter can be NULL only when the lpOverlapped parameter is not NULL.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=vs.85%29.aspx
Heres your problem :
You are missing a necessary struct-member and:
0 and ~0 and {0} are all bad code, constant expressions like these will always produce unepected results -- WINAPI doesnt work like libc, parameters are not always compared against constants, instead they are tested against/via macros and other preprocessor-definitions themselves so passing constant values or initializing WINAPI structs with constants will often lead to errors like these.
After years of experimenting i have found that there is only one surefire way of avoiding them, i will express it in corrected code :
OVERLAPPED overlapped;
overlapped.hEvent = CreateEvent( ........... ); // put valid parameters here!
UnlockFileEx(hFile, 0 /*"reserved"*/, ULONG_MAX, ULONG_MAX, &overlapped);
please read this carefully : http://msdn.microsoft.com/en-us/library/windows/desktop/aa365716%28v=vs.85%29.aspx

WriteFile writing filename to file

I'm getting quite a strange problem.
I'm hooking to the Winsock function on the Xbox 360, send. This function is called a-lot in the application I'm trying to dump the Http Request information from.
First I will show the code and explain my issue:
WritetoFile function.
BOOL WritetoFile(char* filename, char* buffer, DWORD len)
{
// Setup expansion
doMountPath("Hdd:", "\\Device\\Harddisk0\\Partition1");
//print
printf("Creating %s\n", filename);
//create our file
HANDLE fileHandle = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
//does file exist?
if(fileHandle!=INVALID_HANDLE_VALUE)
{
//print
printf("Writing to file... \n");
//bytes written parameter
DWORD wfbr;
//write to our file
if(WriteFile(fileHandle, (void*)&buffer, len, &wfbr, NULL))
{
printf("File written! (Bytes Written:%u) \n", wfbr);
} else {
printf("Error writing to file: (Error:%u)\n", GetLastError());
}
//close our file handle
CloseHandle(fileHandle);
} else {
printf("Error creating file: (Error:%u)\n", GetLastError());
}
return true;
}
Winsock hook
INT WINSOCK_SEND_HOOK(SOCKET s,const char FAR *buf,int len,int flags)
{
memcpy(SocketData.SendData, buf, len);
if(len>40)
{
WINSOCK_SEND_COUNT +=1;
char Filename[40];
sprintf(Filename, "Hdd:\\Dump\\Send\\Winsock_Send_%d.txt", WINSOCK_SEND_COUNT);
WritetoFile(Filename, SocketData.SendData, len);
} else { printf("Winsock skipped\n"); }
memset(SocketData.SendData, 0, 0x1388);
return send(s, buf, len, flags);
}
The problem is pretty difficult to explain. So the first time I ran my .dll to hook onto this function it worked fine up until tries to create 'Winsock_Send_85.txt'. It prints this:
`Creating b0ZEK0EwSDBwSXR2RW5EdXd5ZXFnN1IrLzFQYno4RmN0ZnI2MnNnWWQwb2JXMGlYbEdQRkxGOXFkdHJabiszb1I2MG1vUFlkSjBJVW0xcFB4UzZxWEtqZEVYSjEvQmJtOHhmMUdVMDlZaHA2SUtWZTJjb0ZVU1RsUTlvYXJhc0NDOHJNUitlUDBaQmVSOTNUWVM1TU1hLzB0NlhGZmQ2dE1CVDRKVTRxdzliRUtlRmVvVGgvaVdoMUFBczBpNzhkcXNlVUYwaTlQT3B5ekdyeU9ZTzU0QWYyVXpUSXZiTDMzRWl4SXhzOUJOZDZxaWtDQUlNQmZkNHRYVTNaS2pKZngxRmd3dXE2QnRIYmkySlgxcE9vUjFyVlRpci9iZHdTZTZEOTJDSXFqNkNqM0lSaDY1N3VKUzhOQ3VxaFZpclhTUnZMZlJCN21mTS9aV2dCRUJNWHBVeUdZcGxqOVNGUÿÿexception code=0xc0000005 thread=0xf9000044 address=0x910d0a00 read=0x910d0a00 firstxbWatson: Xbox is restarting`
And crashes. After restarting the console I then run it again and it works fine and doesnt crash but it's now writing the incorrect data to the files which is all the same repetitive data even though the buffer points to different data. This is what it writes to file:
‘ÀÛ( W
ÿÿÿÿÿÿÿÿ ÿÿÿÿ‘Á Hdd:\Dump\Send\Winsock_Send_87.txt  ‚i夀…Ü H>
I then discovered a way to stop this from happening which was to unplug the console entirely from all power but then it goes back to the first issue.
Please ignore what you may think be un-necessary uses of memcpy.
The problem was solved pretty quickly (embarrassing) and I cant believe I was struggling with this for 1 hour, silly mistake.
I wasn't checking the size of the buffer therefore I wasn't allocating enough memory.

C++ WriteFile only writing 4 bytes

Here's what I'm trying to achieve; I'm hooking onto the HttpSendRequest function (on Xbox it's XHttp) and trying dump the certificate that's in pcszHeaders which has the size of 0x1F0E.
Now the problem; it only seems to write 4 bytes, I've even tried allocating extra memory and setting each bit to 0 to see if it's the size of Headers and it continues to only write 4 bytes. I've been able to dump pcszHeaders remotely because I got the address whilst debugging but I need to dump it at run-time.
Something I notice whilst debugging - The address of pcszHeaders only shows in locals until it reaches;
printf("XHttpSendRequest: %s\n", "Creating Certificate.bin...");
Once it reaches the printf() above the address changes to 0x00000000 (bad ptr) but it still writes the first byte of correct data of pcszHeaders correctly but nothing more.
Here is the entire hook;
BOOL XHTTP_SEND_REQUEST_HOOK(
HINTERNET hRequest,
const CHAR *pcszHeaders,
DWORD dwHeadersLength,
const VOID *lpOptional,
DWORD dwOptionalLength,
DWORD dwTotalLength,
DWORD_PTR dwContext)
{
if(pcszHeaders != XHTTP_NO_ADDITIONAL_HEADERS)
{
printf("XHttpSendRequest: %s\n", "Creating Certificate.bin...");
// Setup expansion
doMountPath("Hdd:", "\\Device\\Harddisk0\\Partition1");
//create our file
HANDLE fileHandle = CreateFile("Hdd:\\Certificate.bin", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
//does file exist?
if(GetLastError()!=ERROR_ALREADY_EXISTS
||fileHandle!=INVALID_HANDLE_VALUE)
{
printf("XHttpSendRequest: %s\n", "Writing to file...");
DWORD wfbr;
//write to our file
if(WriteFile(fileHandle, pcszHeaders, 0x2000, &wfbr, NULL))
{
printf("XHttpSendRequest: %s\n", "File written!");
printf("%s\n", "Request has ended.");
CloseHandle(fileHandle);
return XHttpSendRequest(hRequest, pcszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext);
}
}
}
}
EDIT: I've changed the code slightly and I've copied pcszHeaders data into another section of memory that I've created and my pointers seems to have all the correct data and I've tried Writing it to file and it still only writes 4 bytes. I've even used sizeof() instead of hard-coded 0x2000.
pcszHeaders is a char* pointer. sizeof(pcszHeaders) is 4 in a 32bit app (8 in a 64bit app). You need to use the dwHeadersLength parameter instead, which tells you how many characters are in pcszHeaders.
Also, your GetLastError() check after CreateFile() is wrong. If CreateFile() fails for any reason other than ERROR_ALREADY_EXISTS, you are entering the code block and thus writing data to an invalid file handle. When using CREATE_NEW, CreateFile() returns INVALID_HANDLE_VALUE if the file already exists. You don't need to check GetLastError() for that, checking for INVALID_HANDLE_VALUE by itself is enough. If you want to overwrite the existing file, use CREATE_ALWAYS instead.
You are also leaking the file handle if WriteFile() fails.
And you are calling the original HttpSendRequest() only if you successfully write headers to your file. If there are no headers, or the create/write fails, you are not allowing the request to proceed. Is that what you really want?
Try this instead:
BOOL XHTTP_SEND_REQUEST_HOOK(
HINTERNET hRequest,
const CHAR *pcszHeaders,
DWORD dwHeadersLength,
const VOID *lpOptional,
DWORD dwOptionalLength,
DWORD dwTotalLength,
DWORD_PTR dwContext)
{
if (pcszHeaders != XHTTP_NO_ADDITIONAL_HEADERS)
{
printf("XHttpSendRequest: Creating Certificate.bin...\n");
// Setup expansion
doMountPath("Hdd:", "\\Device\\Harddisk0\\Partition1");
//create our file
HANDLE fileHandle = CreateFile("Hdd:\\Certificate.bin", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
//is file open?
if (fileHandle != INVALID_HANDLE_VALUE)
{
printf("XHttpSendRequest: Writing to file...\n");
DWORD wfbr;
//write to our file
if (WriteFile(fileHandle, pcszHeaders, dwHeadersLength, &wfbr, NULL))
printf("XHttpSendRequest: File written!\n");
else
printf("XHttpSendRequest: Error writing to file: %u\n", GetLastError());
CloseHandle(fileHandle);
}
else
printf("XHttpSendRequest: Error creating file: %u\n", GetLastError());
}
printf("Request has ended.\n");
return XHttpSendRequest(hRequest, pcszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext);
}
Finally the problem has been solved!
First I created an empty array for the data to be stored.
CHAR xtoken[0x2000];
memset(xtoken, 0, 0x2000);
The first part of the hook is to store the header data.
DWORD bufferLength = dwHeadersLength;
memcpy(xtoken, pcszHeaders, bufferLength);
I then write the data to file
WriteFile(fileHandle, (void*)&xtoken, bufferLength, &wfbr, NULL))
Success! I guess the problem was that parameter 2 of WriteFile() was incorrect.