4 * Serves as an intermediate stub Win32 console application to
5 * avoid a hanging pipe when redirecting 16-bit console based
6 * programs (including MS-DOS console based programs and batch
7 * files) on Window 95 and Windows 98.
9 * This program is to be launched with redirected standard
10 * handles. It will launch the command line specified 16-bit
11 * console based application in the same console, forwarding
12 * its own redirected standard handles to the 16-bit child.
14 * AKA solution to the problem described in KB: Q150956.
17 #define WIN32_LEAN_AND_MEAN
20 #include <stdlib.h> /* for malloc and its friends */
23 "This program is used by Python's os.popen function\n"
24 "to work around a limitation in Windows 95/98. It is\n"
25 "not designed to be used as a stand-alone program.";
27 int main(int argc
, char *argv
[])
31 PROCESS_INFORMATION pi
;
35 char *cmdline
, *cmdlinefill
;
38 if (GetFileType(GetStdHandle(STD_INPUT_HANDLE
))==FILE_TYPE_CHAR
)
39 /* Attached to a console, and therefore not executed by Python
40 Display a message box for the inquisitive user
42 MessageBox(NULL
, usage
, argv
[0], MB_OK
);
44 /* Eeek - executed by Python, but args are screwed!
45 Write an error message to stdout so there is at
46 least some clue for the end user when it appears
48 A message box would be hidden and blocks the app.
50 fprintf(stdout
, "Internal popen error - no args specified\n%s\n", usage
);
54 /* Build up the command-line from the args.
55 Args with a space are quoted, existing quotes are escaped.
56 To keep things simple calculating the buffer size, we assume
57 every character is a quote - ie, we allocate double what we need
58 in the worst case. As this is only double the command line passed
59 to us, there is a good chance this is reasonably small, so the total
60 allocation will almost always be < 512 bytes.
63 cmdlen
+= strlen(argv
[i
])*2 + 3; /* one space, maybe 2 quotes */
64 cmdline
= cmdlinefill
= (char *)malloc(cmdlen
+1);
67 for (i
=1;i
<argc
;i
++) {
69 int bQuote
= strchr(argv
[i
], ' ') != NULL
;
73 for (arglook
=argv
[i
];*arglook
;arglook
++) {
75 *cmdlinefill
++ = '\\';
76 *cmdlinefill
++ = *arglook
;
84 /* Make child process use this app's standard files. */
85 ZeroMemory(&si
, sizeof si
);
87 si
.dwFlags
= STARTF_USESTDHANDLES
;
88 si
.hStdInput
= GetStdHandle(STD_INPUT_HANDLE
);
89 si
.hStdOutput
= GetStdHandle(STD_OUTPUT_HANDLE
);
90 si
.hStdError
= GetStdHandle(STD_ERROR_HANDLE
);
103 if (WaitForSingleObject(pi
.hProcess
, INFINITE
) != WAIT_FAILED
) {
104 GetExitCodeProcess(pi
.hProcess
, &exit_code
);
106 CloseHandle(pi
.hProcess
);
107 CloseHandle(pi
.hThread
);