mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 18:28:49 +00:00 
			
		
		
		
	 7a1f91709b
			
		
	
	
		7a1f91709b
		
	
	
	
	
		
			
			MSDN sample programs use it, apparently in error. The correct name is WIN32_LEAN_AND_MEAN. After switching to the correct name, in two cases more was needed because the code actually relied on things that disappear when WIN32_LEAN_AND_MEAN is defined.
		
			
				
	
	
		
			112 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * w9xpopen.c
 | |
|  *
 | |
|  * Serves as an intermediate stub Win32 console application to
 | |
|  * avoid a hanging pipe when redirecting 16-bit console based
 | |
|  * programs (including MS-DOS console based programs and batch
 | |
|  * files) on Window 95 and Windows 98.
 | |
|  *
 | |
|  * This program is to be launched with redirected standard
 | |
|  * handles. It will launch the command line specified 16-bit
 | |
|  * console based application in the same console, forwarding
 | |
|  * it's own redirected standard handles to the 16-bit child.
 | |
| 
 | |
|  * AKA solution to the problem described in KB: Q150956.
 | |
|  */    
 | |
| 
 | |
| #define WIN32_LEAN_AND_MEAN
 | |
| #include <windows.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>  /* for malloc and its friends */
 | |
| 
 | |
| const char *usage =
 | |
| "This program is used by Python's os.popen function\n"
 | |
| "to work around a limitation in Windows 95/98.  It is\n"
 | |
| "not designed to be used as a stand-alone program.";
 | |
| 
 | |
| int main(int argc, char *argv[])
 | |
| {
 | |
|     BOOL bRet;
 | |
|     STARTUPINFO si;
 | |
|     PROCESS_INFORMATION pi;
 | |
|     DWORD exit_code=0;
 | |
|     int cmdlen = 0;
 | |
|     int i;
 | |
|     char *cmdline, *cmdlinefill;
 | |
| 
 | |
|     if (argc < 2) {
 | |
|         if (GetFileType(GetStdHandle(STD_INPUT_HANDLE))==FILE_TYPE_CHAR)
 | |
|             /* Attached to a console, and therefore not executed by Python
 | |
|                Display a message box for the inquisitive user
 | |
|             */
 | |
|             MessageBox(NULL, usage, argv[0], MB_OK);
 | |
|         else {
 | |
|             /* Eeek - executed by Python, but args are screwed!
 | |
|                Write an error message to stdout so there is at
 | |
|                least some clue for the end user when it appears
 | |
|                in their output.
 | |
|                A message box would be hidden and blocks the app.
 | |
|              */
 | |
|             fprintf(stdout, "Internal popen error - no args specified\n%s\n", usage);
 | |
|         }
 | |
|         return 1;
 | |
|     }
 | |
|     /* Build up the command-line from the args.
 | |
|        Args with a space are quoted, existing quotes are escaped.
 | |
|        To keep things simple calculating the buffer size, we assume
 | |
|        every character is a quote - ie, we allocate double what we need
 | |
|        in the worst case.  As this is only double the command line passed
 | |
|        to us, there is a good chance this is reasonably small, so the total 
 | |
|        allocation will almost always be < 512 bytes.
 | |
|     */
 | |
|     for (i=1;i<argc;i++)
 | |
|         cmdlen += strlen(argv[i])*2 + 3; /* one space, maybe 2 quotes */
 | |
|     cmdline = cmdlinefill = (char *)malloc(cmdlen+1);
 | |
|     if (cmdline == NULL)
 | |
|         return -1;
 | |
|     for (i=1;i<argc;i++) {
 | |
|         const char *arglook;
 | |
|         int bQuote = strchr(argv[i], ' ') != NULL;
 | |
|         if (bQuote)
 | |
|             *cmdlinefill++ = '"';
 | |
|         /* escape quotes */
 | |
|         for (arglook=argv[i];*arglook;arglook++) {
 | |
|             if (*arglook=='"')
 | |
|                 *cmdlinefill++ = '\\';
 | |
|             *cmdlinefill++ = *arglook;
 | |
|         }
 | |
|         if (bQuote)
 | |
|             *cmdlinefill++ = '"';
 | |
|         *cmdlinefill++ = ' ';
 | |
|     }
 | |
|     *cmdlinefill = '\0';
 | |
| 
 | |
|     /* Make child process use this app's standard files. */
 | |
|     ZeroMemory(&si, sizeof si);
 | |
|     si.cb = sizeof si;
 | |
|     si.dwFlags = STARTF_USESTDHANDLES;
 | |
|     si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
 | |
|     si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
 | |
|     si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
 | |
| 
 | |
|     bRet = CreateProcess(
 | |
|         NULL, cmdline,
 | |
|         NULL, NULL,
 | |
|         TRUE, 0,
 | |
|         NULL, NULL,
 | |
|         &si, &pi
 | |
|         );
 | |
| 
 | |
|     free(cmdline);
 | |
| 
 | |
|     if (bRet) {
 | |
|         if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_FAILED) {
 | |
| 	    GetExitCodeProcess(pi.hProcess, &exit_code);
 | |
| 	}
 | |
|         CloseHandle(pi.hProcess);
 | |
|         CloseHandle(pi.hThread);
 | |
|         return exit_code;
 | |
|     }
 | |
| 
 | |
|     return 1;
 | |
| }
 |