Crashing When Creating a Process - c++

I am trying to use msdn function (CreateProcess) in C++ in order to run an application. I don't get any errors but when I run it, it crashes. What I did also notice it that it created a process, but it didn't run the text file it was supposed to.
My code:
#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
void createPro ();
int main()
{
createPro();
}
void createPro () {
LPCTSTR lpApplicationName = "C:/Users/Andyy/Desktop/hello.txt";
LPSTARTUPINFO lpStartupInfo;
LPPROCESS_INFORMATION lpProcessInfo;
memset(&lpStartupInfo, 0, sizeof(lpStartupInfo));
memset(&lpProcessInfo, 0, sizeof(lpProcessInfo));
if (!CreateProcess(lpApplicationName,
NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
lpStartupInfo,
lpProcessInfo
)
) {
cout << "Failed to create process" << lpApplicationName << endl;
}
cout << "Program exec: " << lpApplicationName << endl;
}
It creates the process but it fails to run the text file and no errors showed in compilers. Thanks in advance.
Return error: Process returned -1073741819 (0xC0000005)

CreateProcess is used to create process objects from executable files. You are passing a text file which is not an executable file. Presumably you are actually trying to show the text file in the default text editor. Use ShellExecuteEx to do that.
Beyond that, you don't allocate the two structs that are needed in your call to CreateProcess. Instead you declare pointers to structs, and leave the pointer uninitialized. I expect that this is the cause of the access violation error 0xC0000005. For future reference, you would allocate and initialise these structs like so:
STARTUPINFO StartupInfo = { sizeof StartupInfo };
PROCESS_INFORMATION ProcessInfo = { 0 };
Then pass &StartupInfo and &ProcessInfo to CreateProcess. Of course, I'm just adding this advice for completeness. You'll be throwing away all the code relating to CreateProcess and calling ShellExecuteEx instead.

Related

How to run an exe with multiple arguments with CreateProcessW in C++

I have tried to use this example to run an external program using CreateProcessW() in C++, however, when I use multiple arguments this code seems to not work.
In my case, I pass the following path:
std::string pathToExe = "C:\\Users\\Aitor - ST\\Documents\\QtProjects\\ErgoEvalPlatform\\ErgonomicEvaluationPlatform\\FACTS\\xsim-runner.exe"
and the following arguments:
std::string arguments = "--model=facts_input.xml --output_xml=something.xml"
These parameters work from cmd, but they seem to not give any output (an xml should appear in the same folder) when I use them from C++.
Is there something I might be missing?
The following is an example for showing "How to run an exe with multiple arguments with CreateProcessW in C++". You can check if it helps.
The launcher application (a console app):
#include <iostream>
#include <windows.h>
int main()
{
STARTUPINFO si;
PROCESS_INFORMATION pi; // The function returns this
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
CONST wchar_t* commandLine = TEXT("arg1 arg2 arg3");
// Start the child process.
if (!CreateProcessW(
L"D:\\Win32-Cases\\TestTargetApp\\Debug\\TestTargetApp.exe", // app path
(LPWSTR)commandLine, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
throw std::exception("Could not create child process");
}
else
{
std::cout << "[ ] Successfully launched child process" << std::endl;
}
}
The target application (another console app) that will be launched:
#include <iostream>
#include <windows.h>
int main(int argc, char *argv[])
{
if (argc > 0)
{
for (int index = 0; index < argc; index++)
{
std::cout << argv[index] << std::endl;
}
}
return 1;
}
There's two potential problems I can infer from the code you're showing.
Space before the arguments
Depending on how you're concatenating the arguments string to the executable string, you may miss a space before the arguments. Without the code, it's impossible to tell, but try changing the arguments string like this :
std::string arguments = " --model=facts_input.xml --output_xml=something.xml;"
Current directory
CreateProcess spawns a child process that inherits the current directory from it's parent process. The XML files you specify on the arguments use relative paths.
Try specifying the full path of the XML files you're passing in the arguments, something like this :
std::string arguments = " --model=\"C:\\Users\\Aitor - ST\\Documents\\QtProjects\\ErgoEvalPlatform\\ErgonomicEvaluationPlatform\\FACTS\\facts_input.xml\" --output_xml=\"C:\\Users\\Aitor - ST\\Documents\\QtProjects\\ErgoEvalPlatform\\ErgonomicEvaluationPlatform\\FACTS\\something.xml\"";
You have to pass the complete command line in the arguments as under:
std::string arguments = "C:\\Users\\Aitor-ST\\Documents\\QtProjects\\ErgoEvalPlatform\\ErgonomicEvaluationPlatform\\FACTS\\xsim-runner.exe --model=facts_input.xml --output_xml=something.xml"
The second parameter of CreateProcessW requires complete command line and not just arguments. It passes this to the process and if the target process is a C program taking agrs, then as usual the first parameter will be module name and others that follow will be args.
Hope this helps

Calling a function from another process

I apologize in advance for my English :D
How can I call a function from a process, knowing the pointer to it?
I tried this:
Process.cpp:
DWORD pid;
HWND hwnd;
HANDLE phandle;
void Attach() {
hwnd = FindWindow(NULL, L"GTA:SA:MP");
if (!hwnd) {
cout << "Process is not found" << endl;
system("pause");
}
else if (hwnd) {
cout << "Process was successfully loaded" << endl;
GetWindowThreadProcessId(hwnd, &pid);
phandle = OpenProcess(PROCESS_VM_READ, 0, pid);
}
else
{
cout << "Error 0x01" << endl;
system("pause");
}
}
void GameText(const char* szText, int iTime, signed int iStyle)
{
typedef void(__stdcall* GameText_t)(const char*, int, signed int);
GameText_t pGameText = (GameText_t)((char*)phandle + 0x69F2B0);
return pGameText(szText, iTime, iStyle);
}
main.cpp:
int main()
{
std::cout << "Hello World!\n";
Attach();
GameText("~r~Test!", 1000, 5);
}
And I get the following exception:
An exception was thrown at the address 0x006EF7B6 in wh_mta.exe:
0xC0000005: access violation during execution at 0x006EF7B6.
Why is this happening? How can I call a function by its pointer through HANDLE?
P.S
Reading an integer through HANDLE works great.
int Read_Int(int address) {
int value;
ReadProcessMemory(phandle, (void*)address, &value, sizeof(value), 0);
return value;
}
Maybe 30 years ago that would have worked :D :D :D
Processes can't access each other's memory… Every process has their own image of the memory, so address 0xWHATEVER in a process does not contain the same data as 0xWHATEVER in another process!
You need to make a library or use some inter process communication (IPC).
What you are doing is adding the pointer to the HANDLE of the process. You need the address of the process in it's virtual address space. To do so, use EnumProcessModules andGetModuleFileNameEx to find the filename of the module with the function you want. (Could be an EXE or a DLL.) EnumProcessModules returns an array of HMODULES which are just addresses of module in the specified process's virtual address space. So loop through the array, then cast the HMODULE that you need to a PBYTE. Then, add the function pointer to it, then try to execute.
Also, according your code, you are going to execute the function in YOUR program. That's fine, just make sure that if it needs to run in the target program, you'll need to use CreateRemoteThread to run it there.

How do I simulate user input to a console application from Unit Test project?

I am trying to write a text processing console application in C++ and I have met Windows API for the first time. But before defining a grammar or using the existing bison/flex or boost tools I want to realize a TDD approach and write all tests and interfaces (except here I have put a dummy test having hard time with even launching the .exe from test code).
My design is following:
- Unit tests from native test project call a CreateProcess() function from Windows API that I have put into CreateProc() macro. Example of this macro (I have slightly modified it) is taken from MSDN. Idea of this macro is execute my console application but from unit test to simulate user input after. Here is the code:
#define MYEXE L"my_Console_Application_Path.exe"
#ifdef MYEXE
PROCESS_INFORMATION CreateProc() {
STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi = { 0 };
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if (CreateProcess
(
MYEXE,
NULL,
NULL,
NULL,
NULL, //,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi
)
)
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return pi;
}
else
{
std::cout << "Unable to execute.";
return pi;
}
}
#endif
Test that runs and "uses" my console application is defined:
TEST_CLASS(UnitTest1)
{
public:
TEST_METHOD(Should_Open_Console)
{
PROCESS_INFORMATION processInfo = CreateProc();
Assert::IsTrue(processInfo.dwProcessId); // check if process id is not zero
}
main function of console application looks like this:
int main()
{
std::cout << "test that function is running" << std::endl;
std::string myline = "";
std::getline(std::cin, myline);
return 0;
}
Basically my CreateProc() sucessfully launches the executable. However I want tests to simulate user input that main is listening to with getline(...). After I am going to parse this sequence with some parser.
How could I simulate this input within current console process? Of course I will be grateful if you can advise me some concrete instruments (is this SendInput() solution the best way to simulate input?) and the most important - how it should be done in terms of design? Ideally I see a string defined in a Unit test and passed through CreateProcess() as argument to main and the same string is somehow read from console after. Kind of this:
TEST_CLASS(UnitTest1)
{
public:
// parsing Hola as Hello
TEST_METHOD(Should_Return_Hello_If_Input_Equals_to_Hola)
{
CreateProc("Hola");
Assert::AreEqual(Console.readline() = "Hello"); // dummy code
}
Am I right? If yes, how could I actually do it? (if you can correct code snippets it would be great)

FindResource() fails to find data even though data is in exe

I have been all over this one, and I am just plumb stuck. I have been building a project and I want to embed a text file as a resource into the executable. I understand all the basics of how this "should" work, but for some reason it is not. So, let me start from what I have so far and maybe the problem can be pinned down.
There are two functions here, the first, EnumResNameProc was an attempt to debug the problem my self, the second, LoadFileInResource is the function I am trying to get working.
It is a little messy because I was in the middle of building it when I starting having problems.
The exact issue is, FindResourceExA is returning NULL, and I am lost as to the exact reason. I know it is an error, and the return code is 1813, "Resource Not Found".
I have other resources in this project, I have a version node, a mainifest node, (of which, I am not directly reading) I have an icon node (that I am applying to my window system menu icon) and a bitmap (that I am loading as a texture.). These all have defined types, for example, the type for the Bitmap is 12. Now, I am attempting to load a text file, with is a 'user defined' type of 10. I know the data is INSIDE the executable, because if I open it in a text editor... (yes, I tried that) it is present, so, it is being included.
the first function was an attempt to walk through all the file resources in an attempt to locate the data. It found types 2, 3, 14, 16 and 24., but not 10. I have ruled out these other types as being the above mentioned resources. (bitmap=2), (icon=3), (RT_ICON(3)+RT_ICON_GROUP(11)=14) (version=16), (manifest=24). User defined should be type 10, and it didn't find it.
My Resources.rc file includes the following:
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDR_textfile1 textfile ".\\Data\\World.txt"
This defines the file to be loaded, (again, I know this works, I can see the text of the code IN the executable.)
My resources.h file defines the following:
#define IDR_textfile1 102
So, it is being defined, included, built, and all the other resources work, and yet, FindResourceExA returns NULL on this. All the include files are lined up, (i'd get warnings and errors if it was not.)
So, the question is, am I calling FindResourceExA correctly? it is defined as:
WINBASEAPI HRSRC WINAPI FindResourceExA(HINSTANCE,LPCSTR,LPCSTR,WORD);
well, I have tried for HINSTANCE, null, hInstance passed to be my Windows in WinMain, even GetModuleHandleA's results, no dice.
For LPCSTR, which is the resource ID, I have tried what you see, MAKEINTRESOURCE(IDR_textfile1), and I have tried hard coding the ID number as well, in this case, 102. No dice.
For the type, I have tired other variations, the correct value according to Microsoft should be 10. That's why I crated the EnumResNameProc, trying to see what other IDs exist, from 0 to 500, and all I got back was the ones listed above, on the off chance something was defined funny. No Dice.
I have tried both FindResourceExA FindResourceA (with and without the 'Ex')
No Dice.
I know it is there, I have learned more then I care to about this function, but it won't find it, and I am at a loss at what else to try.
As for development environment, I am using MinGW+Eclipse+CDT, and using winres from the GCC tools to build the resource object file. I have looked for bugs in winres to see if it is doing something funny on binary types. (that's what undefined are considered, even though I am loading a text file.) oh, I also tried re-saving the file as ANSI, UTF-8, and UNICODE in case the binary format of the text mattered.
I am at a loss, I don't know what else to try. I know the data is there, I just don't why it won't access it. The Windows API call can't either see the data, or the data is encoded in a screwey way and so it doesn't access it.
What else can I try?
BOOL CALLBACK EnumResNameProc (
HMODULE hModule,
LPCTSTR lpszType,
LPTSTR lpszName,
LONG_PTR lParam)
{
std::cerr << "WTF INFO BEGIN here! \n";
// std::string info = lpszName;
int a = lParam;
std::cerr << "We found something: " << a << std::endl;
MessageBoxA ( NULL, lpszName, (LPCSTR) "Found: ", MB_OK);
std::cerr << "WTF INFO END here! \n";
return true;
}
void LoadFileInResource( HINSTANCE hInstance,
int name,
int type,
DWORD size,
const char* data)
{
// HMODULE handle = GetModuleHandleA(NULL);
for (int a = 0;a<500;a++) {
EnumResourceNamesA(hInstance, MAKEINTRESOURCE(a),
(ENUMRESNAMEPROCA) & EnumResNameProc, (LONG_PTR) a);
}
HRSRC rc = FindResourceExA(hInstance,
MAKEINTRESOURCE(IDR_textfile1),
MAKEINTRESOURCE(10),
MAKELANGID(LANG_NEUTRAL,
SUBLANG_NEUTRAL));
if (rc == NULL) {
DWORD fup = GetLastError();
MessageBoxA ( NULL, (LPCSTR) "Crap not loaded.", (LPCSTR) "Error", MB_OK);
std::cerr << "Crap not loaded, ERR: " << fup << std::endl;
}
// MessageBoxA ( NULL, (LPCSTR) " Test ", (LPCSTR) "Found: ", MB_OK);
HGLOBAL rcData = LoadResource(hInstance, rc);
// data = static_cast<const char*>(LockResource(rcData));
data = (const char*) LockResource(rcData);
size = SizeofResource(hInstance, rc);
std::cout << "Res size = " << (long) size << std::endl;
std::cout << "data =" << data << :: std::endl;
// wsprintf(szMsg,"Values loaded : %d, %d, %d\nSize = %d",
// pmem->Value1,pmem->Value2,pmem->Value3);
// MessageBox(hWnd, szMsg,lpszAppName,MB_OK);
}
IDR_textfile1 textfile ".\\Data\\World.txt"
You declared the resource type as "textfile". Which is fine but that's a string, not a number. So using MAKEINTRESOURCE() for the resource type isn't going to help you find it, that's why EnumResourceNames doesn't find it back. Fix:
IDR_textfile1 RC_DATA ".\\Data\\World.txt"
And
HRSRC rc = FindResourceEx(hInstance,
MAKEINTRESOURCE(RC_DATA),
MAKEINTRESOURCE(IDR_textfile1),
MAKELANGID(LANG_NEUTRAL,
SUBLANG_NEUTRAL));
or if you want to use your original approach:
HRSRC rc = FindResourceEx(hInstance,
L"textfile",
MAKEINTRESOURCE(IDR_textfile1),
MAKELANGID(LANG_NEUTRAL,
SUBLANG_NEUTRAL));
The call to FindResourceExA is wrong, resource type is passed in the second parameter and id in the third.
FindResourceEx at MSDN

Createprocess and 0xc0000142 error

i have the following test code:
#define CMDLINE ".\\dummyFolder\\dummyProc.exe op1 op2 op3"
int main(int argc, char **argv) {
STARTUPINFO info;
info.cb = sizeof(STARTUPINFO);
info.lpReserved = NULL;
info.cbReserved2 = 0;
info.lpReserved2 = NULL;
PROCESS_INFORMATION processInfo;
SECURITY_ATTRIBUTES procAttr;
procAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
procAttr.lpSecurityDescriptor = NULL;
procAttr.bInheritHandle = false;
SECURITY_ATTRIBUTES threadAttr;
procAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
procAttr.lpSecurityDescriptor = NULL;
procAttr.bInheritHandle = false;
bool handlersInheritable = true;
char cmdLine2[sizeof(CMDLINE)];
strcpy(cmdLine2, CMDLINE);
char AppName[sizeof(".\\dummyFolder\\dummyProc.exe")];
strcpy(AppName, ".\\dummyFolder\\dummyProc.exe");
if (CreateProcess(AppName, cmdLine2, &procAttr, &threadAttr,
handlersInheritable, 0, NULL, NULL, &info, &processInfo)) {
//::WaitForMultipleObjects(procQty, handlers, waitForAll, waitInterval);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
CloseHandle(info.hStdError);
CloseHandle(info.hStdInput);
CloseHandle(info.hStdOutput);
} else {
std::cout << "Returned: " << GetLastError() << std::endl;
}
std::cout << "Exiting main process" << std::endl;
return 0;
}
This is just a test code for creating processes in windows. The problem is that when i launch "dummyProc.exe" i get a 0xc0000142 error.
The process dummyProc.exe runs fine from the command line, but not from within the code.
Here's the dummyProc code if it helps:
int main(int argc, char **argv) {
std::cout << "Working!!!!" << std::endl << "Receivedi: " << std::endl;
for (int i = 0; i < argc; ++i)
std::cout << argv[i] << std::endl;
return 0;
}
So, any ideas?
The most obvious thing that char cmdLine2[sizeof(CMDLINE)]; declares a string of length equal to your machine's pointer size. You need to use strlen(CMDLINE)+1 instead. Likewise for appName.
Note that the first parameter to CreateProcess does not need to be writeable. Just pass the string literal directly to it. No need for appName variable.
As for lpCommandLine which does need to be writeable it's easiest to do it like this:
char cmdline[] = "op1 op2 op3";
That gives you a writeable buffer. Note that you do not need to repeat the executable file name.
Another problem is that you have not initialized all the parameters to CreateProcess. For example the STARTUPINFO struct has 19 fields and you initialize only 3. You should initialize all your structs to 0 and then fill out any fields you need to be non-zero. Like this:
STARTUPINFO info = { 0 };
Do this for all the structs you pass.
You can, and should, pass NULL for the lpProcessAttributes and lpThreadAttributes parameters.
This answer is to relate another cause for 0xc0000142 - placed here (even though another answer was accepted for this question) because there is very little useful information on the intertubes about this error - and a shocking lack of any useful information on the subject from Microsoft - and so someone's internet search may get them here. (Well, mine did.)
So: You can get The application was unable to start correctly (0xc0000142) on starting a process written in C++ where you access though a null pointer in a constructor of a static object. (In my case it was in an initializer of a constructor of a static object.)
Your hint to this will be an event in the application log (event id 1000 source "Application Error") which has lines similar to the following:
Faulting module name: unknown, version: 0.0.0.0, time stamp: 0x00000000
Exception code: 0xc0000005
Fault offset: 0x0000000000000000
0xc0000005 is access violation, of course, and the offset of 0 (actually anything less than 0x10000 is a reference through a null pointer.
Anyway, the surprising thing (to me) is that evaluating statics happens before the debugger can attach (!!) so launching it with ImageFileExecutionOptions set or even directly within Visual Studio doesn't let you debug this thing!!
(And then of course you won't find 0xc0000142 in any Microsoft documentation whatsoever. Well done, NT team!)