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

📄 stioinit.c

📁 不错的东西 请查看 WINCE OS
💻 C
📖 第 1 页 / 共 2 页
字号:
 * 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 + -