📄 stioinit.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/***
* stioinit.c - Init that is ONLY pulled in if CORSTIOA or CORESTIOW
* components are selected
*
*
*Purpose:
* Init code for all the STDIO functionality in CE
*
*******************************************************************************/
#include <cruntime.h>
#include <crtmisc.h>
#include <internal.h>
#include <malloc.h>
#include <mtdll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <crttchar.h>
#include <dbgint.h>
#include <msdos.h>
#include <coredll.h>
#include <console.h>
extern FARPROC pfnTermStdio;
// This data should NOT be pulled in in the STR-only version
// Other Locks
CRITICAL_SECTION csIobScanLock; // used to lock entire __piob array
// This is the basic structure of the STDIO/buffered IO portion
// of the library. The FILE handle apps get are actualy FILEX ptrs
// This array grows dynamically in increments of NSTREAM_INCREMENT
FILEX** __piob; // pointer to an array of ptrs to FILEX*
int _nstream; // Current length of the __piob array.
// Console globals. Initialized on access to the console handles stdin/out/err
// (if they havn't been redirected). Access to these is protected by the
// csStdioInitLock both at Init and later in OpenStdConsole & LowioTerm
HANDLE hConsoleDevice;
int iConsoleNumber;
HANDLE hCOMPort = INVALID_HANDLE_VALUE;
HMODULE hCoreDll = NULL;
tGetCommState fGetCommState = NULL;
tSetCommState fSetCommState = NULL;
tSetCommTimeouts fSetCommTimeouts = NULL;
tGetCommTimeouts fGetCommTimeouts = NULL;
// Value of regkey we read to decide whether to redirect console to COMx: or debugout
int iConsoleRedir;
DWORD dwCOMSpeed;
// functions decalred in this file
void __cdecl ConsoleRedirInit(void);
int __cdecl TermStdio(void);
BOOL __cdecl InitPiob(void);
void __cdecl TermPiob(void);
void __cdecl MarkConsoleForDereg(void);
BOOL __cdecl LowioInit(void);
void __cdecl LowioTerm(void);
int __cdecl _real_filbuf2(FILEX *str, int fWide);
int __cdecl _real_flsbuf2(int ch,FILEX *str, int fWide);
int __cdecl _InitStdioLib(void)
{
// already inside csStdioInitLock
DEBUGMSG (DBGSTDIO, (TEXT("Stdio: STDIO is being INITED\r\n")));
// Init the rest of the locks
InitializeCriticalSection(&csIobScanLock);
if(!LowioInit())
return FALSE;
// setup __piob array & init stdin/out/err FILEX structs. Must be last
if(!InitPiob())
return FALSE;
// Init for the str-only library
_pfnfilbuf2 = _real_filbuf2;
_pfnflsbuf2 = _real_flsbuf2;
// setup cleanup function pointer
pfnTermStdio = TermStdio;
return TRUE;
}
/*
* Cleanup
*/
int __cdecl TermStdio(void)
{
EnterCriticalSection(&csStdioInitLock);
if(!fStdioInited) goto done;
// we can't do a real deregister due to possibel deadlock
// so we've added this IOCTL hack. Do this before TermPiob
MarkConsoleForDereg();
TermPiob(); // flush & close all stream & free __piob. Must be called *before* LowioTerm
LowioTerm(); // DeRegister our console device if any
DeleteCriticalSection(&csIobScanLock);
fStdioInited = FALSE;
done:
LeaveCriticalSection(&csStdioInitLock);
return 0;
}
/***
* InitPiob
* Create and initialize the __piob array.
*******************************************************************************/
BOOL __cdecl InitPiob(void)
{
int i;
// We are inside the csInitStdioLock critsec
_nstream = INITIAL_NSTREAM;
if(!(__piob = (FILEX**)_malloc_crt(_nstream * sizeof(FILEX*))))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
memset(__piob, 0, (_nstream * sizeof(FILEX*)));
// Initialize the stdin/out/err handles
for ( i = 0 ; i < 3 ; i++ )
{
// allocate a new _FILEX, set _piob[i] to it and return a pointer to it.
if(!(__piob[i] = _malloc_crt(sizeof(_FILEX))))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
memset(__piob[i], 0, sizeof(_FILEX));
InitializeCriticalSection( &(__piob[i]->lock) );
__piob[i]->fd = i;
__piob[i]->osfhnd = INVALID_HANDLE_VALUE;
__piob[i]->peekch = '\n';
// These have been initialize them with invalid handles. When anyone tries actual
// IO to these handles we'll catch them & open the console then
// however these must be set like it's all A-OK
__piob[i]->osfile = (BYTE)(FTEXT|FDEV|FOPEN);
__piob[i]->_flag = ((i==0) ? _IOREAD : _IOWRT);
}
return TRUE;
}
/***
* TermPiob
*
* (1) Flush all streams. (Do this even if we're going to
* call fcloseall since that routine won't do anything to the
* std streams.)
*
* (2) If returning to caller, close all streams. This is
* not necessary if the exe is terminating because the OS will
* close the files for us (much more efficiently, too).
*
*******************************************************************************/
void __cdecl TermPiob(void)
{
// We are inside the csInitStdioLock critsec
// flush all streams
_flushall();
_fcloseall();
}
BOOL __cdecl LowioInit(void)
{
// We are inside the csInitStdioLock critsec
// Read the console-redir registry key
ConsoleRedirInit();
// but don't do anything else with the console YET
hConsoleDevice = NULL;
iConsoleNumber = -1;
hCOMPort = INVALID_HANDLE_VALUE;
return TRUE;
}
void __cdecl MarkConsoleForDereg(void)
{
int i;
DWORD dwDummy;
// NOTE: This IOCTL is here to avoid a deadlock between (a) us being in our
// DllMain calling DeregisterDevice (and hence trying to acquire the device
// CS *after* the loader CS and (b) Various other devices which acquire the
// device CS *before* the Loader CS (by calling LoadLib, FreeLib etc inside
// the device fns etc). See #4165.
// IOCTL call has to be on a *file* handle, not a device handle, so we try
// all 3 of stdin, out & err
if(hConsoleDevice)
{
for(i=0; i<3; i++)
{
if(__piob[i]->osfhnd != INVALID_HANDLE_VALUE)
DeviceIoControl(__piob[i]->osfhnd, IOCTL_DEVICE_AUTODEREGISTER, NULL, 0, NULL, 0, &dwDummy, NULL);
}
hConsoleDevice = NULL;
iConsoleNumber = -1;
}
}
void __cdecl LowioTerm(void)
{
// does nothing now
}
/*------------------------------------------------------------
* This function is called from LowioInit() to just read the
* Console redirect registry key. No action is taken based on
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -