How can I use LPSTARTUPINFO and LPPROCESSINFO properly in CreateProcessA? - c++

I tried to use the tutorials around about using the CreateProcessA wherein it uses the STARTUPINFOA and LPPROCESS_INFORMATION.
However, when I tried to use the LPSTARTUPINFOA and LPPROCESS_INFORMATION and sadly it didn't work.
//Working
STARTUPINFOA startUpInfo = {0};
PROCESS_INFORMATION processInformation = {0};
startUpInfo.cb = sizeof(STARTUPINFOA);
CreateProcessA(NULL, "c:\\windows\\system32\\calc.exe", NULL, NULL, FALSE, 0, NULL, NULL, &startUpInfo, &processInformation);
//Fails
LPSTARTUPINFOA startUpInfo;
LPPROCESS_INFORMATION processInformation;
startUpInfo = (LPSTARTUPINFOA)malloc(sizeof(startUpInfo));
processInformation = (LPPROCESS_INFORMATION)malloc(sizeof(processInformation));
ZeroMemory(startUpInfo, sizeof(STARTUPINFOA));
ZeroMemory(processInformation, sizeof(PROCESS_INFORMATION));
startUpInfo->cb = sizeof(STARTUPINFOA);
CreateProcessA(NULL,"c:\\windows\\system32\\calc.exe", NULL, NULL, FALSE, 0, NULL, NULL, startUpInfo, processInformation);
I expect that both would work successfully, however, I wonder why LPSTARTUPINFOA and LPPROCESS_INFORMATION fails. Is there anyone who can enlighten me about my error in this program below.

Related

Why does the manifest file have no effect

I tried to open photoshop.exe using C++, but photoshop.exe.manifest did not take effect. If you manually double-click to open photoshop.exe file that shows normal working.
The registry has set and reboot system:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide]
"PreferExternalManifest"=dword:00000001
Maybe it's the path?
TCHAR szCommandLineName[200]= _T("Photoshop.exe");
TCHAR szCommandLinePath[200] = _T("F:\\Program Files\\Adobe Photoshop 2020\\");
TCHAR szCommandLine[200] = _T("F:\\Program Files\\Adobe Photoshop 2020\\Photoshop.exe");
TCHAR buf[1000];
GetCurrentDirectory(1000, buf);
TRACE(_T("Current Directory:%s\n"), buf);
SetCurrentDirectory(szCommandLinePath);
//::WinExec("F:\\Program Files\\Adobe Photoshop 2020\\Photoshop.exe", SW_SHOW);
//ShellExecuteW(NULL, _T("open"), _T("photoshop.exe.bat"), NULL, szCommandLinePath, SW_SHOWNORMAL);
//return;
// system("photoshop.exe");
// return;
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESHOWWINDOW;
//si.wShowWindow = SW_HIDE;
si.wShowWindow = TRUE;
BOOL bRet = ::CreateProcess(
szCommandLine,
NULL,
NULL,
NULL,
FALSE, //bInheritHandles
NULL, //dwCreationFlags
NULL, //lpEnvironment
NULL,//lpCurrentDirectory
&si,
&pi);
int nError = GetLastError();
::CloseHandle(pi.hThread);
::CloseHandle(pi.hProcess);
return ;

Parent process hangs when calling CreateProcess() in MFC

My code is,
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
info.dwFlags = STARTF_USESHOWWINDOW;
info.wShowWindow = TRUE;
if (CreateProcess("My_program.exe", command, NULL, NULL, TRUE,
CREATE_NEW_CONSOLE, NULL, NULL, &info, &processInfo))
{
WaitForSingleObject(processInfo.hProcess, INFINITE);
GetExitCodeProcess(processInfo.hProcess, &exit_code);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
When i call this function CreateProcess(), My_program.exe invokes and runs.
But my MFC Diolog box gets hang and it shows not responding. Can anyone please help me to avoid this.

Redirecting CreateProcess input stream to a file

I'm using CreateProcess to substitute a system() call in my code. I was using:
system(xfoil.exe < create_results.txt");
Which I am substituing by this:
PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter
STARTUPINFO StartupInfo; //This is an [in] parameter
LPCWSTR input_file = _tcsdup(TEXT(".\\create_results.txt"));
HANDLE inpfl = CreateFile(input_file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
StartupInfo.hStdInput = inpfl;
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof StartupInfo; //Only compulsory field
LPCWSTR exe_path =_tcsdup(TEXT(".\\xfoil.exe"));
if (CreateProcess(exe_path, NULL,
NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL,
NULL, &StartupInfo, &ProcessInfo))
{
WaitForSingleObject(&ProcessInfo.hProcess, 2000);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
CloseHandle(inpfl);
}
else
{
CloseHandle(inpfl);
std::cout << "Could not create xfoil process" << std::endl;
}
The reason being I need to control how long the process is allowed to run ( 2000ms in this case), however it seems that this method does not work.
I'm redirecting the input of the process to the handle of the file I want as input (to substitute the < operator), but the process is not receiving anything. It does launch the xfoil.exe in a separate console, though.
You need to set file security attributes to allow handle to be inherited and startup info flag to make child process use the handle passed:
::STARTUPINFO startup_information{};
::SECURITY_ATTRIBUTES security_attributes
{
sizeof(::SECURITY_ATTRIBUTES)
, nullptr
, TRUE // allow handle to be inherited
};
::HANDLE const inpfl{::CreateFileW(input_file, GENERIC_READ, FILE_SHARE_READ, ::std::addressof(security_attributes), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)};
if(INVALID_HANDLE_VALUE == inpfl)
{
auto const last_error{::GetLastError()};
// handle error...
}
startup_information.cb = sizeof(startup_information);
startup_information.dwFlags = STARTF_USESTDHANDLES;
startup_information.hStdInput = inpfl;
PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter
STARTUPINFO StartupInfo; //This is an [in] parameter
LPCWSTR input_file = _tcsdup(TEXT(".\\create_results.txt"));
HANDLE inpfl = CreateFile(input_file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
StartupInfo.hStdInput = inpfl;
What happens to StartupInfo.hStdInput after the next call?
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
Oops... hStdInput zeroed now
Doing this initially...
PROCESS_INFORMATION ProcessInfo = {};
STARTUPINFO StartupInfo = {};
... will prevent you from needing to zero anything... see
Also, according to CreateProcess StartupInfo documentation, you have to, for hStdInput, set dwFlags to STARTF_USESTDHANDLES, else the default input is the keyboard buffer

MFC Command Window Command

In MFC I want to Create a process by opening Command Window and executing a command in that say open notepad.
i Found this tried it didn't work
STARTUPINFO sInfo = {0};
sInfo.cb = sizeof(sInfo);
PROCESS_INFORMATION pInfo = {0};
CreateProcess("C:\\WINDOWS\\System32\\cmd.exe",""0,0,TRUE,
NORMAL_PRIORITY_CLASS,0,0,&sInfo,&pInfo);
You're not telling cmd to do anything. Try this:
CreateProcess(0, "C:\\WINDOWS\\System32\\cmd.exe /c notepad.exe", 0, 0, TRUE, 0, 0, 0, &sInfo, &pInfo);
But maybe this is easier
ShellExecute(0, "open", "cmd.exe", "/C notepad.exe", 0, SW_HIDE);
Or even this:
system("notepad.exe");
Go to the MSDN document we can see, you don't specify the second parameter that is the command line to excute.
On the other hand, there are no NORMAL_PRIORITY_CLASS enum item for the sixth parameter. You should do like this:
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = TRUE;
TCHAR cmdline[] =TEXT(" notepad.exe");
BOOL bRet = ::CreateProcess (
TEXT("C:\\WINDOWS\\System32\\cmd.exe"),
cmdline,
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi);

Understanding a self-deleting program in C++

There is a self deleting program
#include <windows.h>
#include <stdio.h>
void main(int argc, char* argv[])
{
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
si.cb = sizeof(si);
if (argc == 1)
{
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
CopyFile(argv[0], "1.exe", FALSE);
MoveFile(argv[0], "2.exe");
CreateFile("1.exe", 0, FILE_SHARE_READ, &sa,
OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
CreateProcess(NULL, "1.exe x", NULL, NULL,
TRUE, 0, NULL, NULL, &si, &pi);
}
else if (argc == 2)
{
while(!DeleteFile("2.exe"));
CreateProcess(NULL, "net", NULL, NULL, TRUE,
DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &si, &pi);
}
}
If I remove this :CreateProcess(NULL, "net", NULL, NULL, TRUE, DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &si, &pi);
it can't work.
Could anyone explain to me how it works?
Here's an explanation (as I understand things)
void main(int argc, char* argv[])
{
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
si.cb = sizeof(si);
if (argc == 1)
{
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
// Make a copy of ourselves which we'll use to delete the version we were run from
CopyFile(argv[0], "1.exe", FALSE);
// Rename the running copy of ourself to another name
MoveFile(argv[0], "2.exe");
// Make sure we delete the copy of ourselves that's going to delete us when we die
CreateFile("1.exe", 0, FILE_SHARE_READ, &sa, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
// Invoke the process that will delete us
// allowing it to inherit the handle we just created above.
CreateProcess(NULL, "1.exe x", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
}
else if (argc == 2)
{
// Wait for the original program to die (deleting us and closing a handle), then delete it
while(!DeleteFile("2.exe"));
// Launch a child process which will inherit our file handles
// -- This keeps the file handle with FILE_FLAG_DELETE_ON_CLOSE (which we inherited) alive beyond our lifetime
// this allowing us to be deleted after we've died and our own handle is closed.
CreateProcess(NULL, "notepad", NULL, NULL, TRUE, DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &si, &pi);
}
}