Windows App using PeekNamedPipe() used to work in XP but does not in Win7 - windows-7

I used to have an application which launched an application using CreateProcess() and then piped data back and forth. The child process used printf() and getch().
The code had:
PeekNamedPipe(pCmdIF->m_asynch_hReadPipeOut,NULL,NULL,NULL, &dwBytesInOutPipe, &dwBytesLeftInOutPipe))
Which checked how much data was in the incoming pipe and then I used ReadFile to read that data.
Now, in Windows 7 that same code does not work.
To create the pipe I used the code ...
// Set the bInheritHandle flag so pipe handles are inherited.
ZeroMemory( &m_asynch_sa, sizeof(SECURITY_ATTRIBUTES));
m_asynch_sa.bInheritHandle = TRUE;
m_asynch_sa.lpSecurityDescriptor = NULL;
m_asynch_sa.nLength = sizeof(SECURITY_ATTRIBUTES);
// Create a pipe for the child process's STDOUT (will also be used for STDERR)
if( ! CreatePipe( &m_hChildStd_OUT_Rd, &m_hChildStd_OUT_Wr, &m_asynch_sa, 0 ) )
{
return 2;
}
Is it a case that m_asynch_sa.lpSecurityDescriptor should not be set to NULL. If that is the case, I cannot find any example of how to set it to a proper value.
Thank you in advance.

Related

Do I have to specify handles to be inherited with PROC_THREAD_ATTRIBUTE_LIST when using CreateProcess in threads?

I'm writing a program that spawns multiple child processes simultaneously and communicates to each of them by redirecting their stdin/stdout to anonymous pipes (as described here).
This is my actual code adapted from above example:
HANDLE h_child_stdout_r = NULL;
HANDLE h_child_stdout_w = NULL;
HANDLE h_child_stdin_r = NULL;
HANDLE h_child_stdin_w = NULL;
SECURITY_ATTRIBUTES saAttr;
BOOL bSuccess = TRUE;
// Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
// Create a pipe for the child process's STDOUT.
bSuccess &= CreatePipe(&h_child_stdout_r, &h_child_stdout_w, &saAttr, 0);
// Ensure the read handle to the pipe for STDOUT is not inherited.
bSuccess &= SetHandleInformation(h_child_stdout_r, HANDLE_FLAG_INHERIT, 0);
// Create a pipe for the child process's STDIN.
bSuccess &= CreatePipe(&h_child_stdin_r, &h_child_stdin_w, &saAttr, 0);
// Ensure the write handle to the pipe for STDIN is not inherited.
bSuccess &= SetHandleInformation(h_child_stdin_w, HANDLE_FLAG_INHERIT, 0);
if(!bSuccess)
{
throw dlg_exception("Failed to create child process handles");
}
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
// Set up members of the STARTUPINFO structure.
// This structure specifies the STDIN and STDOUT handles for redirection.
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
siStartInfo.hStdError = h_child_stdout_w;
siStartInfo.hStdOutput = h_child_stdout_w;
siStartInfo.hStdInput = h_child_stdin_r;
DWORD processFlags = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT;
// Create the child process.
bSuccess = CreateProcess(
const_cast<wchar_t *>(utf8::widen(exeName).c_str()), // application name
const_cast<wchar_t *>(utf8::widen(cmd).c_str()), // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
processFlags, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
// If an error occurs, exit the application.
if (!bSuccess)
{
string msg = "Create process failed with error code ";
msg.append( std::to_string(GetLastError()) );
throw dlg_exception(msg.c_str());
}
// Close handles to the child process and its primary thread.
// Some applications might keep these handles to monitor the status
// of the child process, for example.
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
// Close handles to the stdin and stdout pipes no longer needed by the child process.
// If they are not explicitly closed, there is no way to recognize that the child process has ended.
CloseHandle(h_child_stdout_w);
CloseHandle(h_child_stdin_r);
The above function will be called from multiple threads that are responsible for creating child processes and reading their output.
Everything works as expected but just to make sure I started searching about thread-safety of CreateProcess and I came across this article which in short says there will be an issue if multiple calls to CreateProcess are made from different threads because then each child process will inherit ALL handles from the parent process.
Now I have two questions:
1- Will this really be an issue for me? Since I am only redirecting the child process's stdin and stdout to the pipe handles, so I'm not sure if there will be a problem even if all the handles are inherited by the child. The child is merely writing to its own stdout and doesn't care about what handles it has inherited right?
2- I tried inspecting the child processes with Sysinternal's Process Explorer but as far as I could tell only two handles were inherited by each child not all of them.
Here's a screenshot of Process Explorer. As you can see the parent process has created 4 child processes. For each process I created, a new pair of handles would appear in parent process's list of handles (I have highlighted the first two):
As you can see there is four pairs of these, one for each child process.
And for each child process the handle list looks like this:
After reading the article what I was expecting was that the fourth child process would have all the handles listed because it's supposed to inherit all inheritable handles. But it only has two handles like all other childs.
So I'm wondering if I can get away with my current code without doing the PROC_THREAD_ATTRIBUTE_LIST which looks complicated and unfun.

Getting process information of every process

I am trying to create a program that any normal user can run on windows and generate a process list of all processes, including the executable location. I have used CreateToolhelp32Snapshot() to get all process names, pid, ppid. But having issues getting the image path. Everything I do results in pretty much Access Denied.
I have tried ZwQueryInformationProcess, GetProcessImageFileName, etc. and also using OpenProcess to get the handle to each process. I can get the handle by using PROCESS_QUERY_LIMITED_INFORMATION, but any other option doesn't work. I am lost and have been at this for a few days. Can anyone point me in the right direction?
This is the code that works for non-admin user on Windows. Use the szExeFile member of PROCESSENTRY32 to get the path:
HANDLE hProcessSnap = NULL;
HANDLE hProcess = NULL;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass = 0;
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
return;
}
// Set the size of the structure before using it.
pe32.dwSize = sizeof(PROCESSENTRY32);
// Retrieve information about the first process,
// and exit if unsuccessful
if (!Process32First(hProcessSnap, &pe32))
{
CloseHandle(hProcessSnap); // clean the snapshot object
return;
}
// Now walk the snapshot of processes, and
// display information about each process in turn
do
{
// do something with the pe32 struct.
// pe32.szExeFile -> path of the file
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);

Automatically Resume a Suspended Windows Process

I'm trying to write a windows batch file in order to resume a windows process that gets Suspended. I'm using pssuspend (from pstools) to resume the process. However, I'm trying to write windows batch file script that will continually get the status of a process (e.g. myExe.exe). If the script is not suspended, I would like for it to keep checking if it is suspended. If it is suspended, I would like it to run the pssuspend code. I'm unsure how to obtain the Suspend status. So far I have this:
if myExe.exe == "Suspend" (
pssuspend -r myExe.exe
suspend_fix.bat
) else (
suspend_fix.bat
)
Thanks for your help!
Windows services (that are created with the right attributes) can be suspended, but I am not sure how an executable can be suspended, or what exactly you mean by that.
If you mean that the program has been stopped, and when it does, you want to restart it, then here are a couple of code blocks that I have used to determine if a program is running:
1) by checking to see if the exe name exists, i.e., is running.
By the way, I recommend this one from my interpretation of your post:
BOOL ExeExists(char *exe)
{
HANDLE pss = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(pe);
if (Process32First(pss, &pe))
{
do
{
if (strstr(pe.szExeFile,exe))
{
CloseHandle(pss);
return TRUE;
}
}
while(Process32Next(pss, &pe));
}
CloseHandle(pss);
return FALSE;
}
2) by checking to see if the PID exists
BOOL PidExists(int pid)
{
HANDLE pss = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(pe);
if (Process32First(pss, &pe))
{
do
{
if (pe.th32ProcessID == pid)
{
CloseHandle(pss);
return TRUE;
}
}
while(Process32Next(pss, &pe));
}
CloseHandle(pss);
return FALSE;
}
By the way this is used to get the process ID (it is defined in winbase.h)
of the application making the call.
int GetProcessIdApp(void)
{
return GetProcessId(GetCurrentProcess());//defined in WinBase.h
}
Inside WinBase.h
WINBASEAPI
DWORD
WINAPI
GetProcessId(
__in HANDLE Process
);
In my scenario, An application broadcasts its PID at start up, such that
my monitoring program (the Windows service) can read it, then use it to make an ongoing determination of the application's status. If the app is discovered to be dead, and if other criteria indicate it should still be running, my service will start it back up.

Acessing CONIN$ without a tty

I am trying to get access to a file descriptor which receives input from the console. I am currently using
HANDLE fd = CreateFile(
"CONIN$",
GENERIC_READ | GENERIC_WRITE,
TRUE,
0,
OPEN_EXISTING,
0,
0);
SetConsoleMode(fd, ENABLE_WINDOW_INPUT);
And returning the fd to a program that reads (based on libuv) the input from the console.
This works fine when the process is executed in the console, but reading from the fd crashes when I pipe input into the program
echo hello | inputProgram
I have a suspicion that there is no console associated with the input process, but I'm not certain. How do I properly read the input into the cmd window when executing in this way?
So I a am binding to this C++ program in Node.js. I call
var ReadStream = require("tty").ReadStream();
var TTY = process.binding("tty_wrap").TTY;
module.exports = function () {
var opentty = require("./bin/opentty.node") // program returns the fd int
var fd = opentty();
var t = new _TTY(fd, true);
return new ReadStream(t);
}
opentty returns 3 in redirected input mode for the file handle. The code that deals with this file handle can be found here
https://github.com/joyent/node/blob/master/src/tty_wrap.cc#L185
which essentially calls into uv_tty_init found here
https://github.com/joyent/node/blob/master/deps/uv/src/win/tty.c#L99
The stream errors with Error: read EBADF, syscall: read
Looking through the Node repository it seems clear that new _TTY(fd, true) is expecting a C file descriptor, but you're passing it a Win32 handle.
The _open_osfhandle function creates a file descriptor from a handle.
So, you should try
var t = new _TTY(_open_osfhandle(fd), true);
(as discussed in the comments, this will only work if you're sharing the C runtime with libuv.)
Ideally you would use libuv's open function, but unfortunately there's a bug in fs__open:
case _O_RDWR:
access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
This is where it decides which access permissions to request. FILE_GENERIC_WRITE and FILE_GENERIC_READ are, as the names suggest, specific to files, and can't be used to open CONIN$. It should be
case _O_RDWR:
access = GENERIC_READ | GENERIC_WRITE;
which will work for both files and other types of objects such as the console input and output. (I've reproduced this in a simple C program; on my system, using the FILE_* permissions definitely prevents you from opening CONIN$.)

Waiting for grandchild processes in windows

Is it possible to wait for all processes launched by a child process in Windows? I can't modify the child or grandchild processes.
Specifically, here's what I want to do. My process launches uninstallA.exe. The process uninistallA.exe launches uninstallB.exe and immediately exits, and uninstallB.exe runs for a while. I'd like to wait for uninstallB.exe to exit so that I can know when the uninstall is finished.
Create a Job Object with CreateJobObject. Use CreateProcess to start UninstallA.exe in a suspended state. Assign that new process to your job object with AssignProcessToJobObject. Start UninstallA.exe running by calling ResumeThread on the handle of the thread you got back from CreateProcess.
Then the hard part: wait for the job object to complete its execution. Unfortunately, this is quite a bit more complex than anybody would reasonably hope for. The basic idea is that you create an I/O completion port, then you create the object object, associate it with the I/O completion port, and finally wait on the I/O completion port (getting its status with GetQueuedCompletionStatus). Raymond Chen has a demonstration (and explanation of how this came about) on his blog.
Here's a technique that, while not infallible, can be useful if for some reason you can't use a job object. The idea is to create an anonymous pipe and let the child process inherit the handle to the write end of the pipe.
Typically, grandchild processes will also inherit the write end of the pipe. In particular, processes launched by cmd.exe (e.g., from a batch file) will inherit handles.
Once the child process has exited, the parent process closes its handle to the write end of the pipe, and then attempts to read from the pipe. Since nobody is writing to the pipe, the read operation will block indefinitely. (Of course you can use threads or asynchronous I/O if you want to keep doing stuff while waiting for the grandchildren.)
When (and only when) the last handle to the write end of the pipe is closed, the write end of the pipe is automatically destroyed. This breaks the pipe and the read operation completes and reports an ERROR_BROKEN_PIPE failure.
I've been using this code (and earlier versions of the same code) in production for a number of years.
// pwatch.c
//
// Written in 2011 by Harry Johnston, University of Waikato, New Zealand.
// This code has been placed in the public domain. It may be freely
// used, modified, and distributed. However it is provided with no
// warranty, either express or implied.
//
// Launches a process with an inherited pipe handle,
// and doesn't exit until (a) the process has exited
// and (b) all instances of the pipe handle have been closed.
//
// This effectively waits for any child processes to exit,
// PROVIDED the child processes were created with handle
// inheritance enabled. This is usually but not always
// true.
//
// In particular if you launch a command shell (cmd.exe)
// any commands launched from that command shell will be
// waited on.
#include <windows.h>
#include <stdio.h>
void error(const wchar_t * message, DWORD err) {
wchar_t msg[512];
swprintf_s(msg, sizeof(msg)/sizeof(*msg), message, err);
printf("pwatch: %ws\n", msg);
MessageBox(NULL, msg, L"Error in pwatch utility", MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
ExitProcess(err);
}
int main(int argc, char ** argv) {
LPWSTR lpCmdLine = GetCommandLine();
wchar_t ch;
DWORD dw, returncode;
HANDLE piperead, pipewrite;
STARTUPINFO si;
PROCESS_INFORMATION pi;
SECURITY_ATTRIBUTES sa;
char buffer[1];
while (ch = *(lpCmdLine++)) {
if (ch == '"') while (ch = *(lpCmdLine++)) if (ch == '"') break;
if (ch == ' ') break;
}
while (*lpCmdLine == ' ') lpCmdLine++;
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
if (!CreatePipe(&piperead, &pipewrite, &sa, 1)) error(L"Unable to create pipes: %u", GetLastError());
GetStartupInfo(&si);
if (!CreateProcess(NULL, lpCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
error(L"Error %u creating process.", GetLastError());
if (WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED) error(L"Error %u waiting for process.", GetLastError());
if (!GetExitCodeProcess(pi.hProcess, &returncode)) error(L"Error %u getting exit code.", GetLastError());
CloseHandle(pipewrite);
if (ReadFile(piperead, buffer, 1, &dw, NULL)) {
error(L"Unexpected data received from pipe; bug in application being watched?", ERROR_INVALID_HANDLE);
}
dw = GetLastError();
if (dw != ERROR_BROKEN_PIPE) error(L"Unexpected error %u reading from pipe.", dw);
return returncode;
}
There is not a generic way to wait for all grandchildren but for your specific case you may be able to hack something together. You know you are looking for a specific process instance. I would first wait for uninstallA.exe to exit (using WaitForSingleObject) because at that point you know that uninstallB.exe has been started. Then use EnumProcesses and GetProcessImageFileName from PSAPI to find the running uninstallB.exe instance. If you don't find it you know it has already finished, otherwise you can wait for it.
An additional complication is that if you need to support versions of Windows older than XP you can't use GetProcessImageFileName, and for Windows NT you can't use PSAPI at all. For Windows 2000 you can use GetModuleFileNameEx but it has some caveats that mean it might fail sometimes (check docs). If you have to support NT then look up Toolhelp32.
Yes this is super ugly.
Use a named mutex.
One possibility is to install Cygwin and then use the ps command to watch for the grandchild to exit

Resources