Using stdout in a Win32 GUI application: crashes if I don't have a redirect to file in arguments - windows

I'm building a Win32 GUI app. Inside that app, I'm using a DLL that was intended to be used in a command line app.
Suppose Foo.exe is my GUI app, and bar() is a function in the DLL that prints "hello" to stdout. Foo.exe calls bar().
If I run Foo.exe from the command line with a redirect (>) (i.e. Foo.exe > out.txt) it writes "hello" to out.txt and exits normally (as expected).
However, if I run Foo.exe without a redirect (either from cmd.exe or by double-clicking in Windows Explorer), it crashes when bar() is called.
If I run Foo.exe inside the debugger with the redirect in the command line (set through VS's properties for the project) and call "GetStdHandle(STD_OUTPUT_HANDLE)", I get a reasonable address for a handle. If I call it without the redirect in the command line, I get 0.
Do I need something to "initialize" standard out? Is there a way that I can set up this redirect in the application startup? (Redirecting to a file would be ideal. But just throwing out the data printed by the DLL would be okay, too.)
Finally, I suspect that the DLL is writing to stdout through the CRT POSIX-like API, because it is a cross-platform DLL. I don't know if this matters.
I've tried creating a file with CreateFile and calling SetStdHandle, but that doesn't seem to work. I may be creating the file incorrectly, however. See code below.
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
// hStdOut is zero
HANDLE hFile;
hFile = CreateFile(TEXT("something.txt"), // name of the write
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // default security
CREATE_NEW, // create new file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
BOOL r = SetStdHandle(STD_OUTPUT_HANDLE, hFile) ;
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
// hStdOut is now equal to hFile, and r is 1
bar();
// crashes if there isn't a redirect in the program arguments
UPDATE: I just found this article: http://support.microsoft.com/kb/105305. It states "Note that this code does not correct problems with handles 0, 1, and 2. In fact, due to other complications, it is not possible to correct this, and therefore it is necessary to use stream I/O instead of low-level I/O."
My DLL definitely uses file handles 0,1 and 2. So, there may be no good solution to this problem.
I'm working on a solution that checks for this case, and re-launches the exe appropriately using CreateProcess. I'll post here when I'm done.

The solution that I've found is the following:
obtain a valid File HANDLE in some way to direct the standard output.
Lets call the file handle "fh".
(please note that on Windows a File HANDLE is not the same thing of a file descriptor)
associate a file descriptor to the file handle with _open_osfhandle
(see http://msdn.microsoft.com/en-us/library/kdfaxaay.aspx for details)
Lets call "fd" the new file descriptor, an int value.
call dup2 to associate the STDOUT_FILENO to the given file descriptor:
dup2(fd, STDOUT_FILENO)
create a file strem associated to the stdout file descriptor
FILE* f = _fdopen(STDOUT_FILENO, "w");
memset stdout to the content of f:
*stdout = *f
call SetStdHandle on the given file handle:
SetStdHandle(STD_OUTPUT_HANDLE, ofh);
Please note that I've not tested exactly this sequence but something slightly different.
I don't know if some steps are redundant.
In any case the following article explain very well the concept of file handle, descriptor et fiel stream:
http://dslweb.nwnexus.com/~ast/dload/guicon.htm

You must build foo.exe as a console application with the /SUBSYSTEM switch. Windows will allocate a console (stdout) for your application automatically, which can be :
The current console
A redirection to a file
A pipe to another program's STDIN
If you build foo.exe as a GUI application, the console is not allocated by default, wich explains the crash
If you must use the GUI subsystem, it can still be done with AllocConsole. This old WDJ article has sample code to help you.

Can you tell me which library do you use? This problem have good solution. Write small stub launcher EXE (in GUI mode but with NO windows!) that have your icon and that all shortcuts launch. Make this stub EXE "CreateProcess" the real EXE with redirected output to "NUL" or "CON", or, CreateProcess() it suspended, take its STDOUT, doing nothing with it. This way, your original EXE should work without visible console, but will actually have where to write - in the handles 0,1 and 2 that are taken by the parent invisible stub EXE. Note that killing the parent EXE may make the child lost its handles - and - crash.
You may end up with two processes in Task Manager. So you can try making these 2 processes a job like Google Chrome does.
On your question Do I need something to "initialize" standard out? - only your parent / launcher can pre-initialize your STDOUT for handles 0,1 and 2 "properly".

Related

Windows DuplicateHandle named pipe handle strange error 183 "file already exists"

I have a problem with DuplicateHandle (Win32). I try to duplicate a named pipe handle and I always get the Error 183 "file already exists". I do not understand this error message, because I try to create a copy of a file handle and the new file handle does not exist before. (Is there a start value required to overwrite?) This is my call:
return DuplicateHandle (MeshellProcessHandle, sourcehandle, HelperProcess, targethandle, 0, TRUE, DUPLICATE_SAME_ACCESS) != 0;
To understand what I am doing, I have to explain more extensively: I am working on a convenient editor frontend for the command line program cmd.exe. This project already works fine on the OS/2 Operating System which is very familiar with Win32, because from a historical point of view, the two OS were developed together until one year before finishing, where Microsoft and IBM went different ways.
The implementation of this program was quite tricky: There's a windowed front end editor program. This program creates named pipes for stderr, stdout and stderr, but from the reverse point of view (output from cmd.exe is input for the editor). Because of limited communication between different sessions, I had to program a "cmd helper program" which is a tiny commandline program holding several API calls and running in the same session as the cmd.exe program. The helper gets the editor process ID via commandline parameter and opens the existing pipes created by the windowed editor program and then redirects stdin/stdout/stderr to the pipes. The helper gets the process handle of the editor from the editor process ID via "OpenProcess" API call. Then the helper executes cmd.exe which automatically inherits the stdin/stdout/stderr handles and now cmd.exe writes to and reads from the pipe.
Another option would be to parse the full pipe names to cmd.exe without using DuplicateHandle, but I would prefer to be as close as to my solution which already works fine on the OS/2 Operating System.
I am still not sure why I have no access rights to duplicate the pipe handles. But I have found another solution: My helper console program starts the child process (cmd.exe) and within this child process, I want to use the named pipes instead of stdin/stdout/stderr - this is the reason why I want to use DuplicateHandle. Windows offers a convenient solution when starting the child process by using
CreateProcess (...)
With CreateProcess, you have always to hold parameters in the STARTUPINFO structure. And there are three handle variables you can set to redirect stdin/stdout/stderr to the three named pipes cmd_std*:
STARTUPINFO StartupInfo;
HFILE cmd_stdout, cmd_stdin, cmd_stderr;
//Open the existing pipes with CreateFile
//Start child process program
StartupInfo.hStdOutput = &cmd_stdout;
StartupInfo.hStdInput = &cmd_stdin;
StartupInfo.hStdError = &cmd_stderr;
CreateProcess (..., &StartupInfo, ...);
This solution has much less code than the variant with DuplicateHandle, because I also have to save and to restore the original file handles, so this way replaces 9 DuplicateHandle calls.
I did program the changes now but my new code described above does not work. If I set the "handle inheritance flag" in CreateProcess to TRUE, cmd.exe does not get executed, but CreateProcess returns TRUE (=OK). Here's my detailed code:
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInformation;
HFILE cmd_stdout, cmd_stdin, cmd_stderr;
char *pprogstr, *pargstr;
//Open the existing pipes with CreateFile
//Start child process program cmd.exe
StartupInfo.hStdOutput = &cmd_stdout;
StartupInfo.hStdInput = &cmd_stdin;
StartupInfo.hStdError = &cmd_stderr;
StartupInfo.dwFlags = STARTF_USESTDHANDLES;
pprogstr = "C:\\WINDOWS\\system32\\cmd.exe";
pargstr = "/K";
CreateProcess (
pprogstr, // pointer to name of executable module
pargstr, // pointer to command line string
NULL, // pointer to process security attributes
NULL, // pointer to thread security attributes
TRUE, // handle inheritance flag
0, // creation flags
NULL, // pointer to new environment block
NULL, // pointer to current directory name
&StartupInfo, // pointer to STARTUPINFO
&ProcessInformation) // pointer to PROCESS_INFORMATION
Any idea?

LockFileEx returns success, but seems to have no effect

I'm trying to lock a file, because it is sitting on a network drive, and multiple instances of a program from multiple computers need to edit it. To prevent damage, I intend to set it up so that only one of the instances has rights to it at a time.
I implemented a lock, which would theoretically lock the first 100 bytes of the file from any access. I'm using Qt with its own file handling, but it has a method of returning a generic file handle.
QFile file(path);
HANDLE handle = (HANDLE)_get_osfhandle(file.handle());
OVERLAPPED ov1;
memset(&ov1, 0, sizeof(ov1));
ov1.Offset = 0;
ov1.OffsetHigh = 0;
if (handle == INVALID_HANDLE_VALUE)
{
// error
return;
}
LockFileEx(handle, LOCKFILE_FAIL_IMMEDIATELY | LOCKFILE_EXCLUSIVE_LOCK, 0, 100, 0, &ov1);
qDebug() << file.readLine();
LockFileEx() returns 1, so it seems to have been successful. However, if I run the program in multiple instances, all of them can read and print the first line of the file. More than this, I can freely edit the file with any text editor.
Being a network file is not an issue, as it behaves similarly with a local file.
The problem was that, while the program does not terminate, the QFile variable was local, so after finishing the function, the destructor of the QFile was called, so it released the file. The OS then seemed to have released the lock.
If my QFile survives the scope, everything works just fine. A minor issue is, that while I expected the file to be locked against reading, external programs do have a read-only access to it. It's not a problem, as my program can check whether it can create a lock, and detect failure to do so. This means that the intended mutex functionality works.

file_operations Question, how do i know if a process that opened a file for writing has decided to close it?

I'm currently writing a simple "multicaster" module.
Only one process can open a proc filesystem file for writing, and the rest can open it for reading.
To do so i use the inode_operation .permission callback, I check the operation and when i detect someone open a file for writing I set a flag ON.
i need a way to detect if a process that opened a file for writing has decided to close the file so i can set the flag OFF, so someone else can open for writing.
Currently in case someone is open for writing i save the current->pid of that process and when the .close callback is called I check if that process is the one I saved earlier.
Is there a better way to do that? Without saving the pid, perhaps checking the files that the current process has opened and it's permission...
Thanks!
No, it's not safe. Consider a few scenarios:
Process A opens the file for writing, and then fork()s, creating process B. Now both A and B have the file open for writing. When Process A closes it, you set the flag to 0 but process B still has it open for writing.
Process A has multiple threads. Thread X opens the file for writing, but Thread Y closes it. Now the flag is stuck at 1. (Remember that ->pid in kernel space is actually the userspace thread ID).
Rather than doing things at the inode level, you should be doing things in the .open and .release methods of your file_operations struct.
Your inode's private data should contain a struct file *current_writer;, initialised to NULL. In the file_operations.open method, if it's being opened for write then check the current_writer; if it's NULL, set it to the struct file * being opened, otherwise fail the open with EPERM. In the file_operations.release method, check if the struct file * being released is equal to the inode's current_writer - if so, set current_writer back to NULL.
PS: Bandan is also correct that you need locking, but the using the inode's existing i_mutex should suffice to protect the current_writer.
I hope I understood your question correctly: When someone wants to write to your proc file, you set a variable called flag to 1 and also save the current->pid in a global variable. Then, when any close() entry point is called, you check current->pid of the close() instance and compare that with your saved value. If that matches, you turn flag to off. Right ?
Consider this situation : Process A wants to write to your proc resource, and so you check the permission callback. You see that flag is 0, so you can set it to 1 for process A. But at that moment, the scheduler finds out process A has used up its time share and chooses a different process to run(flag is still o!). After sometime, process B comes up wanting to write to your proc resource also, checks that the flag is 0, sets it to 1, and then goes about writing to the file. Unfortunately at this moment, process A gets scheduled to run again and since, it thinks that flag is 0 (remember, before the scheduler pre-empted it, flag was 0) and so sets it to 1 and goes about writing to the file. End result : data in your proc resource goes corrupt.
You should use a good locking mechanism provided by the kernel for this type of operation and based on your requirement, I think RCU is the best : Have a look at RCU locking mechanism

Change default Console I/O functions handle

Is it possible to somehow change standart I/O functions handle on Windows? Language preffered is C++. If I understand it right, by selecting console project, compiler just pre-allocate console for you, and operates all standart I/O functions to work with its handle. So, what I want to do is to let one Console app actually write into another app Console buffer. I though that I could get first´s Console handle, than pass it to second app by a file (I don´t know much about interprocess comunication, and this seems easy) and than somehow use for example prinf with the first app handle. Can this be done? I know how to get console handle, but I have no idea how to redirect printf to that handle. Its just study-purpose project to more understand of OS work behind this. I am interested in how printf knows what Console it is assiciated with.
If I understand you correctly, it sounds like you want the Windows API function AttachConsole(pid), which attaches the current process to the console owned by the process whose PID is pid.
If I understand you correct you can find the source code of application which you want to write in http://msdn.microsoft.com/en-us/library/ms682499%28VS.85%29.aspx. This example show how to write in stdin of another application and read it's stdout.
For general understanding. Compiler don't "pre-allocate console for you". Compiler use standard C/C++ libraries which write in the output. So if you use for example printf() the following code will be executed at the end will look like:
void Output (PCWSTR pszwText, UINT uTextLenght) // uTextLenght is Lenght in charakters
{
DWORD n;
UINT uCodePage = GetOEMCP(); // CP_OEMCP, CP_THREAD_ACP, CP_ACP
PSTR pszText = _alloca (uTextLenght);
// in the console are typically not used UNICODE, so
if (WideCharToMultiByte (uCodePage, 0, pszwText, uTextLenght,
pszText, uTextLenght, NULL, NULL) != (int)uTextLenght)
return;
WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), pszText, uTextLenght, &n, NULL);
//_tprintf (TEXT("%.*ls"), uTextLenght, pszText);
//_puttchar();
//fwrite (pszText, sizeof(TCHAR), uTextLenght, stdout);
//_write (
}
So if one changes the value of STD_OUTPUT_HANDLE all output will be go to a file/pipe and so on. If instead of WriteFile the program use WriteConsole function such redirection will not works, but standard C/C++ library don't do this.
If you want redirect of stdout not from the child process but from the current process you can call SetStdHandle() directly (see http://msdn.microsoft.com/en-us/library/ms686244%28VS.85%29.aspx).
The "allocating of console" do a loader of operation system. It looks the word of binary EXE file (in the Subsystem part of IMAGE_OPTIONAL_HEADER see http://msdn.microsoft.com/en-us/library/ms680339%28VS.85%29.aspx) and if the EXE has 3 on this place (IMAGE_SUBSYSTEM_WINDOWS_CUI), than it use console of the parent process or create a new one. One can change a little this behavior in parameters of CreateProcess call (but only if you start child process in your code). This Subsystem flag of the EXE you define with respect of linker switch /subsystem (see http://msdn.microsoft.com/en-us/library/fcc1zstk%28VS.80%29.aspx).
If you want to redirect printf to a handle (FILE*), just do
fprintf(handle, "...");
For example replicating printf with fprintf
fprintf(stdout, "...");
Or error reporting
fprintf(stderr, "FATAL: %s fails", "smurf");
This is also how you write to files. fprintf(file, "Blah.");

win32 api for Process.BeginOutputReadLine

i wanted to know the c++ equivalent of c#'s Process.BeginOutputReadLine, where i aynchronously read from the standardoutput of another process. Is there any API for it?
To read the standard output of a process you need to assign an appropriate handle to an instance of STARTUPINFO passed to CreateProcess. Remember to include the STARTF_USESTDHANDLES flag.
Usually an anonymous pipe is used, created via CreatePipe.
See "Creating a Child Process with Redirected Input and Output" for an example.
You can use the normal Win32 approaches (OVERLAPPED + event, IOCompleteion Port,...) to reading the output handle asynchronously.

Resources