⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclwinpipe.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
	outputHandle = INVALID_HANDLE_VALUE;	inputFileName = NULL;	outputFileName = NULL;	if (inputFile != NULL) {	    filePtr = (WinFile *) inputFile;	    switch (filePtr->type) {		case WIN_FILE:		case WIN32S_TMPFILE: {		    h = INVALID_HANDLE_VALUE;		    inputFileName = MakeTempFile(&inputTempFile);		    if (inputFileName != NULL) {			h = CreateFile(inputFileName, GENERIC_WRITE, 0, 				NULL, CREATE_ALWAYS, 0, NULL);		    }		    if (h == INVALID_HANDLE_VALUE) {			Tcl_AppendResult(interp, "couldn't duplicate input handle: ", 				Tcl_PosixError(interp), (char *) NULL);			goto end32s;		    }		    CopyChannel(h, filePtr->handle);		    CloseHandle(h);		    break;		}		case WIN32S_PIPE: {		    inputFileName = ((WinPipe*)inputFile)->fileName;		    break;		}	    }	}	if (inputFileName == NULL) {	    inputFileName = "nul";	}	if (outputFile != NULL) {	    filePtr = (WinFile *)outputFile;	    if (filePtr->type == WIN_FILE) {		outputFileName = MakeTempFile(&outputTempFile);		if (outputFileName == NULL) {		    Tcl_AppendResult(interp, "couldn't duplicate output handle: ",			    Tcl_PosixError(interp), (char *) NULL);		    goto end32s;		}		outputHandle = filePtr->handle;	    } else if (filePtr->type == WIN32S_PIPE) {		outputFileName = ((WinPipe*)outputFile)->fileName;	    }	}	if (outputFileName == NULL) {	    outputFileName = "nul";	}	if (applType == APPL_DOS) {	    args[0] = (DWORD) Tcl_DStringValue(&cmdLine);	    args[1] = (DWORD) inputFileName;	    args[2] = (DWORD) outputFileName;	    trans[0] = &args[0];	    trans[1] = &args[1];	    trans[2] = &args[2];	    trans[3] = NULL;	    if (TclWinSynchSpawn(args, 0, trans, pidPtr) != 0) {		result = TCL_OK;	    }	} else if (applType == APPL_WIN3X) {	    args[0] = (DWORD) Tcl_DStringValue(&cmdLine);	    trans[0] = &args[0];	    trans[1] = NULL;	    if (TclWinSynchSpawn(args, 1, trans, pidPtr) != 0) {		result = TCL_OK;	    }	} else {	    if (CreateProcess(NULL, Tcl_DStringValue(&cmdLine), NULL, NULL, 		    FALSE, DETACHED_PROCESS, NULL, NULL, &startInfo, 		    &procInfo) != 0) {		CloseHandle(procInfo.hThread);		while (1) {		    if (GetExitCodeProcess(procInfo.hProcess, &status) == FALSE) {			break;		    }		    if (status != STILL_ACTIVE) {			break;		    }		    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) == TRUE) {			TranslateMessage(&msg);			DispatchMessage(&msg);		    }		}		*pidPtr = (Tcl_Pid) procInfo.hProcess;		if (*pidPtr != 0) {		    ProcInfo *procPtr = (ProcInfo *) ckalloc(sizeof(ProcInfo));		    procPtr->hProcess = procInfo.hProcess;		    procPtr->dwProcessId = procInfo.dwProcessId;		    procPtr->nextPtr = procList;		    procList = procPtr;		}		result = TCL_OK;	    }	}	if (result != TCL_OK) {	    TclWinConvertError(GetLastError());	    Tcl_AppendResult(interp, "couldn't execute \"", originalName,		    "\": ", Tcl_PosixError(interp), (char *) NULL);	}	end32s:	if (outputHandle != INVALID_HANDLE_VALUE) {	    /*	     * Now copy stuff from temp file to actual output handle. Don't	     * close outputHandle because it is associated with the output	     * file owned by the caller.	     */	    h = CreateFile(outputFileName, GENERIC_READ, 0, NULL, OPEN_ALWAYS,		    0, NULL);	    if (h != INVALID_HANDLE_VALUE) {		CopyChannel(outputHandle, h);	    }	    CloseHandle(h);	}	if (inputFileName == Tcl_DStringValue(&inputTempFile)) {	    DeleteFile(inputFileName);	}		if (outputFileName == Tcl_DStringValue(&outputTempFile)) {	    DeleteFile(outputFileName);	}	Tcl_DStringFree(&inputTempFile);	Tcl_DStringFree(&outputTempFile);        Tcl_DStringFree(&cmdLine);	return result;    }    hProcess = GetCurrentProcess();    /*     * STARTF_USESTDHANDLES must be used to pass handles to child process.     * Using SetStdHandle() and/or dup2() only works when a console mode      * parent process is spawning an attached console mode child process.     */    ZeroMemory(&startInfo, sizeof(startInfo));    startInfo.cb = sizeof(startInfo);    startInfo.dwFlags   = STARTF_USESTDHANDLES;    startInfo.hStdInput	= INVALID_HANDLE_VALUE;    startInfo.hStdOutput= INVALID_HANDLE_VALUE;    startInfo.hStdError = INVALID_HANDLE_VALUE;    secAtts.nLength = sizeof(SECURITY_ATTRIBUTES);    secAtts.lpSecurityDescriptor = NULL;    secAtts.bInheritHandle = TRUE;    /*     * We have to check the type of each file, since we cannot duplicate      * some file types.       */    inputHandle = INVALID_HANDLE_VALUE;    if (inputFile != NULL) {	filePtr = (WinFile *)inputFile;	if (filePtr->type == WIN_FILE) {	    inputHandle = filePtr->handle;	}    }    outputHandle = INVALID_HANDLE_VALUE;    if (outputFile != NULL) {	filePtr = (WinFile *)outputFile;	if (filePtr->type == WIN_FILE) {	    outputHandle = filePtr->handle;	}    }    errorHandle = INVALID_HANDLE_VALUE;    if (errorFile != NULL) {	filePtr = (WinFile *)errorFile;	if (filePtr->type == WIN_FILE) {	    errorHandle = filePtr->handle;	}    }    /*     * Duplicate all the handles which will be passed off as stdin, stdout     * and stderr of the child process. The duplicate handles are set to     * be inheritable, so the child process can use them.     */    if (inputHandle == INVALID_HANDLE_VALUE) {	/* 	 * If handle was not set, stdin should return immediate EOF.	 * Under Windows95, some applications (both 16 and 32 bit!) 	 * cannot read from the NUL device; they read from console	 * instead.  When running tk, this is fatal because the child 	 * process would hang forever waiting for EOF from the unmapped 	 * console window used by the helper application.	 *	 * Fortunately, the helper application detects a closed pipe 	 * as an immediate EOF and can pass that information to the 	 * child process.	 */	if (CreatePipe(&startInfo.hStdInput, &h, &secAtts, 0) != FALSE) {	    CloseHandle(h);	}    } else {	DuplicateHandle(hProcess, inputHandle, hProcess, &startInfo.hStdInput,		0, TRUE, DUPLICATE_SAME_ACCESS);    }    if (startInfo.hStdInput == INVALID_HANDLE_VALUE) {	TclWinConvertError(GetLastError());	Tcl_AppendResult(interp, "couldn't duplicate input handle: ",		Tcl_PosixError(interp), (char *) NULL);	goto end;    }    if (outputHandle == INVALID_HANDLE_VALUE) {	/*	 * If handle was not set, output should be sent to an infinitely 	 * deep sink.  Under Windows 95, some 16 bit applications cannot	 * have stdout redirected to NUL; they send their output to	 * the console instead.  Some applications, like "more" or "dir /p", 	 * when outputting multiple pages to the console, also then try and	 * read from the console to go the next page.  When running tk, this	 * is fatal because the child process would hang forever waiting	 * for input from the unmapped console window used by the helper	 * application.	 *	 * Fortunately, the helper application will detect a closed pipe	 * as a sink.	 */	if ((TclWinGetPlatformId() == VER_PLATFORM_WIN32_WINDOWS) 		&& (applType == APPL_DOS)) {	    if (CreatePipe(&h, &startInfo.hStdOutput, &secAtts, 0) != FALSE) {		CloseHandle(h);	    }	} else {	    startInfo.hStdOutput = CreateFile("NUL:", GENERIC_WRITE, 0,		    &secAtts, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);	}    } else {	DuplicateHandle(hProcess, outputHandle, hProcess, &startInfo.hStdOutput, 		0, TRUE, DUPLICATE_SAME_ACCESS);    }    if (startInfo.hStdOutput == INVALID_HANDLE_VALUE) {	TclWinConvertError(GetLastError());	Tcl_AppendResult(interp, "couldn't duplicate output handle: ",		Tcl_PosixError(interp), (char *) NULL);	goto end;    }    if (errorHandle == INVALID_HANDLE_VALUE) {	/*	 * If handle was not set, errors should be sent to an infinitely	 * deep sink.	 */	startInfo.hStdError = CreateFile("NUL:", GENERIC_WRITE, 0,		&secAtts, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);    } else {	DuplicateHandle(hProcess, errorHandle, hProcess, &startInfo.hStdError, 		0, TRUE, DUPLICATE_SAME_ACCESS);    }     if (startInfo.hStdError == INVALID_HANDLE_VALUE) {	TclWinConvertError(GetLastError());	Tcl_AppendResult(interp, "couldn't duplicate error handle: ",		Tcl_PosixError(interp), (char *) NULL);	goto end;    }    /*      * If we do not have a console window, then we must run DOS and     * WIN32 console mode applications as detached processes. This tells     * the loader that the child application should not inherit the     * console, and that it should not create a new console window for     * the child application.  The child application should get its stdio      * from the redirection handles provided by this application, and run     * in the background.     *     * If we are starting a GUI process, they don't automatically get a      * console, so it doesn't matter if they are started as foreground or     * detached processes.  The GUI window will still pop up to the     * foreground.     */    if (TclWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {	if (HasConsole()) {	    createFlags = 0;	} else if (applType == APPL_DOS) {	    /*	     * Under NT, 16-bit DOS applications will not run unless they	     * can be attached to a console.  If we are running without a	     * console, run the 16-bit program as an normal process inside	     * of a hidden console application, and then run that hidden	     * console as a detached process.	     */	    startInfo.wShowWindow = SW_HIDE;	    startInfo.dwFlags |= STARTF_USESHOWWINDOW;	    createFlags = CREATE_NEW_CONSOLE;	    Tcl_DStringAppend(&cmdLine, "cmd.exe /c ", -1);	} else {	    createFlags = DETACHED_PROCESS;	}     } else {	if (HasConsole()) {	    createFlags = 0;	} else {	    createFlags = DETACHED_PROCESS;	}		if (applType == APPL_DOS) {	    /*	     * Under Windows 95, 16-bit DOS applications do not work well 	     * with pipes:	     *	     * 1. EOF on a pipe between a detached 16-bit DOS application 	     * and another application is not seen at the other	     * end of the pipe, so the listening process blocks forever on 	     * reads.  This inablity to detect EOF happens when either a 	     * 16-bit app or the 32-bit app is the listener.  	     *	     * 2. If a 16-bit DOS application (detached or not) blocks when 	     * writing to a pipe, it will never wake up again, and it	     * eventually brings the whole system down around it.	     *	     * The 16-bit application is run as a normal process inside	     * of a hidden helper console app, and this helper may be run	     * as a detached process.  If any of the stdio handles is	     * a pipe, the helper application accumulates information 	     * into temp files and forwards it to or from the DOS 	     * application as appropriate.  This means that DOS apps 	     * must receive EOF from a stdin pipe before they will actually	     * begin, and must finish generating stdout or stderr before 	     * the data will be sent to the next stage of the pipe.	     *	     * The helper app should be located in the same directory as	     * the tcl dll.	     */	    if (createFlags != 0) {		startInfo.wShowWindow = SW_HIDE;		startInfo.dwFlags |= STARTF_USESHOWWINDOW;		createFlags = CREATE_NEW_CONSOLE;	    }	    Tcl_DStringAppend(&cmdLine, "tclpip" STRINGIFY(TCL_MAJOR_VERSION) 		    STRINGIFY(TCL_MINOR_VERSION) ".dll ", -1);	}    }        /*     * cmdLine gets the full command line used to invoke the executable,     * including the name of the executable itself.  The command line     * arguments in argv[] are stored in cmdLine separated by spaces.      * Special characters in individual arguments from argv[] must be      * quoted when being stored in cmdLine.     *     * When calling any application, bear in mind that arguments that      * specify a path name are not converted.  If an argument contains      * forward slashes as path separators, it may or may not be      * recognized as a path name, depending on the program.  In general,     * most applications accept forward slashes only as option      * delimiters and backslashes only as paths.     *     * Additionally, when calling a 16-bit dos or windows application,      * all path names must use the short, cryptic, path format (e.g.,      * using ab~1.def instead of "a b.default").       */    BuildCommandLine(argc, argv, &cmdLine);    if (!CreateProcess(NULL, Tcl_DStringValue(&cmdLine), NULL, NULL, TRUE, 	    createFlags, NULL, NULL, &startInfo, &procInfo)) {	TclWinConvertError(GetLastError());	Tcl_AppendResult(interp, "couldn't execute \"", originalName,		"\": ", Tcl_PosixError(interp), (char *) NULL);	goto end;    }    if (applType == APPL_DOS) {	WaitForSingleObject(hProcess, 50);    }    /*      * "When an application spawns a process repeatedly, a new thread      * instance will be created for each process but the previous      * instances may not be cleaned up.  This results in a significant      * virtual memory loss each time the process is spawned.  If there      * is a WaitForInputIdle() call between CreateProcess() and     * CloseHandle(), the problem does not occur." PSS ID Number: Q124121     */    WaitForInputIdle(procInfo.hProcess, 5000);    CloseHandle(procInfo.hThread);    *pidPtr = (Tcl_Pid) procInfo.hProcess;    if (*pidPtr != 0) {	ProcInfo *procPtr = (ProcInfo *) ckalloc(sizeof(ProcInfo));	procPtr->hProcess = procInfo.hProcess;	procPtr->dwProcessId = procInfo.dwProcessId;	procPtr->nextPtr = procList;	procList = procPtr;    }    result = TCL_OK;    end:    Tcl_DStringFree(&cmdLine);    if (startInfo.hStdInput != INVALID_HANDLE_VALUE) {        CloseHandle(startInfo.hStdInput);    }    if (startInfo.hStdOutput != INVALID_HANDLE_VALUE) {        CloseHandle(startInfo.hStdOutput);    }    if (startInfo.hStdError != INVALID_HANDLE_VALUE) {	CloseHandle(startInfo.hStdError);    }    return result;}/* *---------------------------------------------------------------------- * * HasConsole -- * *	Determines whether the current application is attached to a *	console. * * Results: *	Returns TRUE if this application has a console, else FALSE. * * Side effects: *	None. * *---------------------------------------------------------------------- */static BOOLHasConsole(){    HANDLE handle = CreateFile("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE,	    NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);    if (handle != INVALID_HANDLE_VALUE) {        CloseHandle(handle);	return TRUE;    } else {        return FALSE;    }}/* *-------------------------------------------------------------------- * * ApplicationType -- * *	Search for the specified program and identify if it refers to a DOS, *	Windows 3.X, or Win32 program.  Used to determine how to invoke  *	a program, or if it can even be invoked. * *	It is possible to almost positively identify DOS and Windows  *	applications that contain the appropriate magic numbers.  However,  *	DOS .com files do not seem to contain a magic number; if the program  *	name ends with .com and could not be identified as a Windows .com *	file, it will be assumed to be a DOS application, even if it was *	just random data.  If the program name does not end with .com, no  *	such assumption is made. * *	The Win32 procedure GetBinaryType incorrectly identifies any  *	junk file that ends with .exe as a dos executable and some  *	executables that don't end with .exe as not executable.  Plus it  *	doesn't exist under win95, so I won't feel bad about reimplementing *	functionality. * * Results:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -