Windows WriteFileGather function set last error as ERROR_INVALID_PARAMETER - c++

Example code to reproduce my problem:
#include <windows.h>
#include <iostream>
int main()
{
using namespace std;
HANDLE hdl = CreateFile("test.file", GENERIC_WRITE,
FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_NO_BUFFERING |
FILE_FLAG_OVERLAPPED,
NULL);
char data[4096] = {0};
DWORD written = 0;
for(size_t i = 0; i < sizeof(data); ++i)
data[i] = 'a' + (i % 26);
OVERLAPPED async_hdl = {0};
FILE_SEGMENT_ELEMENT segs[3] = {0};
segs[0].Buffer = PtrToPtr64(data);
segs[1].Buffer = PtrToPtr64(data);
if(!WriteFileGather(hdl, segs, 8192, NULL, &async_hdl)) {
cout << "Last error: " << GetLastError() << endl;
cout << "overlapped internal status: " << async_hdl.Internal << endl;
// Last error: 87
// overlapped internal status: 259
}
CloseHandle(hdl);
return 0;
}
I compile it with Visual Studio 2012 and test on Windows 7. As inlined comment, the WriteFileGather function always sets the last error as ERROR_INVALID_PARAMETER (87) and Internal field of the OVERLAPPED struct is 259.
What did I miss?

MSDN: aSegmentArray ...system memory page and must be aligned on a system memory page size boundary. Use _aligned_malloc() instead of stack memory.

Related

WINAPI Cpp - OpenFileMapping fails with error (2) ERROR_FILE_NOT_FOUND [duplicate]

This question already has an answer here:
OpenFileMapping issues, can't find filemap
(1 answer)
Closed last year.
I'm trying to use WinApi to CreateFileMapping, MapViewOfFile and CopyMemory. It's not showhing me errors and buffor is being filed with my PID
int write_pid_to_memory(const char *t_pid)
{
_tprintf(TEXT("[write_pid_to_memory] t_pid: (%s).\n"), t_pid);
HANDLE h_map_file;
LPCTSTR p_buf;
h_map_file = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
BUF_SIZE, // maximum object size (low-order DWORD)
t_name); // name of mapping object
if (h_map_file == NULL)
{
_tprintf(TEXT("[write_pid_to_memory] Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
p_buf = (LPTSTR)MapViewOfFile(
h_map_file, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (p_buf == NULL)
{
_tprintf(TEXT("[write_pid_to_memory] Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(h_map_file);
return 1;
}
std::cout << "[write_pid_to_memory] strlen(t_pid) * sizeof(char) " << strlen(t_pid) * sizeof(char) << std::endl;
CopyMemory((PVOID)p_buf, t_pid, (strlen(t_pid) * sizeof(char)));
_getch();
std::cout << "p_buf " << p_buf << std::endl;
UnmapViewOfFile(p_buf);
CloseHandle(h_map_file);
return 0;
}
... but then there is reading from memmory
int access_pid_from_memory()
{
HANDLE h_map_file;
LPCTSTR p_buf;
h_map_file = OpenFileMapping(
FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
t_name); // name of mapping object
if (h_map_file == NULL)
{
_tprintf(TEXT("[access_pid_from_memory] Could not open file mapping object (%d).\n"),
GetLastError());
return 1;
}
p_buf = (LPTSTR)MapViewOfFile(
h_map_file, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (p_buf == NULL)
{
_tprintf(TEXT("[access_pid_from_memory] Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(h_map_file);
return 1;
}
MessageBox(NULL, p_buf, TEXT("[access_pid_from_memory] Process2"), MB_OK);
UnmapViewOfFile(p_buf);
CloseHandle(h_map_file);
return 0;
}
where I get System Error (2) while trying to open Mapping.
My PID: 19516
[access_pid_from_memory] Could not open file mapping object (2).
[write_pid_to_memory] t_pid: (19516).
[write_pid_to_memory] strlen(t_pid) * sizeof(char) 5
p_buf 19516
Envariamental variable = NEW
Env var value length = 3
Env var value compare resault = 0
Mutex created sucesfully
Code of those functions is from
https://learn.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory
and only thing I've changed is
CopyMemory((PVOID)p_buf, t_pid, (strlen(t_pid) * sizeof(char)));
Instead of
CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
Where t_pid is just a const char *, becouse I was tired of Windows TCHAR types and I had no clue how to convert DWORD ProcessID to TCHAR to pass it to memcopy.
Well, I'm clueless why I'm unable to open Mapping. Windows is probably beyond me and I have no idea
how
TCHAR t_name[] = TEXT("Global\\MyFileMappingObject");
is supposed to be recognised by system to find memory from which I want to read a message.
Whole programm is supposed to lock execution for only one process and if there is a System variable named "SO2" of value "NEW", new process should stop execution of previous process and continoue locking program for himself.
Locking mechanism is with mutex and to find previous porcess ID, I wanted my current process ID to be saved in memory, for next process to read it form, to close it when sys var will be "NEW".
Nothing crazy. All of this in Linux I've done in one day, but Windows is killing me.
Please help
There is main if someone would be intrested:
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <windows.h>
#include <string>
#include <conio.h>
#include <tchar.h>
#define BUFFER_SIZE 2048
#define ENV_KEY "SO2"
#define ENV_VAL "NEW"
#define BUF_SIZE 256
TCHAR t_name[] = TEXT("Global\\MyFileMappingObject");
HANDLE h_mutex;
int write_pid_to_memory(const char *dw_pid);
int access_pid_from_memory();
int main(int argc, char **argv)
{
DWORD dw_pid = GetCurrentProcessId();
std::stringstream stream;
stream << dw_pid;
const char *t_pid = stream.str().c_str();
// int legnth = s_pid.length()
// const char *t_pid = (char*)malloc( * sizeof(char));
// const char t_pid = (char)malloc(strlen(dw_pid) * sizeof(char));
std::cout << "My PID: " << dw_pid << std::endl;
access_pid_from_memory();
write_pid_to_memory(t_pid);
std::string env_val(ENV_VAL);
char c_buffer[BUFFER_SIZE];
LPCSTR lp_name = ENV_KEY;
LPSTR lp_buffer = c_buffer;
DWORD dw_size = BUFFER_SIZE;
DWORD get_env_var;
//Write to memory your pid for other process to access it and close you
get_env_var = GetEnvironmentVariable(
lp_name,
lp_buffer,
dw_size);
if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
{
std::cout << "Couldn't find envariamental variable \"SO2\"." << std::endl;
}
if (BUFFER_SIZE == get_env_var)
{
std::cout << "Buffer for function [GetEnvironmentVariable] is too small. Function failed." << std::endl;
}
std::cout << "Envariamental variable = " << lp_buffer << std::endl;
std::string str_buffer(lp_buffer);
std::cout << "Env var value length = " << str_buffer.length() << std::endl;
std::cout << "Env var value compare resault = " << str_buffer.compare(env_val) << std::endl;
HANDLE h_mutex = NULL;
LPCSTR str = ENV_KEY;
h_mutex = OpenMutex(
MUTEX_ALL_ACCESS,
TRUE,
str);
if (NULL != h_mutex)
{
if (str_buffer.compare(env_val) == 0)
{
//Realease mutex3
ReleaseMutex(h_mutex);
//Close previous process
}
else
{
throw std::runtime_error("Instance of a program is already running");
}
}
h_mutex = CreateMutex(
NULL,
FALSE,
str);
if (h_mutex == NULL)
{
std::cout << "Failed to create mutex: error - " << GetLastError() << std::endl;
return 1;
}
std::cout << "Mutex created sucesfully" << std::endl;
DWORD dw_wait_res;
dw_wait_res = WaitForSingleObject(
h_mutex, // handle to mutex
INFINITE); // no time-out interval
for (;;)
{
Sleep(100);
}
CloseHandle(h_mutex);
system("PAUSE");
return 0;
}
Your logging clearly shows [access_pid_from_memory] occurs before [write_pid_to_memory].
And we can clearly see in your main() function that it calls access_pid_from_memory() first (which attempts to open the memory map and then closes it), and then afterwards calls write_pid_to_memory() (which creates the memory map and then closes it). Since there is no active handle referring to the mapping, it gets destroyed as soon as write_pid_to_memory() exits.
So, you are doing operations out of order, which is why OpenFileMapping() is failing. At no point does the mapping actually exist when access_pid_from_memory() is trying to open it.
You need to do the following instead:
in one process, create the mapping first, and leave it open.
THEN, in another process, open the mapping while it is still open in the previous process.
THEN, use the mapped memory as needed.
THEN, close the mapping in both processes.
There are other issues with your code, too:
converting the process ID to a string just to share it. You can share the ID as a binary DWORD instead.
access_pid_from_memory() doesn't actually read anything from the mapping (if it were able to open it at all).
main() is assigning t_pid to point at dangling memory. The call to stream.str() produces a temporary std::string that is destroyed as soon as c_str() exits.
I don't even know what you are attempting to do with your environment variable and mutex, and what that has to do with sharing memory. For purposes of this post, you should remove that code until you have your shared memory working properly.

I still have this issue: C++ get Partition Styles

I am new to C / C ++. This is an exercise. And I don't really understand it. The code above is that I copied on internet.
I'm learning C ++, so even though the code is C, I want to switch back to C ++.
I need to understand the code and output the screen:
is MBR disk/drive
is GPT disk/drive
or is RAW disk/drive
I am having trouble retrieving information about the Hard Drive Partition Types in C/C++.
I pressed F5 on Visual Studio 2013, and was notified:
The variable 'partitions_style' is being used without being initialized.
I still have another problem: I use the clean command in DiskPart for My Hard Drive. When I ran the test, I found IOCTL_DISK_GET_DRIVE_LAYOUT_EX did not recognize PartitionStyle RAW correctly, because this time my hard drive was RAW DISK (and certainly not PartitionStyle MBR or PartitionStyle GPT).
Please help me.
Thanks.
#include "windows.h"
#include <stdio.h>
#include <iostream>
using namespace std;
BOOL Get_Partition_Styles(LPWSTR wszPath, PDRIVE_LAYOUT_INFORMATION_EX p_LAYOUT_INFORMATION_EX)
{
DWORD partitionsSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX)+127 * sizeof(PARTITION_INFORMATION_EX);
p_LAYOUT_INFORMATION_EX = (PDRIVE_LAYOUT_INFORMATION_EX)malloc(partitionsSize);
HANDLE hDevice = INVALID_HANDLE_VALUE;
BOOL bResult = FALSE;
DWORD junk = 0;
hDevice = CreateFileW(wszPath,
0,
FILE_SHARE_READ |
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
return (FALSE);
}
bResult = DeviceIoControl(hDevice,
IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
NULL, 0,
p_LAYOUT_INFORMATION_EX, partitionsSize,
&junk,
(LPOVERLAPPED)NULL);
CloseHandle(hDevice);
return (bResult);
}
void enum_Partitions()
{
for (int i = 0;; i++)
{
WCHAR volume[MAX_PATH];
wsprintf(volume, L"\\\\.\\PhysicalDrive%d", i);
HANDLE h = CreateFile(volume, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
bool success = h != INVALID_HANDLE_VALUE;
if (!success)
break;
wcout << endl << endl << endl << L"Disk #" << i << endl;
PDRIVE_LAYOUT_INFORMATION_EX partitions_style; // disk drive geometry structure
BOOL bResult = FALSE; // generic results flag
bResult = Get_Partition_Styles(volume, partitions_style);
if (!bResult)
{
wcout << L"Partition Style: " << partitions_style->PartitionStyle << endl;
}
else
{
wcout << L"Get_Partition_Styles failed. Error: " << GetLastError() << endl;
}
CloseHandle(h);
}
free(partitions_style);
}
int main(int argc, char* argv[])
{
enum_Partitions();
bool success_nh;
cin >> success_nh;
return 0;
}
You pass a PDRIVE_LAYOUT_INFORMATION_EX to Get_Partition_Styles() but in the function you say p_LAYOUT_INFORMATION_EX = (PDRIVE_LAYOUT_INFORMATION_EX)malloc(partitionsSize); so you have just overridden the value you passed in.
Since you are passing by value, the updated version is not visible in the caller and so the one in the caller is never set to a value. (also the one in the called function is probably a memory leak since there is a malloc but no free).
As a side note: C or C++ ?
If you're in C++ you could pass a reference but then why are you using malloc ?
If your're in C then you could pass a pointer to be populated (the old version of passing a reference :-)

MiniDumpWriteDump fails with "MiniDumpWithFullMemory"

I'm trying to get the process dump. But when I use flag MiniDumpWithFullMemory the function crashes.
Maybe I use DuplicateHandle wrong... I don't know.
Is MiniDumpWithFullMemory is necessary flag to obtain general information or I can use only other flags (like in code listing below) ??
I need to get the dump in order to send it to VirusTotal...
Here is the code:
#include <iostream>
#include <windows.h>
using namespace std;
#pragma comment(lib, "dbghelp.lib")
#include <dbghelp.h>
#include <stdio.h>
void WriteFullDump(wchar_t* path_to_dump, HANDLE hProc)
{
const DWORD Flags = MiniDumpWithHandleData|
MiniDumpWithHandleData|
MiniDumpWithDataSegs|
MiniDumpScanMemory |
MiniDumpFilterMemory|
MiniDumpNormal|
MiniDumpWithUnloadedModules|
MiniDumpWithThreadInfo;
HANDLE hFile = CreateFile(path_to_dump, GENERIC_WRITE, 0, nullptr,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
BOOL Result = MiniDumpWriteDump(hProc,
GetProcessId(hProc),
hFile,
(MINIDUMP_TYPE)Flags,
nullptr,
nullptr,
nullptr);
CloseHandle(hFile);
if (!Result)
{
cout << Result << endl;
std::cerr << "Looks like an error: MiniDumpWriteDump failed" << endl;
cout << GetLastError() << endl;
}
CloseHandle(hFile);
return;
}
int main()
{
wchar_t* path = L"C:\\C++\\122332.txt";
int pid;
cin >> pid;
HANDLE proc = OpenProcess(PROCESS_DUP_HANDLE, 1, pid);
HANDLE pseudoproc;
HANDLE my = GetCurrentProcess();
DuplicateHandle(proc, proc, my, &pseudoproc, PROCESS_QUERY_INFORMATION, 1, DUPLICATE_SAME_ACCESS);
WriteFullDump(path,proc);
CloseHandle(proc);
cout << "Finished!" << endl;
char g;
cin >> g;
return 0;
}

Named Pipes Issue

I am trying to learn how named pipes work, and created 2 consoles to test the connectivity between server and client. Client will send a message to the server and the server will display the message, but instead of the message, it returns a value of "nullptr" as shown in the error exception break from VS.
below are my codes, do enlighten me if you found any problem with my code, and I am still learning..
Server.cpp
#include "cust_ostream.hpp"
#include <Windows.h>
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
LPVOID buffer = NULL;
DWORD readbyte;
cout << "---Named Pipe Server Test---" << endl << endl;
cout << "Creating named pipe: \\\\.\\pipe\\mypipe" << endl;
HANDLE hPipe = CreateNamedPipeA("\\\\.\\pipe\\mypipe", PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, NULL);
if (!hPipe || hPipe == INVALID_HANDLE_VALUE)
{
cout << "Pipe creation failed." << endl;
return 0;
}
cout << "Connecting pipe to client..." << endl;
BOOL connect = ConnectNamedPipe(hPipe, NULL);
if (!connect)
{
cout << "Connect named pipe failed" << endl;
}
cout << "Success! Reading pipe message from client..." << endl;
ReadFile(hPipe, buffer, sizeof(buffer), &readbyte, NULL);
c_cout << "Pipe message = " << *(int *)buffer << endl;
_getch();
return 0;
}
cust_ostream.hpp
#include <Windows.h>
#include <iostream>
#include <sstream>
using namespace std;
#define endl "\n"
class cust_ostream
{
public:
~cust_ostream()
{
cout << m_buffer.str();
}
template <typename T>
cust_ostream &operator<<(T const &value)
{
m_buffer << value;
return *this;
}
private:
ostringstream m_buffer;
};
#define c_cout cust_ostream()
and my client
#include <Windows.h>
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
LPVOID data;
DWORD writebyte;
int i = 2;
cout << "---Named Pipe Client---" << endl << endl;
cout << "Creating pipe file: \\\\.\\pipe\\mypipe" << endl;
HANDLE pipe = CreateFileA("\\\\.\\pipe\\mypipe", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (!pipe || pipe == INVALID_HANDLE_VALUE)
{
cout << "Pipe client failed." << endl;
return 0;
}
cout << "Pipe connected to server, sending data..." << endl;
WriteFile(pipe, &i, sizeof(i), &writebyte, NULL);
_getch();
return 0;
}
You need to wait for the NamedPipe to have a ConnectPipeReady event on it. As it stands, you are trying to create the pipe without actually seeing if it was succesfull. See the MSDN documentation for Named Pipes here: https://msdn.microsoft.com/en-ca/library/windows/desktop/aa365592(v=vs.85).aspx
Specifically, this block:
while (1)
{
hPipe = CreateFile(
lpszPipename, // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
// Break if the pipe handle is valid.
if (hPipe != INVALID_HANDLE_VALUE)
break;
// Exit if an error other than ERROR_PIPE_BUSY occurs.
if (GetLastError() != ERROR_PIPE_BUSY)
{
_tprintf( TEXT("Could not open pipe. GLE=%d\n"), GetLastError() );
return -1;
}
// All pipe instances are busy, so wait for 20 seconds.
if ( ! WaitNamedPipe(lpszPipename, 20000))
{
printf("Could not open pipe: 20 second wait timed out.");
return -1;
}
}
Also you shouldn't use #define endl "\n", use std::endl
You have initialized your buffer as NULL which means that by default its length is zero. Now when you use the sizeof operator in your read function in server (to retrieve the message received by server from client), what happens is that you are asking the sizeof operator in Read function to read 0 bytes! which means that nothing will be read.
To solve this, you can declare a char array of size 100 or a size of a message which you are sure that won't be exceeded by client. Like if you are assuming that message by client is not going to be longer than lets say 60 characters, then you can create your char buffer to be of size 100 just to make sure that you do accommodate all the message by client.
And one more thing, if problem still persists, instead of using sizeof in read, use 100 or whatever the size of of your char buffer array. This should solve your problem.

Checking for which of my COM ports are open and usable

I am quite new to COM port programming and am currently at the basics right now, looking for advice. For checking for COM ports, am I correct in using CreateFile() func? and for checking which of my COM ports are open, is the only way to call this function on each of the COM Ports?
Also is there anything I should keep in mind while going forward? Right now I am just at the basics and appreciate any help. Thanks.
EDIT:
This is my code so far but the COM ports 1-10 are failing or I'm doing something wrong.
#include <string>
#include <Windows.h>
#include <conio.h>
#include <iostream>
#include <sstream>
int main(){
std::string com = "\\\\.\\COM";
std::string portname;
HANDLE hCom;
for( int i = 1; i<10; i++)
{
std::stringstream sstm;
std::cout << "Trying "<< i<<"\n";
sstm << com << i;
portname = sstm.str();
TCHAR *szPort = (TCHAR*)(portname.c_str());
hCom = CreateFile(szPort,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
if (hCom == INVALID_HANDLE_VALUE)
{
DWORD err=GetLastError();
std::cout << "Failed\n";
}
else
{
std::cout << i << " Didn't Fail o.o";
CloseHandle(hCom);
}
}
return 0;
}
EDIT 2:
I also tried manually calling the function using
hCom = CreateFile("\\\\.\\COM1",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
switching \\.\COM1 with COMs 1-10 and keep getting the error 2 from GetLastError().