Set child process name in Windows? - c++

I have process, that run multiple times child processes (each without GUI), and it needs to set to all child processes different "names" and "description" for Task Manager. Is it possible using Win API? I can't find solution for Windows family.
I look to WriteProcessMemory, but it looks like form of cheating, even if there is possible to change name.
Solution with copying .exe file, run it, and after process finished - deleting it - is even more cheating.
There may be exist solution using start process from memory (so, I load exe file to memory, then start it from there), but it also looks bad and I'm not sure I will be able to change name.
I hope there have to be solution to set process name to my own child process, isn't it?

You can't change the "Image Name" that appears in Task Manager. As you found, Windows obtains that from the name of the file that is actually executing and the only way to have something different appear is to actually run a file with a different name (such as by copying your executable).
If you are targeting newer versions of Windows, Task Manager can display a "Command Line" column (View -> Select Columns). You can make your processes distinguishable by including a particular flag in the command line, or by setting the first token of the lpCommandLine argument to something unique - you just have to also set the lpApplicationName argument to the actual executable you want to run so the loader can find it.
For example:
BOOL ret1 = CreateProcess(
"c:\\program\\worker.exe",
"worker1.exe infile outfile",
...);
BOOL ret2 = CreateProcess(
"c:\\program\\worker.exe",
"worker2.exe infile outfile",
...);
These will have identical Image Name values in Task Manager, but they will be distinguishable by the Command Line values.

Related

How to get the number of process sharing a file by using mmap?

Is there any way to get the number of process those are mapped to a particular file ?
Actually, I want to delete the file which is shared by multiple process when all processes are down. Is there any way to do that?
I tried with fstat function call to get the number of hard links but since after mapping I am closing the file so stat.st_nlink is always 0.
At first you need to create a pool of your fork. Then you can access to every file either hardlink,symb-link and so on via struct stat , pleae see man 2 stat.
Because you want to find out relative between PIDs and files you need to /proc you need to : /proc/PID/stat
I think the following project easy your job:
http://brokestream.com/procstat.html
After saving all of files of your process in a std::tuple, you can down your process and then delete your files.
Assuming that full path to the mmap()-ed file is /dir1/dir2/my_file, you could create a daemon, which executes lsof /dir1/dir2/my_file in a loop, until it finds that no process has my_file opened.
Assuming the applications are your, and you can change the code, I would advise another approach. Have one application that starts before others (can even spawn other processes), and have this application create and delete the file.

How to return a command from a c++ application to parent terminal?

Is it possible to run a c++ application from a terminal and on certain conditions return a command back into the terminal from which it was called from? For instance, if I were to run an application within my terminal and after my selections; my application needs to change my PATH by running an export command such as:
(USING BASH)
export PATH=.:/home/User/application/bin:$PATH
After I'm done and before my application completely closes can I make the application change my terminals local environment variables with the above command? Does Qt offer a way of doing this? Thanks in advance for any help!
No, you cannot change parent application environment.
Why? When your parent app started yours (probably using system()), it actually fork()ed - child process was born as to be almost exact replica of parent, and then that child used execve() call, which completely replaced executable image of that process with executable image of your application (for scripts it would be image of interpreter like bash).
In addition to that, that process also prepared few more things. One is list of open files, starting with file handles 0,1,2 (stdin, stdout, stderr). Also, it created memory block (which belongs to child process address space) which contains environment variables (as key=value pairs).
Because environment block belongs to your process, you can change your own environment as you please. But, it is impossible for your process to change environment memory block of parent (or any other process for that matter). The only way to possibly achieve this would be to use IPC (inter-process communication) and gently ask parent to do this task inside of it, but parent must be actively listening (on local or network socket) and be willing to fulfill such request from somebody, and child is not any special compared to any other process in that regard.
This also reason why you can change environment in bash using some shell script, but ONLY using source or . bash macro - because it is processed by bash itself, without starting any external process.
However, you cannot change environment by executing any other program or script for reasons stated above.
The common solution is to have your application print the result to standard output, then have the invoker pass it to its environment. A textbook example is ssh-agent which prints an environment variable assigment; you usually invoke it with eval $(ssh-agent)

Is it possible to send command to console window in which my program is running?

I know the system() function but that creates it's own environment so every variable set here isn't forwarded to main console. I wonder is it possible to send command as it would be written by the user or as it would be executed by *.bat file ?
The reason I need this is that I look for a way to set env variable of parent CMD process. And yes I know that system doesn't want me to do it, but maybe there is a some workaround for that...
Idea is to create app that would set as a variable anything that is send to it via input pipe, like this:
echo Bob| setvar name
so then:
echo %name%
would produce Bob
The whole idea is to make easier setting a variable from any program output (I know how to do it with for command) with taking account of peculiarities with special batch characters like ^!% since these are allowed in file names. It would make simpler many cmd scripts.
You can certainly run programs in the same console window as your program. That's the default behavior for CreateProcess. MSDN has more details on what happens between related processes sharing a console. You'll probably want to wait for the child process to terminate before continuing to run your own program.
However, that won't help with your real goal. The window where a program runs has absolutely nothing to do with the environment variables of any of its ancestor processes. You'll have to look elsewhere for a solution to your real problem.

Is there a way to identify the Windows command prompt regardless of file name or location?

I'm writing a program to immediately track and kill when a user runs command prompt (and regedit if that's possible). This is to stop users from running commands I would rather they not have.
I've already written code that sees when a process is launched and checks its name using QueryFullProcessImageName. The issue is that if someone were to rename command prompt then I could no longer detect it via process name. The way I detect command prompt is currently "\cmd.exe" but clearly this is not very secure.
Posted below is what I have for the code. I removed all error checking for brevity. Please let me know if you need more clarity. Thanks!
TCHAR exeName[MAX_PATH];
DWORD exeNameSize = MAX_PATH;
//the pid comes into the function as a parameter
HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, pid);
if (handle)
{
if (QueryFullProcessImageName(handle, 0, exeName, &exeNameSize))
{
tstring name = exeName;
/*
badProcs would contain the path identifiers such as
"\\cmd.exe" or "\\regedit.exe". This detection is
what I want to make better.
*/
for(int i=0; i < badProcs.size(); i++)
{
if(tstring::npos != name.find(badProcs.at(i)))
{
if(TerminateProcess(handle,0))
OutputDebugString(_T("Process should be dead\n\n"));
}
}
}
CloseHandle(handle);
}
Some additional information: The reason I'm writing this is to control what goes on in other desktops. I want to make it so that when a user launches a different desktop (via whatever proprietary program) I can control whether or not they have access to items which present the biggest security holes to the system. Given that I only want to control actions does on the other desktop, I do not want to change settings for fear of corrupting data outside of the target desktop. Is corruption not something to worry about?
I'm only interested in controlling a proprietary desktop, not mucking with what users do in their own space. Essentially the separate desktop is for corporate work, and I want to be able to limit what people can do with company information, etc.
Don't. Windows has internal means for that. Read up on the policy editor, and/or file access control.
If you're admin and the "user" is not, policy (or simple ACL) will do the job; if the "user" is also an admin, they'll be able to defeat your program fairly easily.
The best way to block the command prompt and registry editor is through the windows registry. These work even if you copy the executables to a different location.
Both the Registry Editor and Command Prompt cannot be run if the registry keys are set:
HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\System\DisableRegistryTools
or for the whole machine
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\System\DisableRegistryTools
Setting this to 1 will disable regedit, and setting to 0 will enable it.
HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\System\DisableCMD
(the local machine varient works here as well).
Setting this to 1 will disable the command prompt and batch files, setting this to 2 will only disable the command line, and setting to 0 will enable it.

How can I change Windows shell (cmd.exe) environment variables from C++?

I would like to write a program that sets an environment variable in an instance of the shell (cmd.exe) it was called from. The idea is that I could store some state in this variable and then use it again on a subsequent call.
I know there are commands like SetEnvironmentVariable, but my understanding is that those only change the variable for the current process and won't modify the calling shell's variables.
Specifically what I would like to be able to do is create a command that can bounce between two directories. Pushd/Popd can go to a directory and back, but don't have a way of returning a 2nd time to the originally pushed directory.
MSDN states the following:
Calling SetEnvironmentVariable has no
effect on the system environment
variables. To programmatically add or
modify system environment variables,
add them to the
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session
Manager\Environment registry key, then
broadcast a WM_SETTINGCHANGE message
with lParam set to the string
"Environment". This allows
applications, such as the shell, to
pick up your updates. Note that the
values of the environment variables
listed in this key are limited to 1024
characters.
Considering that there are two levels of environment - System and Process - changing those in the shell would constitute changing the environment of another process. I don't believe that this is possible.
A common techniques is the write an env file, that is then "call"ed from the script.
del env.var
foo.exe ## writes to env.var
call env.var
In Windows when one process creates another, it can simply let the child inherit the current environment strings, or it can give the new child process a modified, or even completely new environment.
See the full info for the CreateProccess() win32 API
There is no supported way for a child process to reach back to the parent process and change the parent's environment.
That being said, with CMD scripts and PowerShell, the parent command shell can take output from the child process and update its own environment. This is a common technique.
personly, I don't like any kind of complex CMD scripts - they are a bitch to write an debug. You may want to do this in PowerShell - there is a learning curve to be sure, but it is much richer.
There is a way...
Just inject your code into parent process and call SetEnvironmentVariableA inside
cmd's process memory. After injecting just free the allocated memory.