📄 tmman32.c
字号:
/*
tmman32.dll
provides services to Win32 clients for communicating with the DSP.
HISTORY
960417 TR Created
960620 TR Started changes for release candicate 3.
961015 TR Adding ArgC & ArgV support to tmDSpLoadExecutable
*/
#include "windows.h"
#include "tmwincom.h"
#include "tmman32.h"
#include "tmif.h"
#include "tmmain.h"
#include "cqueue.h"
#include "verinfo.h"
#include "stdio.h"
//#undef USE_LOADERCOPY
#define USE_LOADERCOPY
#include "TMDownLoader.h"
#include "TMObj.h"
#define DEFAULT_WINDOW_SIZE 50
TMMAN_GLOBAL Global;
CHAR szTemp[0x80];
//-----------------------------------------------------------------------------
// PROTOTYPES
//-----------------------------------------------------------------------------
DWORD WINAPI MsgRecvThread ( PVOID pvContext );
BOOL WINAPI tmmanControlHandler ( DWORD dwCtrlType );
BOOL tmDSPInterrupt ( PVOID pObject, DWORD dwCommand );
BOOL halValidateAddress ( PTMSTD_MEMORY_BLOCK pMem, DWORD dwAddress );
BOOL halValidateLength ( PTMSTD_MEMORY_BLOCK pMem, DWORD dwAddress,
DWORD dwLength );
VOID ErrorBox ( PCHAR pszErrorString );
//-----------------------------------------------------------------------------
// TMMAN SUPPORTING FUNCTIONS
//-----------------------------------------------------------------------------
BOOL WINAPI DLLInitialize ( PVOID DllHandle, DWORD dwReason,
PVOID pvContext )
{
DWORD dwBytesReturned;
TMIF_REGISTERCLIENT Client;
TMIF_STRUCT_NEGOTIATEVERSION Version;
DWORD dwWindowsVersion, dwWindowsMajorVersion, dwWindowsMinorVersion;
switch ( dwReason )
{
case DLL_PROCESS_ATTACH :
dwWindowsVersion = GetVersion();
// Get major and minor version numbers of Windows
dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwWindowsVersion)));
dwWindowsMinorVersion = (DWORD)(HIBYTE(LOWORD(dwWindowsVersion)));
// Get build numbers for Windows NT or Win32s
if (dwWindowsVersion < 0x80000000) // Windows NT
{
wsprintf ( szTemp,
"tmman32:DLLInitialize:NTOS:NOT SUPPORTED\n" );
OutputDebugString ( szTemp );
ErrorBox ( "NTOS : NOT SUPPORTED" );
return FALSE;
}
else // should be 95 or Win32s
{
if (dwWindowsMajorVersion < 4) // Win32s
{
wsprintf ( szTemp,
"tmman32:DLLInitialize:Win32s:NOT SUPPORTED\n" );
OutputDebugString ( szTemp );
ErrorBox ( "Win32s : NOT SUPPORTED" );
return FALSE;
}
}
wsprintf ( szTemp, "\ntmman32:Version[%d.%d.%d]\n",
verGetFileMajorVersion(),
verGetFileMinorVersion(),
verGetFileBuildVersion() );
OutputDebugString ( szTemp );
// initialize the values for PROCES_DETACH
Global.hDevice = INVALID_HANDLE_VALUE;
Global.hEvent = INVALID_HANDLE_VALUE;
Global.hThread = INVALID_HANDLE_VALUE;
Global.dwClientHandle = 0;
Global.dwThreadID = 0;
Global.pvAdvisoryQueue = NULL;
Global.pOverlapped = NULL;
//InitializeCriticalSection ( &Global.ISRMonitor );
if ( ( Global.hDevice =
CreateFile ( "\\\\.\\vtmman.vxd",0,0,0, CREATE_NEW ,
FILE_FLAG_DELETE_ON_CLOSE | FILE_FLAG_OVERLAPPED,
0 ) ) == INVALID_HANDLE_VALUE )
{
wsprintf ( szTemp,
"tmman32:DLLInitialize:CreateFile:vtmman.vxd:FAIL[%x]\n",
GetLastError() );
OutputDebugString ( szTemp );
ErrorBox ( "CreateFile Failed [vtmman.vxd]" );
return FALSE;
}
Version.Version.dwMajor = verGetFileMajorVersion();
Version.Version.dwMinor = verGetFileMinorVersion();
// perform the version control
if ( DeviceIoControl ( Global.hDevice,
(DWORD)(TMIF_DIOC_NEGOTIATEVERSION),
(PVOID)&Version, sizeof (TMIF_STRUCT_NEGOTIATEVERSION),
(PVOID)&Version, sizeof (TMIF_STRUCT_NEGOTIATEVERSION),
&dwBytesReturned, NULL ) != TRUE )
{
/* this will fail if vxd does not support negotiate version */
wsprintf ( szTemp,
"tmman32:DLLInitialize:DeviceIoControl:NEGOTIATEVERSION:FAIL[%x]\n",
GetLastError() );
OutputDebugString ( szTemp );
ErrorBox ( "Obsolete Version of [vtmman.vxd]" );
return FALSE;
}
if ( Version.Status != TMOK )
{
wsprintf ( szTemp,
"tmman32:DLLInitialize:NEGOTIATEVERSION:FAIL[%x]\n", Version.Status );
OutputDebugString ( szTemp );
ErrorBox ( "Obsolete Version of [tmman32.dll]" );
return FALSE;
}
if ( ( Version.Version.dwMajor < verGetFileMajorVersion() ) ||
( Version.Version.dwMinor < verGetFileMinorVersion()) )
{
OutputDebugString(
"tmman32:DLLInitialize:VersionCheck:vtmman.vxd:FAIL\n");
ErrorBox ( "Obsolete Version of [vtmman.vxd]" );
return FALSE;
}
// register this client with the VxD, ensure that Global is a
// per-instance data structure
if ( ( Global.hEvent =
CreateEvent ( 0, TRUE , 0, NULL )) == NULL )
{
wsprintf ( szTemp,
"tmman32:DLLInitialize:CreateEvent:FAIL[%x]\n",
GetLastError() );
OutputDebugString ( szTemp );
ErrorBox ( "CreateEvent Failed" );
return FALSE;
}
Client.dwModuleHandle = (DWORD)GetModuleHandle ("tmman32");
if ( DeviceIoControl ( Global.hDevice,
(DWORD)(TMIF_DIOC_REGISTERCLIENT),
(PVOID)&Client, sizeof ( TMIF_REGISTERCLIENT ),
(PVOID)&Client, sizeof ( TMIF_REGISTERCLIENT ),
&dwBytesReturned, NULL ) != TRUE)
{
wsprintf ( szTemp,
"tmman32:DLLInitialize:DeviceIoControl:REGISTERCLIENT:FAIL[%x]\n",
GetLastError() );
OutputDebugString ( szTemp );
ErrorBox ( "DeviceIOControl Register Client Failed" );
return FALSE;
}
if ( Client.Status != TMOK )
{
wsprintf ( szTemp,
"tmman32:DLLInitialize:REGISTERCLIENT:FAIL[%x]\n",
Client.Status );
OutputDebugString ( szTemp );
ErrorBox ( "Register Cleint Failed : Too Many Processes Using TMMan" );
return FALSE;
}
// store the info returnd by the Ring 0 driver
Global.dwClientHandle = Client.dwClientHandle;
Global.pOverlapped = Client.pvOverlapped;
Global.pvAdvisoryQueue = Client.pvAdvisoryQueue;
// store the event handle in the overlapped object that
// can be used later for blocking and signalling the thread.
// NOTE : a ring 3 app is acessing kernel address space - NT ??
// possible in NT via ZwMappedViewOfSectionXXX
Global.pOverlapped->hEvent = Global.hEvent;
if ( SetConsoleCtrlHandler ( tmmanControlHandler , TRUE ) != TRUE )
{
wsprintf ( szTemp,
"tmman32:DLLInitialize:SetConsoleCtrlHandler:FAIL[%x]\n",
GetLastError() );
OutputDebugString ( szTemp );
ErrorBox ( "SetConsoleCtrlHandler Failed" );
return FALSE;
}
if ( ( Global.hThread =
CreateThread ( NULL,0, MsgRecvThread, &Global,
0,
&Global.dwThreadID ) ) == NULL )
{
wsprintf ( szTemp,
"tmman32:DLLInitialize:CreateThread:FAIL[%x]\n",
GetLastError() );
OutputDebugString ( szTemp );
ErrorBox ( "CreateThread Failed" );
return FALSE;
}
break;
case DLL_PROCESS_DETACH :
//DeleteCriticalSection ( &Global.ISRMonitor );
OutputDebugString("1111111111111111\n\r");
// terminate thread
Global.fTerminateThread = TRUE;
if ( Global.hEvent )
{
PulseEvent ( Global.hEvent );
}
//remove the console handler
SetConsoleCtrlHandler ( tmmanControlHandler, FALSE );
if ( Global.dwClientHandle != 0 )
{
// unregister the client with the VxD.
if ( DeviceIoControl ( Global.hDevice,
(DWORD)(TMIF_DIOC_UNREGISTERCLIENT),
(PVOID)&Global.dwClientHandle, sizeof ( DWORD ),
(PVOID)NULL, 0,
&dwBytesReturned, NULL ) != TRUE)
{
return FALSE;
}
}
// release the thread object
if ( Global.hDevice != INVALID_HANDLE_VALUE )
{
DWORD dwExitCode;
//***This will terminate the thread properly
while (!GetExitCodeThread(Global.hThread,&dwExitCode));
TerminateThread(Global.hThread, dwExitCode);
CloseHandle ( Global.hThread );
}
// release the event
if ( Global.hEvent != INVALID_HANDLE_VALUE )
{
CloseHandle ( Global.hEvent );
}
// release the VxD
if ( Global.hDevice != INVALID_HANDLE_VALUE)
{
CloseHandle ( Global.hDevice );
}
#if 0
if ( (Global.hThread != NULL))
{
DWORD dwExitCode;
while (!GetExitCodeThread(Global.hThread,&dwExitCode));
TerminateThread(Global.hThread, dwExitCode);
CloseHandle(Global.hThread);
}
#endif
break;
case DLL_THREAD_ATTACH :
break;
case DLL_THREAD_DETACH :
break;
}
return TRUE;
}
/*
MsgRecvThread
This thread waits on an event to be set by the VxD.
When the event is set it calls the respective tasks advisory notification
function. A single instance of TMMAN may be loaded to deal with several
tasks. For all these will signal the same event on the occurace of all
events. Hence this function has to perform routing of the advisory
callback to the right owner.
To pass information from the VxD to Ring 3, at the time of client
registration, the VxD allocates a buffer in linear address space, this
buffer can be accessed by the VxD and Ring 3 at callback time. However
this approach is not portable over NT.
*/
DWORD WINAPI MsgRecvThread ( PVOID pvContext )
{
DWORD dwBytesReturned;
BOOL fInterruptPeer = FALSE;
DWORD dwInterruptCommand = 0;
TMIF_ADVISORY_REQUEST Advise;
PTMIF_ADVISORY_REQUEST pAdvise = &Advise;
OutputDebugString ("tmman32:MsgRecvThread:Started\n");
SetThreadPriority ( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL );
while ( ! Global.fTerminateThread )
{
// this call should result in an ERROR_IO_PENDING status
DeviceIoControl ( Global.hDevice, (DWORD)(TMIF_DIOC_BLOCKONADVISE),
(PVOID)&Global.dwClientHandle, sizeof( DWORD) ,
(PVOID)NULL, 0,
&dwBytesReturned, Global.pOverlapped );
GetOverlappedResult( Global.hDevice, Global.pOverlapped,
&dwBytesReturned, TRUE );
if ( Global.fTerminateThread )
break;
// ignore this comment TR960812
// after the device io ctrl call pAdvise points to the ring0
// tmif allocated advise request structure that completely encapsulates
// all the information requried to perform the callback.
// main processing code starts here
//pTask = (PTMMAN_TASK_STRUCT)pAdvise->pvTaskContext;
// retrieve all items from the Advisory queue and make the callbacks.
while ( ! cqueueIsEmpty ( Global.pvAdvisoryQueue ) )
{
cqueueDelete ( Global.pvAdvisoryQueue, pAdvise );
if ( pAdvise->dwCallback )
{
( (TMMAN_ADVISORY_NOTIFICATION)pAdvise->dwCallback ) (
pAdvise->dwMessage, pAdvise->dwObjHandle,
pAdvise->pContext, &pAdvise->Packet );
}
else
{
wsprintf(szTemp,
"\ntmman32:pAdvise->dwCallback != NULL:FAIL\n" );
OutputDebugString( szTemp);
}
}
}
OutputDebugString ("\ntmman32:MsgRecvThread:Exiting");
return TMOK;
}
BOOL WINAPI tmmanControlHandler ( DWORD dwCtrlType )
{
wsprintf ( szTemp, "\ntmman32:tmmanControlHandler [%x]\n", dwCtrlType );
OutputDebugString ( szTemp );
switch ( dwCtrlType )
{
case CTRL_C_EVENT :
case CTRL_BREAK_EVENT :
case CTRL_CLOSE_EVENT :
case CTRL_LOGOFF_EVENT :
case CTRL_SHUTDOWN_EVENT :
Global.fTerminateThread = TRUE;
SetEvent ( Global.hEvent );
break;
}
return FALSE;
}
//-----------------------------------------------------------------------------
// API IMPLEMENTATION
//-----------------------------------------------------------------------------
// DSP related API.
STATUS tmNegotiateVersion ( DWORD dwModuleID, PTMSTD_VERSION_INFO pVersion )
{
STATUS Status = TMOK;
TMIF_STRUCT_NEGOTIATEVERSION TMIF;
TMSTD_VERSION_INFO ReturnedVersion;
DWORD dwBytesReturned;
switch ( dwModuleID )
{
case TMMAN_MODULE_HOST_TMMAN32 :
case TMMAN_DEFAULT :
ReturnedVersion.dwMajor = verGetFileMajorVersion();
ReturnedVersion.dwMinor = verGetFileMinorVersion();
ReturnedVersion.dwBuild = verGetFileBuildVersion();
if ( pVersion->dwMajor < verGetFileMajorVersion() )
{
Status = TM_STATUS ( TMMAN32_ERR_MAJVERSIONERROR );
goto tmNegotiateVersionExit1;
}
if ( pVersion->dwMinor < verGetFileMinorVersion() )
{
Status = TM_STATUS ( TMMAN32_ERR_MINVERSIONERROR );
goto tmNegotiateVersionExit1;
}
break;
case TMMAN_MODULE_HOST_VTMMAN :
case TMMAN_MODULE_DSP_TMMAN :
TMIF.Version.dwMajor = pVersion->dwMajor;
TMIF.Version.dwMinor = pVersion->dwMinor;
TMIF.Version.dwBuild = pVersion->dwBuild;
TMIF.ModuleID = dwModuleID;
// perform the version control
if ( DeviceIoControl ( Global.hDevice,
(DWORD)(TMIF_DIOC_NEGOTIATEVERSION),
(PVOID)&TMIF, sizeof (TMIF_STRUCT_NEGOTIATEVERSION),
(PVOID)&TMIF, sizeof (TMIF_STRUCT_NEGOTIATEVERSION),
&dwBytesReturned, NULL ) != TRUE )
{
Status = TM_STATUS ( TMMAN32_ERR_DEVIOCTLFAIL );
}
else
{
Status = TMIF.Status;
}
ReturnedVersion.dwMajor = TMIF.Version.dwMajor;
ReturnedVersion.dwMinor = TMIF.Version.dwMinor;
ReturnedVersion.dwBuild = TMIF.Version.dwBuild;
break;
default :
Status = TM_STATUS ( TMMAN32_ERR_UNKNOWNCOMPONENT );
break;
}
tmNegotiateVersionExit1:
pVersion->dwMajor = ReturnedVersion.dwMajor;
pVersion->dwMinor = ReturnedVersion.dwMinor;
pVersion->dwBuild = ReturnedVersion.dwBuild;
return Status;
}
STATUS tmDSPGetNum ( PDWORD DSPCount )
{
TMIF_STRUCT_DSPGETNUM TMIF;
DWORD BytesReturned;
TMIF.ClientHandle = Global.dwClientHandle;
if ( DeviceIoControl ( Global.hDevice, (DWORD)(TMIF_DIOC_DSPGETNUM),
(PVOID)&TMIF, sizeof( TMIF_STRUCT_DSPGETNUM) ,
(PVOID)&TMIF, sizeof( TMIF_STRUCT_DSPGETNUM) ,
&BytesReturned, NULL ) != TRUE )
{
return TM_STATUS ( TMMAN32_ERR_DEVIOCTLFAIL );
}
*DSPCount = TMIF.DSPCount;
return TMIF.Status;
}
STATUS tmDSPGetCaps ( DWORD dwHandle, PTMMAN_DSP_CAPS DSPCaps )
{
TMIF_STRUCT_DSPGETCAPS TMIF;
DWORD BytesReturned;
TMIF.ClientHandle = Global.dwClientHandle;
TMIF.DSPHandle = dwHandle;
if ( DeviceIoControl ( Global.hDevice, (DWORD)(TMIF_DIOC_DSPGETCAPS),
(PVOID)&TMIF, sizeof( TMIF_STRUCT_DSPGETCAPS) ,
(PVOID)&TMIF, sizeof( TMIF_STRUCT_DSPGETCAPS) ,
&BytesReturned, NULL ) != TRUE )
{
return TM_STATUS ( TMMAN32_ERR_DEVIOCTLFAIL );
}
*DSPCaps = TMIF.DSPCaps;
Global.DSPCaps = TMIF.DSPCaps;
return TMIF.Status;
}
STATUS tmDSPOpen ( DWORD dwDSPNumber, PDWORD DSPHandle )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -