My code opens a virtual NIC device using CreateFile. After that I am calling SetHandleInformation on the handle returned by CreateFile to avoid leaking the handle to child processes. The problem is, SetHandleInformation fails with error code 5 (ERROR_ACCESS_DENIED).
Following is the piece of code where I am opening the device and calling SetHandleInformation:
handle = CreateFile(dev_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,NULL);
if (handle != INVALID_HANDLE_VALUE) {
if (!(SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0))) {
printf("SetHandleInformation error, code: %u\n", GetLastError());
}
}
I am observing this failure on Windows 10. My application is running with Administrator privileges. I am able to successfully use the handle for read and write even after this failure, which indicates that CreateFile is working fine.
What could be the possible reason of this failure? I could not find much information on SetHandleInformation failure with error code 5.
Related
I've got a pair of windows processes that communicate via named pipes. The server calls CreateNamedPipeW and the client calls CreateFileW to open the same named pipe. Some times this works fine, and then can send messages back and forth. Some times this fails with the error ERROR_PIPE_BUSY on both ends.
I'm pretty sure there is exactly one copy of each of the server and client process. I'm also sure that there is exactly one thread on each end that does the pipe management. i.e. I don't think my problem is that there are multiple producers or consumers.
server:
OVERLAPPED openServerOverlapped;
...
SECURITY_ATTRIBUTES sa;
// ...
server = CreateNamedPipeW(
pipeName.c_str(),
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
1,
PIPE_BUFFER_SIZE,
PIPE_BUFFER_SIZE,
NMPWAIT_USE_DEFAULT_WAIT,
&sa
);
if (server != INVALID_HANDLE_VALUE) {
auto lastError = ConnectNamedPipe(server, &openServerOverlapped) == FALSE
? GetLastError()
: ERROR_PIPE_CONNECTED;
if (lastError == ERROR_IO_PENDING) {
DWORD bytesTransferred = 0;
lastError = GetOverlappedResultEx(
server, &openServerOverlapped, &bytesTransferred,
CLIENT_CONNECT_TIMEOUT, FALSE
) == FALSE
? GetLastError()
: ERROR_PIPE_CONNECTED;
}
if (lastError == ERROR_PIPE_CONNECTED) {
// start reading messages
} else {
// error handling, looks like "ConnectNamedPipe error..."
}
} else {
// error handling, looks like "CreateNamedPipeW error..."
}
We sometimes get errors like the following
got error: CreateNamedPipeW error: LastError=000000e7, All pipe instances are busy.
e7 is ERROR_PIPE_BUSY, which matches the erorr message we got from FormatMessage
When this is happening we get similar errors out of our client. Client is actually c#, but uses marshalling to call the same win32 APIs.
client:
while (true) {
// ...
pipeHandle = CreateFileW(fileName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
IntPtr.Zero,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
IntPtr.Zero
);
if (pipeHandle.ToInt32() == INVALID_HANDLE_VALUE) {
// error handling, looks like "Failed to create pipe client..."
Thread.Sleep(5000);
continue;
}
// ...
}
We get logging like:
Failed to create pipe client, win32 error: 231
231 = e7, so same error: ERROR_PIPE_BUSY
According to the documentation:
Named Pipe Client
A named pipe client uses the CreateFile function to open a handle to a named pipe. If the pipe exists but all of its instances are busy, CreateFile returns INVALID_HANDLE_VALUE and the GetLastError function returns ERROR_PIPE_BUSY.
The reason for the error is that all of its instances are busy.
I suggest you try to use the CreateNamedPipe() function to create another instance of a named pipe. And also try to use the DisconnectNamedPipe function to disconnect the server end of a named pipe instance from a client process, and then you can connect that instance to another client by using the ConnectNamedPipe() function.
I suggest you refer to the example: Multithreaded Pipe Server
I am trying to read raw bytes from a pen drive 'E:', but it gives error code 32 when trying to open the drive using CreateFIle(). My code is as follows:
wchar_t wszDrive[7];
wszDrive[0] = '\\';
wszDrive[1] = '\\';
wszDrive[2] = '.';
wszDrive[3] = '\\';
wszDrive[4] = 'e';
wszDrive[5] = ':';
wszDrive[6] = '\0';
hDevice = CreateFile(wszDrive, //drive name to open
GENERIC_READ | GENERIC_WRITE, ////must be opened with exclusive access(No Sharing)
0, // no access to the drive
NULL, // default security attributes
OPEN_EXISTING, // disposition i.e. if file already exist
0, // file attributes
NULL); // do not copy file attributes
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
printf("CreateFile() failed! from read with error %d.\n", GetLastError());// Program prints this line. with error code 32.
return (FALSE);
}
else
cout << "\nCreateFile() successful! in read";
Edit:
The CreateFile() runs fine without errors if I use FILE_SHARE_READ | FILE_SHARE_WRITE:
hDevice = CreateFile(wszDrive,
GENERIC_READ |
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
Why cannot I run with exclusive access?
Error 32 is ERROR_SHARING_VIOLATION.
The process cannot access the file because it is being used by another process.
It means there is already an open handle to the drive, and that handle is using access/sharing rights which are not compatible with the access/sharing rights you are requesting.
That is why you can't open the drive for exclusive access, but you can open it for read/write sharing - the drive is already open elsewhere for reading/writing.
If you want to know where exactly, you can use a tool like SysInternals Process Explorer to see which processes have open handles to which files/folders, devices, etc.
I am trying to bridge my QEMU VM to a local adapter in my Windows 10 host, but QEMU complains that the interface name provided by ifname option to the -netdev argument cannot be opened. I have followed the answer in https://superuser.com/questions/1317652/how-to-set-up-nat-for-qemu-with-tap-backend-windows-10, but with no luck. I have cross-compiled QEMU from source to debug this behavior, for whether or not the interface name can be detected, and apparently QEMU can find the adapter's name, but not the TAP device file. To further explain my point, here's a code snippet from net/tap-win32.c:595 from the QEMU 4.2.0 source code (latest release version as of this writing), specifically tap_win32_open function, and I will highlight where it was failing in this function (look for // THIS IS WHERE IT WILL FAIL. comments):
Testing with a correct existing network interface:
static int tap_win32_open(tap_win32_overlapped_t **phandle,
const char *preferred_name)
{
...
rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer));
if (rc)
return -1;
snprintf (device_path, sizeof(device_path), "%s%s%s",
USERMODEDEVICEDIR,
device_guid,
TAPSUFFIX);
handle = CreateFile (
device_path,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
0 );
if (handle == INVALID_HANDLE_VALUE) {
return -1; // THIS IS WHERE IT WILL FAIL.
}
...
Testing with an incorrect (non-existent) network interface:
static int tap_win32_open(tap_win32_overlapped_t **phandle,
const char *preferred_name)
{
...
rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer));
if (rc)
return -1; // THIS IS WHERE IT WILL FAIL.
snprintf (device_path, sizeof(device_path), "%s%s%s",
USERMODEDEVICEDIR,
device_guid,
TAPSUFFIX);
handle = CreateFile (
device_path,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
0 );
if (handle == INVALID_HANDLE_VALUE) {
return -1;
}
...
QEMU uses the prefix USERMODEDEVICEDIR, which is \\.\Global\ and a suffix .tap to the device's GUID to create the device's path in Windows. For example, the network adapter I am dealing with results in the following device path: \\.\Global\{990DA322-3986-4854-AE93-1D6FB0BFA137}.tap. Any idea why CreateFile always results in INVALID_HANDLE_VALUE on the device path? By the way, GetLastError() returns 2, which from learn.microsoft.com means the following:
...
ERROR_FILE_NOT_FOUND
2 (0x2)
The system cannot find the file specified.
...
I apologize. I was attaching to a non-TAP adapter, thinking it will acquire the address from it, much like VirtualBox. I did not entirely understand the bridging concept before in QEMU, but now I should attach to a TAP adapter, and bridge that adapter to another preferred adapter.
I ran into an interesting problem. A searched many ways but I coundn't found any solution.
The problem is that I'm trying to open a shared printer in a domain with CreateFile function but it returns ERROR_FILE_NOT_FOUND errorcode.
If I use prompt and type
copy file.txt \\computer\printer
than it successfully completes the copy with result
1 file copied.
The CreateFile parameters is the following:
HANDLE file = CreateFile(printer, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == ERROR_INVALID_HANDLE)
{
char buffer[256];
sprintf_s(buffer, sizeof(buffer), "ErrorCode: %i", GetLastError());
MessageBox(NULL, buffer, "Error opening the file", MB_ICONERROR);
}
or
HANDLE file = CreateFile(printer, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == ERROR_INVALID_HANDLE)
{
char buffer[256];
sprintf_s(buffer, sizeof(buffer), "ErrorCode: %i", GetLastError());
MessageBox(NULL, buffer, "Error opening the file", MB_ICONERROR);
}
where printer containing the '\\host\printer' string according to the debugger.
I build it with Visual Studio 2005 SP1.
I tried to add the printer as Local priter as found on many places but it just resulted that the CreateFile just returned immediately.
Edit: On Windows XP it work perfectly. Windows 7 is the issue.
Edit2: The FOPEN function solves the problem so very likely the windows 7 implementation of function will be the issue.
The following code gets an error when trying to execute the last line
boost::shared_ptr<boost::asio::io_service> ioServicePtr(new boost::asio::io_service());
//setup the terminal with stdin and stdout
int inFD = ::dup(STDIN_FILENO);
int outFD = ::dup(STDOUT_FILENO);
HANDLE osfhandle = (HANDLE)_get_osfhandle(inFD);//osfhandle is valid
boost::asio::windows::stream_handle inputStream(*ioServicePtr, osfhandle); //error
the error is:
uncaught exception of type N5boost16exception_detail10clone_implINS0_19error_info_injectorINS_6system12system_errorEEEEE
- assign: The parameter is incorrect
Appreciate your input.
#sehe
I tried
hstdhandle = GetStdHandle(STD_OUTPUT_HANDLE);
and got the same error
So then I tried
HANDLE handle=
CreateFile(
"CONIN$", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, NULL);
boost::asio::windows::stream_handle inputStream(*ioServicePtr, handle);
and the error was
-assign handle invalid
You might use GetStdHandle, so:
HANDLE isfhandle = GetStdHandle(STD_INPUT_HANDLE);
However, I don't think consoles support asynchronous IO in windows:
The handle must be to an object that supports overlapped I/O.
If a handle is provided, it has to have been opened for overlapped I/O completion. For example, you must
specify the FILE_FLAG_OVERLAPPED flag when using the CreateFile function to obtain the handle
But further the docs for CreateFile say that CreateFile ignores file flags when creating a handle to a console buffer.
So, you will need to emulate stdin/stdout async IO.
Note that on Linux, asynchronous IO to the standard IO handles is only possible in certain situations anyway - depending on the input/output being redirected: Strange exception throw - assign: Operation not permitted