DeviceIoControl with input unsigned char buffer C++ - c++

I have a problem with using DeviceIOControl to put 128 byte buffer to my driver, i use this code:
int Initialize(unsigned char* public_signature, int size)
{
int ret = DeviceIoControl(
DeviceFileHandle,
2236440,
public_signature,
size,
NULL,
0,
NULL,
NULL);
if(ret != 0)
return 0;
wprintf(L"Format message failed with 0x%x\n", GetLastError()); // always error 0x6!
return 1;
}
I always get 0x6 error, what i'm doing wrong?
upd
My handle creating function:
int CreateFileHandle()
{
DeviceFileHandle = CreateFile( L"\Device\test",
GENERIC_WRITE,
GENERIC_READ | GENERIC_WRITE,
NULL,
OPEN_EXISTING,
0,
0);
if(DeviceFileHandle)
return 0;
return 1;
}

The error is in the 1st parameter of CreateFile. In your example, it would try to open a file, not a device. In addition, you didn't escape backslashes in the string. \t and similar are interpreted as special characters in C++.
The device name should be "\\\\.\\Device\\test".

Related

write file in raw usb c++

this is my code:
int main(int argc, CHAR* argv[]) {
using namespace std;
PVOID data[1024];
DWORD dwBytesRead = 0;
DWORD dwBytesWrite = 512;
HANDLE hFile = CreateFile(L"\\\\.\\E:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);//open usb
if (hFile == INVALID_HANDLE_VALUE) {
printf("Error %x", GetLastError());
return 1;
}
printf ("created usb hendle\n");
LARGE_INTEGER a = { 50688 };
SetFilePointerEx(hFile, a,NULL,0); //set the pointer to c600
printf("got usb pointer set\n");
PVOID ToBe = ":) hello this is our file -> ";
if (WriteFile(hFile,ToBe,512 ,&dwBytesWrite, NULL) == 0)
{
printf("writeFile error: %x", GetLastError());
CloseHandle(hFile);
return 1;
}
printf("write the first string in isb\n");
HANDLE aFile = CreateFile(L"C:\\Users\\h7080y_dxlq\\Downloads\\Video\\88250.mp4", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); //open the file handle
printf("created mp4 hendle\n");
if (aFile == INVALID_HANDLE_VALUE) {
printf("Error %x", GetLastError());
return 1;
}
if (ReadFile(aFile, &data, 512, &dwBytesRead, NULL) == 0) {
printf("ReadFile error: %x", GetLastError());
return 1;
}
DWORD dwPos;
printf("checked for read errors in mp4 passed o.k.\n");
while (ReadFile(aFile, data,512, &dwBytesRead, NULL) && dwBytesRead > 0) //read file
{
dwPos = SetFilePointerEx(hFile, a, NULL, 0);
LockFile(hFile, dwPos, 0, dwBytesRead, 0);
WriteFile(hFile, data, 512, &dwBytesWrite, NULL); // write 512 bit chunk at the time to usb
UnlockFile(hFile, dwPos, 0, dwBytesRead, 0);
a = { 50688+512 }; // promot
}
printf("write all mp4 to the usb directtly\n");
ToBe = "<- this is the end of file , see you soon :)";
if (WriteFile(hFile, ToBe, 512, &dwBytesWrite, NULL) == 0)
{
printf("writeFile error: %x", GetLastError());
CloseHandle(hFile);
return 1;
}
printf("after end massage \n");
CloseHandle(hFile);
system("pause");
return 0;
}
I try to take a file (mp4 in this case) , and read it chunk by chunk (512 bit at the time) , take the chunk and write it to usb and so on till end of file .
Now, the problem is:
A the loop never ends.
B that it don't write the file to the USB, it looks like its write on the same spot again and again...
How can I fix it?
LARGE_INTEGER a = { 50688 };
while (ReadFile(aFile, data,512, &dwBytesRead, NULL) && dwBytesRead > 0)
{
dwPos = SetFilePointerEx(hFile, a, NULL, 0);
LockFile(hFile, dwPos, 0, dwBytesRead, 0);
WriteFile(hFile, data, 512, &dwBytesWrite, NULL);
UnlockFile(hFile, dwPos, 0, dwBytesRead, 0);
a = { 50688+512 };
}
The first time round the loop you set the file pointer to 50688 and write there. Each subsequent time round the loop you set the file pointer to 50688+512 and write there.
It looks like it writes to the same spot again and again.
Yes indeed. That's exactly what your code specifies. Your should set the file pointer on aFile outside the loop, and let it advance naturally as the file is written. Something like this:
dwPos = 50688;
LARGE_INTEGER a = { dwPos };
if (!SetFilePointerEx(hFile, a, NULL, 0))
{
// handle error
}
while (ReadFile(aFile, data, 512, &dwBytesRead, NULL) && dwBytesRead > 0)
{
LockFile(hFile, dwPos, 0, dwBytesRead, 0);
WriteFile(hFile, data, 512, &dwBytesWrite, NULL);
UnlockFile(hFile, dwPos, 0, dwBytesRead, 0);
dwPos += 512;
}
Note that your calls to LockFile, and the use of a DWORD for dwPos, means that you cannot write a file larger than 4GB.
It is also far from clear to me that the calls to LockFile are needed. Since your original code got the handling of dwPos wrong, it's clear that you weren't locking the parts of the file you intended to. It is my belief that you should simply remove them. In which case the code will become:
LARGE_INTEGER a = { 50688 };
if (!SetFilePointerEx(hFile, a, NULL, 0))
{
// handle error
}
while (ReadFile(aFile, data, 512, &dwBytesRead, NULL) && dwBytesRead > 0)
{
if (!WriteFile(hFile, data, 512, &dwBytesWrite, NULL))
{
// handle error
}
}
You have also omitted large amounts of error checking in this code. I would not be surprised to find that there are a number of other problems with it. I don't particularly want to try to find every single error in your code, and hope that what I have written is enough to help you on your way.

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

Unable to open file using CreateFile function

Ok so I've been following this tutorial: http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=4422&lngWId=3
And so far I've gotten everything to work, up until I need the program to load in a .raw audio file.
Here's the relevant code:
LPSTR loadAudioBlock(const char* filename, DWORD* blockSize)
{
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD size = 0;
DWORD readBytes = 0;
void* block = NULL;
//open the file
if((hFile = CreateFile((LPCWSTR)filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
return NULL;
// get it's size, allocate memory, and then read it into memory
size = GetFileSize(hFile, NULL);
block = HeapAlloc(GetProcessHeap(), 0, size);
ReadFile(hFile, block, size, &readBytes, NULL);
CloseHandle(hFile);
*blockSize = size;
return (LPSTR)block;
}
And then my main function which calls it:
int _tmain(int argc, _TCHAR* argv[])
{
HWAVEOUT hWaveOut; //device handle
WAVEFORMATEX wfx; //struct for format info
MMRESULT result; // for waveOut return values
LPSTR block;
DWORD blockSize;
// first let's set up the wfx format struct
wfx.nSamplesPerSec = 44100; // rate of the sample
wfx.wBitsPerSample = 16; //sample size
wfx.nChannels = 2; // 2 channels = stereo
wfx.cbSize = 0; // no extra info
wfx.wFormatTag = WAVE_FORMAT_PCM; //PCM format
wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
// then let's open the device
if(waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR)
{
fprintf(stderr, "unable to open Wave Mapper device.\n");
Sleep(1000);
ExitProcess(1);
}
// if no errors then close it
printf("The Wave Mapper device was opened successfully!\n");
//load and play file
if((block = loadAudioBlock("ding.raw", &blockSize)) == NULL)
{
fprintf(stderr, "Unable to load file\n");
Sleep(1000);
ExitProcess(1);
}
writeAudioBlock(hWaveOut, block, blockSize);
Sleep(1000);
waveOutClose(hWaveOut);
return 0;
}
Everytime I run the program I get the: "Unable to load file" output. I've got the "ding.raw" file in the same directory as my exe. I've also tried doing the full path as "C://path" and "C:/path" but then the compiler just gives me more errors about being unable to load a pdb file.
Any ideas? I'm using the Visual Studio 2012 Professional IDE and compiler.
Instead of using the standard char you should be using e.g. _TCHAR and LPCTSTR everywhere. This will make all string and string pointers you pass around be correct.
Look at the argv argument to _tmain and you will see that it uses _TCHAR instead of char. This is because Windows support both normal characters and Unicode characters depending on a couple of macros. See e.g. here for some more information.
So to solve what is likely your problem (since you don't get the actual error code, see my comment about GetLastError) you should change the function like this:
void *loadAudioBlock(LPCTSTR filename, DWORD* blockSize)
{
// ...
if((hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
return NULL;
// ...
}
And call it like this:
// ...
void *block;
if((block = loadAudioBlock(_T("C:\\path\\ding.raw"), &blockSize)) == NULL)
{
fprintf(stderr, "unable to open Wave Mapper device, error code %ld.\n", GetLastError());
Sleep(1000);
ExitProcess(1);
}
// ...
As you can see I also changed the return type, as the file is binary and won't have any readable text.
LPSTR loadAudioBlock(const char* filename, DWORD* blockSize)
{
if((hFile = CreateFile(CA2T(filename), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
return NULL;
}
See ATL conversion macros: http://msdn.microsoft.com/en-us/library/87zae4a3%28v=vs.80%29.aspx Just casting const char* LPCWSTR doesn't work.

Async call to ReadFile function returns 6 error code

I wrote the c++ code below in order to read a file asynchronously:
#define BUF_SIZE 1024
HANDLE hFile;
DWORD NumberOfBytesRead = 0;
BYTE *buf = (BYTE*)malloc(BUF_SIZE*sizeof(BYTE));
OVERLAPPED overlapped;
overlapped.Offset = overlapped.OffsetHigh = 0;
hFile = CreateFile("C:\\Users\\Desktop\\FOO.cpp",
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
printf("invalid hfile\n");
int i;
i= ReadFile(hFile,
&buf,
BUF_SIZE,
&NumberOfBytesRead,
&overlapped);
if(!i && GetLastError() != ERROR_IO_PENDING)
printf ("ReadFile failed with error %d.\n", GetLastError());
else
{
WaitForSingleObject(&(overlapped.hEvent), 0);
printf("here it is %d",NumberOfBytesRead );
}
CloseHandle(hFile);
But the return value from ReadFile is 0, and the last error equals to 6.
Does anyone have any idea why? and what does 6 error code say?
Thanks!.
Maybe your problem is with OVERLAPPED structure, which you don't initialize properly.
See: "Any unused members of this structure should always be initialized to zero before the structure is used in a function call. Otherwise, the function may fail and return ERROR_INVALID_PARAMETER." in remarks here: here. You can use memset to clear all of it.
Error code 6 means invalid handle.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
Which seems odd since you check for invalid handle value. Not sure if this helped you but I might try opening the file synchronously first.

C++: Implementing Named Pipes using the Win32 API

I'm trying to implement named pipes in C++, but either my reader isn't reading anything, or my writer isn't writing anything (or both). Here's my reader:
int main()
{
HANDLE pipe = CreateFile(GetPipeName(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
char data[1024];
DWORD numRead = 1;
while (numRead >= 0)
{
ReadFile(pipe, data, 1024, &numRead, NULL);
if (numRead > 0)
cout << data;
}
return 0;
}
LPCWSTR GetPipeName()
{
return L"\\\\.\\pipe\\LogPipe";
}
And here's my writer:
int main()
{
HANDLE pipe = CreateFile(GetPipeName(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
string message = "Hi";
WriteFile(pipe, message.c_str(), message.length() + 1, NULL, NULL);
return 0;
}
LPCWSTR GetPipeName()
{
return L"\\\\.\\pipe\\LogPipe";
}
Does that look right? numRead in the reader is always 0, for some reason, and it reads nothing but 1024 -54's (some weird I character).
Solution:
Reader (Server):
while (true)
{
HANDLE pipe = CreateNamedPipe(GetPipeName(), PIPE_ACCESS_INBOUND | PIPE_ACCESS_OUTBOUND , PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL);
if (pipe == INVALID_HANDLE_VALUE)
{
cout << "Error: " << GetLastError();
}
char data[1024];
DWORD numRead;
ConnectNamedPipe(pipe, NULL);
ReadFile(pipe, data, 1024, &numRead, NULL);
if (numRead > 0)
cout << data << endl;
CloseHandle(pipe);
}
Writer (client):
HANDLE pipe = CreateFile(GetPipeName(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (pipe == INVALID_HANDLE_VALUE)
{
cout << "Error: " << GetLastError();
}
string message = "Hi";
cout << message.length();
DWORD numWritten;
WriteFile(pipe, message.c_str(), message.length(), &numWritten, NULL);
return 0;
The server blocks until it gets a connected client, reads what the client writes, and then sets itself up for a new connection, ad infinitum. Thanks for the help, all!
You must use CreateNamedPipe() to create the server end of a named pipe. Be sure to specify a non-zero buffer size, zero (documented by MSDN as 'use system default buffer size') doesn't work. MSDN has decent samples for a multi-threaded client&server.
A named pipe client can open the named pipe with CreateFile -- but the named pipe server needs to use CreateNamedPipe to create the named pipe. After it's created the named pipe, the server uses ConnectNamedPipe to wait for a client to connect. Only after the client has connected should the server do a blocking read like your call to ReadFile.