📄 stioinit.c
字号:
* this, as yet.
-------------------------------------------------------------*/
// constant regkey names
const WCHAR wszKey[] = TEXT("Drivers\\Console");
const WCHAR wszValName[] = TEXT("OutputTo");
const WCHAR wszSpeedValName[] = TEXT("COMSpeed");
void __cdecl ConsoleRedirInit(void)
{
HKEY hkey = NULL;
DWORD dwType, dwLen;
int iRedir;
// We are inside the csInitStdioLock critsec
iConsoleRedir = 0;
if(ERROR_SUCCESS != RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszKey, 0, KEY_READ, &hkey))
goto noredir;
dwLen=sizeof(iRedir);
if(ERROR_SUCCESS != RegQueryValueExW(hkey, wszValName, NULL, &dwType, (PBYTE)&iRedir, &dwLen))
goto noredir;
if(dwType!=REG_DWORD || dwLen!=sizeof(DWORD) || iRedir<(-1) || iRedir==0 || iRedir>=10)
goto noredir;
if(iRedir>0)
{
dwLen=sizeof(dwCOMSpeed);
if(ERROR_SUCCESS != RegQueryValueExW(hkey, wszSpeedValName, NULL, &dwType, (PBYTE)&dwCOMSpeed, &dwLen))
dwCOMSpeed = 19600;
}
iConsoleRedir = iRedir;
#ifdef DEBUG
if(iConsoleRedir==(-1))
DEBUGMSG(1, (TEXT("Console redirected to DEBUG for process 0x%X\r\n"), GetCurrentProcessId()));
else
DEBUGMSG(1, (TEXT("Console redirected to COM%d for process 0x%X\r\n"), iConsoleRedir, GetCurrentProcessId()));
#endif
if(hkey) RegCloseKey(hkey);
return;
noredir:
DEBUGMSG(1, (TEXT("Console NOT redirected for process 0x%X\r\n"), GetCurrentProcess()));
if(hkey) RegCloseKey(hkey);
return;
}
/*----------------------------------------------------------------
* This function is called from _get_osfhandle when someone tries to access
* file handles 0, 1 or 2, but there's no OS file handle behind it.
* We first figure out where we want the console I/O to go
*
* If to debugport then //NYI//this function always returns a special value of (-2)
* which is interpreted by our MyReadFile & MyWriteFile etc macros//NYI//
*
* If to COM port then we try to open the specifid COM port
*
* If to Console, then first try to Register the console device if not already
* done, and then try to open the device
*----------------------------------------------------------------*/
// macro used to map 0, 1 and 2 to right value for call to GetStdHandle
#define stdaccess(fh) ((fh==0) ? GENERIC_READ : GENERIC_WRITE)
#define stdshare(fh) (FILE_SHARE_READ | FILE_SHARE_WRITE)
#define stdcreat(fh, d) (((d) || (fh==0)) ? OPEN_EXISTING : OPEN_ALWAYS)
HANDLE __cdecl OpenStdConsole(int fh)
{
WCHAR szDevName[] = TEXT("COXX:");
WCHAR szTempPath[MAX_PATH];
DWORD dwLen = MAX_PATH;
HANDLE hFile = INVALID_HANDLE_VALUE;
DEBUGMSG (DBGSTDIO, (TEXT("Stdio: OpenStdConsole(%d)\r\n"), fh));
_ASSERTE(fh>=0 && fh<=2);
// This function is NOT called on init, so we are NOT inside any global critsecs
// However we should be inside the lock for the *current* FILEX struct
// First try to get inherited stdin/out/err "handle" if any
if(GetStdioPathW(fh, szTempPath, &dwLen) && dwLen && szTempPath[0])
{
// check if it's a device or file
BOOL fDev = (lstrlen(szTempPath)==5 && szTempPath[4]==':');
DEBUGMSG (DBGSTDIO, (TEXT("Stdio: OpenStdConsole(%d)--inherited path(%s) l=%d dev=%d\r\n"), fh, szTempPath, dwLen, fDev));
// open with approp modes based on fh & fDev
hFile = CreateFile(szTempPath, stdaccess(fh), stdshare(fh), NULL, stdcreat(fh, fDev), 0, NULL);
if(INVALID_HANDLE_VALUE != hFile)
{
// set up new inheritance
SetStdioPathW(fh, szTempPath);
// if not a device, turn off FDEV bit
if(!fDev)
{
_osfile(fh) &= (char)(~FDEV);
if (fh != 0) // Write at the end, but read at the beginning.
SetFilePointer (hFile, 0, NULL, FILE_END);
}
goto done;
}
// else fall thru
}
DEBUGMSG (DBGSTDIO, (TEXT("Stdio: OpenStdConsole(%d)--FAILED to inherit path\r\n"), fh));
// Didnt inherit. Check for redir & open new console if neccesary
if(iConsoleRedir==0)
{
// Not redirected
if(!hConsoleDevice)
{
// Try to register a unique console device
int i;
EnterCriticalSection(&csStdioInitLock); // get the init critsec
for(i=1; i<10; i++)
{
if(hConsoleDevice = RegisterDevice_Trap(L"CON", i, L"console.dll", 0))
{
DEBUGMSG (DBGSTDIO, (TEXT("Stdio: OpenStdConsole(%d)--Registered Console %d\r\n"), fh, i));
iConsoleNumber = i;
break;
}
}
LeaveCriticalSection(&csStdioInitLock);
}
if(hConsoleDevice)
{
DEBUGMSG (DBGSTDIO, (TEXT("Stdio: OpenStdConsole(%d)--Opening Console %d\r\n"), fh, iConsoleNumber));
szDevName[2] = 'N';
szDevName[3] = '0'+iConsoleNumber;
hFile = CreateFile(szDevName, stdaccess(fh), stdshare(fh), NULL, OPEN_EXISTING, 0, NULL);
// set up new inheritance
if(INVALID_HANDLE_VALUE != hFile)
SetStdioPathW(fh, szDevName);
}
}
else if(iConsoleRedir == (-1)) // Debug port
{
DEBUGMSG (DBGSTDIO, (TEXT("Stdio: OpenStdConsole(%d)--Redirected to DEBUG\r\n"), fh));
hFile = (HANDLE)(-2);
}
else // COM port
{
if (! hCoreDll)
hCoreDll = LoadLibrary (L"coredll.dll");
if (hCoreDll)
{
if (! fGetCommTimeouts)
fGetCommTimeouts = (tGetCommTimeouts)GetProcAddress (hCoreDll, L"GetCommTimeouts");
if (! fSetCommTimeouts)
fSetCommTimeouts = (tSetCommTimeouts)GetProcAddress (hCoreDll, L"SetCommTimeouts");
if (! fGetCommState)
fGetCommState = (tGetCommState)GetProcAddress (hCoreDll, L"GetCommState");
if (! fSetCommState)
fSetCommState = (tSetCommState)GetProcAddress (hCoreDll, L"SetCommState");
}
// The Serial driver doesn't like to opened multiply even if in
// mutually compatible R/W modes (for stdin & stdout).
// So we open it just once with R & W access and cache the handle.
if(INVALID_HANDLE_VALUE!=hCOMPort)
{
DEBUGMSG (DBGSTDIO, (TEXT("Stdio: OpenStdConsole(%d)--RE-USING COM %d\r\n"), fh, iConsoleRedir));
hFile = hCOMPort;
}
else if (fGetCommTimeouts && fSetCommTimeouts && fGetCommState && fSetCommState)
{
DEBUGMSG (DBGSTDIO, (TEXT("Stdio: OpenStdConsole(%d)--Opening COM %d\r\n"), fh, iConsoleRedir));
szDevName[2] = 'M';
szDevName[3] = '0'+iConsoleRedir;
hFile = CreateFile(szDevName, GENERIC_READ|GENERIC_WRITE, stdshare(fh), NULL, OPEN_EXISTING, 0, NULL);
// cache the handle & set up new inheritance
// also set Comm settings
if(INVALID_HANDLE_VALUE != hFile)
{
COMMTIMEOUTS CommTimeouts;
DCB dcb;
hCOMPort = hFile;
SetStdioPathW(fh, szDevName);
if(fGetCommTimeouts(hFile, &CommTimeouts))
{
CommTimeouts.ReadIntervalTimeout = 100; // Want SMALL number here
CommTimeouts.ReadTotalTimeoutConstant = 1000000; // Want LARGE number here
fSetCommTimeouts(hFile, &CommTimeouts);
}
if(fGetCommState(hFile, &dcb))
{
dcb.BaudRate = dwCOMSpeed;
fSetCommState(hFile, &dcb);
}
}
}
}
done:
_osfhnd(fh) = hFile;
DEBUGMSG (DBGSTDIO, (TEXT("Stdio: OpenStdConsole(%d)--returning(%x)\r\n"), fh, hFile));
return _osfhnd(fh);
}
/*
* This functions has nothing to do with init, but it's in need of a good home
* It translates the stdin/stdout/stderr external macros to FILE handles
*
*/
FILE* __cdecl _getstdfilex(int i)
{
if(!CheckStdioInit())
return NULL;
return (FILE*)__piob[i];
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -