You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
444 lines
12 KiB
444 lines
12 KiB
//***************************************************************************
|
|
//
|
|
//
|
|
//
|
|
//***************************************************************************
|
|
|
|
// Macros:
|
|
|
|
#define CreateSemaphore() (VMM_Create_Semaphore(0))
|
|
#define DestroySemaphore(_s) (VMM_Destroy_Semaphore(_s))
|
|
|
|
#define signal(_s) (VMM_Signal_Semaphore(_s))
|
|
#define wait(_s) (VMM_Wait_Semaphore_Ints(_s))
|
|
#define wait_idle(_s) (VMM_Wait_Semaphore_Idle(_s))
|
|
|
|
#define CreateResourceLock() (VMM_Create_Semaphore(1))
|
|
#define DestroyResourceLock(_s) (VMM_Destroy_Semaphore(_s))
|
|
#define lock(_s) (VMM_Wait_Semaphore_Ints(_s))
|
|
#define unlock(_s) (VMM_Signal_Semaphore(_s))
|
|
|
|
#define WANTVXDWRAPS
|
|
|
|
#include <basedef.h>
|
|
#include <vmm.h>
|
|
#include <vcomm.h>
|
|
#include <debug.h>
|
|
#include <vxdwraps.h>
|
|
#include <configmg.h>
|
|
#include <vwin32.h>
|
|
#include <winerror.h>
|
|
|
|
typedef DIOCPARAMETERS *LPDIOC;
|
|
|
|
#pragma VxD_LOCKED_CODE_SEG
|
|
#pragma VxD_LOCKED_DATA_SEG
|
|
|
|
#define ASSERT(_A) if(!(_A)){_asm int 3}
|
|
|
|
DWORD _stdcall LogInit(DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCParams);
|
|
DWORD _stdcall LogWrite(DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCParams);
|
|
DWORD _stdcall StatsWrite(DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCParams);
|
|
|
|
#define FIRST_DEBUG_PROC 100
|
|
|
|
DWORD ( _stdcall *DebugProcs[] )(DWORD, DWORD, LPDIOC) = {
|
|
LogInit,
|
|
LogWrite,
|
|
StatsWrite
|
|
};
|
|
|
|
#define MAX_DEBUG_PROC (sizeof(DebugProcs)/sizeof(DWORD)+FIRST_DEBUG_PROC-1)
|
|
|
|
typedef struct _LOGENTRY {
|
|
DWORD ThreadHandle;
|
|
DWORD tLogged;
|
|
CHAR debuglevel;
|
|
CHAR str[1];
|
|
} LOGENTRY, *PLOGENTRY;
|
|
|
|
PUCHAR pLog=NULL;
|
|
UINT nCharsPerLine;
|
|
UINT nLogEntries;
|
|
|
|
UINT iLogWritePos;
|
|
UINT nLogEntriesInUse;
|
|
|
|
UINT LogInitCount=0;
|
|
|
|
UINT LogLevel=255;
|
|
UINT LogExact=FALSE;
|
|
|
|
UINT LogLock=0;
|
|
|
|
#define Entry(_i) ((PLOGENTRY)(pLog+((sizeof(LOGENTRY)+nCharsPerLine)*_i)))
|
|
|
|
typedef struct {
|
|
UINT nLogEntries;
|
|
UINT nCharsPerLine;
|
|
} IN_LOGINIT, *PIN_LOGINIT;
|
|
|
|
typedef struct {
|
|
UINT hr;
|
|
} OUT_LOGINIT, *POUT_LOGINIT;
|
|
|
|
typedef struct {
|
|
CHAR debuglevel;
|
|
CHAR str[1];
|
|
} IN_LOGWRITE, *PIN_LOGWRITE;
|
|
|
|
typedef struct {
|
|
UINT hr;
|
|
} OUT_LOGWRITE, *POUT_LOGWRITE;
|
|
|
|
extern UINT stat_ThrottleRate;
|
|
extern UINT stat_BytesSent;
|
|
extern UINT stat_BackLog;
|
|
extern UINT stat_BytesLost;
|
|
extern UINT stat_RemBytesReceived;
|
|
extern UINT stat_Latency;
|
|
extern UINT stat_MinLatency;
|
|
extern UINT stat_AvgLatency;
|
|
extern UINT stat_AvgDevLatency;
|
|
extern UINT stat_USER1;
|
|
extern UINT stat_USER2;
|
|
extern UINT stat_USER3;
|
|
extern UINT stat_USER4;
|
|
extern UINT stat_USER5;
|
|
extern UINT stat_USER6;
|
|
|
|
typedef struct {
|
|
UINT stat_ThrottleRate;
|
|
UINT stat_BytesSent;
|
|
UINT stat_BackLog;
|
|
UINT stat_BytesLost;
|
|
UINT stat_RemBytesReceived;
|
|
UINT stat_Latency;
|
|
UINT stat_MinLatency;
|
|
UINT stat_AvgLatency;
|
|
UINT stat_AvgDevLatency;
|
|
UINT stat_USER1;
|
|
UINT stat_USER2;
|
|
UINT stat_USER3;
|
|
UINT stat_USER4;
|
|
UINT stat_USER5; // remote clock delta change from average
|
|
UINT stat_USER6; // sign of change
|
|
} IN_WRITESTATS, *PIN_WRITESTATS;
|
|
|
|
typedef struct {
|
|
UINT hr;
|
|
} OUT_WRITESTATS, *POUT_WRITESTATS;
|
|
|
|
VOID _stdcall ZeroStats();
|
|
|
|
/****************************************************************************
|
|
DPLAY_W32_DeviceIOControl
|
|
****************************************************************************/
|
|
DWORD _stdcall DPLAY_W32_DeviceIOControl(DWORD dwService,
|
|
DWORD dwDDB,
|
|
DWORD hDevice,
|
|
LPDIOC lpDIOCParms)
|
|
{
|
|
DWORD dwRetVal = 0;
|
|
|
|
if ( dwService == DIOC_OPEN )
|
|
{
|
|
dwRetVal = 0; // I/F supported!
|
|
}
|
|
else if ( dwService == DIOC_CLOSEHANDLE )
|
|
{
|
|
if(LogInitCount)
|
|
{
|
|
if(!(--LogInitCount)){
|
|
DestroyResourceLock(LogLock);
|
|
LogLock=0;
|
|
C_HeapFree(pLog);
|
|
pLog=NULL;
|
|
ZeroStats();
|
|
}
|
|
}
|
|
dwRetVal = VXD_SUCCESS; // ok, we're closed.
|
|
}
|
|
else if ((dwService >= FIRST_DEBUG_PROC) && (dwService <= MAX_DEBUG_PROC))
|
|
{
|
|
dwRetVal = (DebugProcs[dwService-FIRST_DEBUG_PROC])
|
|
(dwDDB, hDevice, lpDIOCParms);
|
|
}
|
|
else
|
|
{
|
|
dwRetVal = ERROR_NOT_SUPPORTED;
|
|
}
|
|
return(dwRetVal);
|
|
}
|
|
|
|
DWORD _stdcall LogInit(DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCParams)
|
|
{
|
|
PIN_LOGINIT pIn;
|
|
POUT_LOGINIT pOut;
|
|
UINT hr=0;
|
|
|
|
pIn=(PIN_LOGINIT)lpDIOCParams->lpvInBuffer;
|
|
pOut=(POUT_LOGINIT)lpDIOCParams->lpvOutBuffer;
|
|
|
|
ASSERT(lpDIOCParams->cbInBuffer>=sizeof(IN_LOGINIT));
|
|
ASSERT(lpDIOCParams->cbOutBuffer>=sizeof(OUT_LOGINIT));
|
|
|
|
if(!LogInitCount){
|
|
|
|
if(!pLog){
|
|
|
|
LogLock=CreateResourceLock();
|
|
nCharsPerLine = pIn->nCharsPerLine;
|
|
nLogEntries = pIn->nLogEntries;
|
|
iLogWritePos = 0;
|
|
nLogEntriesInUse = 0;
|
|
|
|
pLog=(CHAR *)C_HeapAllocate(pIn->nLogEntries*(sizeof(LOGENTRY)+pIn->nCharsPerLine),HEAPZEROINIT);
|
|
}
|
|
|
|
if(!pLog){
|
|
pOut->hr=ERROR_NOT_ENOUGH_MEMORY;
|
|
} else {
|
|
DbgPrint("DPLAYVXD: Logging on, allocated %d entries of length %d each\n",pIn->nLogEntries,pIn->nCharsPerLine);
|
|
pOut->hr=ERROR_SUCCESS;
|
|
LogInitCount=1;
|
|
}
|
|
lpDIOCParams->lpcbBytesReturned=sizeof(OUT_LOGINIT);
|
|
|
|
} else {
|
|
pOut->hr=ERROR_SUCCESS;
|
|
LogInitCount++;
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD _stdcall LogWrite(DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCParams)
|
|
{
|
|
PIN_LOGWRITE pIn;
|
|
POUT_LOGWRITE pOut;
|
|
|
|
pIn=(PIN_LOGWRITE)lpDIOCParams->lpvInBuffer;
|
|
pOut=(POUT_LOGWRITE)lpDIOCParams->lpvOutBuffer;
|
|
|
|
ASSERT(lpDIOCParams->cbInBuffer>=sizeof(IN_LOGWRITE));
|
|
ASSERT(lpDIOCParams->cbOutBuffer>=sizeof(OUT_LOGWRITE));
|
|
|
|
if(LogInitCount){
|
|
UINT BytesToCopy;
|
|
PLOGENTRY pLogEntry;
|
|
|
|
// make sure NULL terminated string
|
|
BytesToCopy=lpDIOCParams->cbInBuffer-sizeof(IN_LOGWRITE)+1;
|
|
if(BytesToCopy > nCharsPerLine){
|
|
BytesToCopy=nCharsPerLine;
|
|
}
|
|
pIn->str[BytesToCopy-1]=0;
|
|
|
|
lock(LogLock);
|
|
|
|
pLogEntry=Entry(iLogWritePos);
|
|
|
|
if(iLogWritePos+1 > nLogEntriesInUse){
|
|
nLogEntriesInUse+=1;
|
|
}
|
|
iLogWritePos=(iLogWritePos+1)%nLogEntries;
|
|
|
|
pLogEntry->ThreadHandle=GetThreadHandle();
|
|
pLogEntry->tLogged=VMM_Get_System_Time();
|
|
memcpy(&pLogEntry->debuglevel,pIn,BytesToCopy+sizeof(IN_LOGWRITE)-1);
|
|
|
|
unlock(LogLock);
|
|
|
|
pOut->hr=ERROR_SUCCESS;
|
|
} else {
|
|
pOut->hr=0x80000008;//E_FAIL
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
VOID SetLogLevel(UINT level, UINT fExact)
|
|
{
|
|
LogExact=fExact;
|
|
LogLevel=level;
|
|
if(LogExact)
|
|
{
|
|
DbgPrint("DPLAY VXD: Log printing is Exact at level %d\n",LogLevel);
|
|
} else {
|
|
DbgPrint("DPLAY VXD: Log printing is level %d and below\n",LogLevel);
|
|
}
|
|
}
|
|
|
|
DumpLogEntry(PLOGENTRY pLogEntry, UINT i, BOOL fResetTimeBase)
|
|
{
|
|
static UINT timebase=0;
|
|
if(pLogEntry){
|
|
DbgPrint("%4d: %8x %6d %2x %s\n",i,pLogEntry->ThreadHandle, pLogEntry->tLogged-timebase,pLogEntry->debuglevel, pLogEntry->str);
|
|
timebase=pLogEntry->tLogged;
|
|
}
|
|
if(fResetTimeBase){
|
|
timebase=0;
|
|
}
|
|
}
|
|
|
|
VOID DumpLog(UINT relstart)
|
|
{
|
|
UINT nToDump=50;
|
|
UINT c=0,i;
|
|
PLOGENTRY pLogEntry;
|
|
UINT start;
|
|
|
|
start=relstart;
|
|
|
|
if(nLogEntriesInUse==nLogEntries){
|
|
start=(iLogWritePos+start)%nLogEntries;
|
|
}
|
|
|
|
DumpLogEntry(NULL, 0, TRUE);
|
|
|
|
DbgPrint("Total Entries: %d, Current Position %d, dumping from record %d, %d ahead of start\n",nLogEntriesInUse,iLogWritePos,start,relstart);
|
|
|
|
for(i=start;i<nLogEntries && c<nToDump;i++){
|
|
pLogEntry=Entry(i);
|
|
if((LogExact)?(pLogEntry->debuglevel==LogLevel):(pLogEntry->debuglevel<=LogLevel)){
|
|
c++;
|
|
DumpLogEntry(pLogEntry,i,FALSE);
|
|
}
|
|
}
|
|
// Dump from beginning to current pos.
|
|
for(i=0;i<iLogWritePos && c<nToDump;i++,c++){
|
|
if((LogExact)?(pLogEntry->debuglevel==LogLevel):(pLogEntry->debuglevel<=LogLevel)){
|
|
c++;
|
|
DumpLogEntry(pLogEntry,i,FALSE);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
VOID DumpLogLast(UINT nToDump)
|
|
{
|
|
UINT c=0,i;
|
|
PLOGENTRY pLogEntry;
|
|
UINT start;
|
|
|
|
//BUGBUG: only works when all debug levels being dumped.
|
|
if(iLogWritePos > nToDump){
|
|
start=(iLogWritePos-nToDump);
|
|
}else{
|
|
start=(nLogEntries-(nToDump-iLogWritePos));
|
|
}
|
|
|
|
DumpLogEntry(NULL,0,TRUE);
|
|
|
|
DbgPrint("Total Entries: %d, Current Position %d, dumping from record %d\n",nLogEntriesInUse,iLogWritePos,start);
|
|
|
|
for(i=start;i<nLogEntries && c<nToDump;i++){
|
|
pLogEntry=Entry(i);
|
|
if((LogExact)?(pLogEntry->debuglevel==LogLevel):(pLogEntry->debuglevel<=LogLevel)){
|
|
c++;
|
|
DumpLogEntry(pLogEntry,i,FALSE);
|
|
}
|
|
}
|
|
// Dump from beginning to current pos.
|
|
for(i=0;i<iLogWritePos && c<nToDump;i++,c++){
|
|
pLogEntry=Entry(i);
|
|
if((LogExact)?(pLogEntry->debuglevel==LogLevel):(pLogEntry->debuglevel<=LogLevel)){
|
|
c++;
|
|
DumpLogEntry(pLogEntry,i,FALSE);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
VOID DumpWholeLog(VOID)
|
|
{
|
|
UINT i;
|
|
PLOGENTRY pLogEntry;
|
|
|
|
DumpLogEntry(NULL,0,TRUE);
|
|
|
|
// Dump from 1 after current pos to end.
|
|
if(nLogEntriesInUse==nLogEntries){
|
|
for(i=iLogWritePos;i<nLogEntries;i++){
|
|
pLogEntry=Entry(i);
|
|
if((LogExact)?(pLogEntry->debuglevel==LogLevel):(pLogEntry->debuglevel<=LogLevel)){
|
|
DumpLogEntry(pLogEntry,i,FALSE);
|
|
}
|
|
}
|
|
}
|
|
// Dump from beginning to current pos.
|
|
for(i=0;i<iLogWritePos;i++){
|
|
pLogEntry=Entry(i);
|
|
if((LogExact)?(pLogEntry->debuglevel==LogLevel):(pLogEntry->debuglevel<=LogLevel)){
|
|
DumpLogEntry(pLogEntry,i,FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
DWORD _stdcall StatsWrite(DWORD dwDDB, DWORD hDevice, LPDIOC lpDIOCParams)
|
|
{
|
|
PIN_WRITESTATS pIn;
|
|
POUT_WRITESTATS pOut;
|
|
UINT hr=0;
|
|
DWORD cbInBuffer;
|
|
|
|
pIn=(PIN_WRITESTATS)lpDIOCParams->lpvInBuffer;
|
|
pOut=(POUT_WRITESTATS)lpDIOCParams->lpvOutBuffer;
|
|
|
|
ASSERT(lpDIOCParams->cbInBuffer>=sizeof(DWORD));
|
|
ASSERT(lpDIOCParams->cbOutBuffer>=sizeof(OUT_WRITESTATS));
|
|
|
|
cbInBuffer=lpDIOCParams->cbInBuffer;
|
|
|
|
if(pIn->stat_ThrottleRate!=0xFFFFFFFF)stat_ThrottleRate=pIn->stat_ThrottleRate;
|
|
cbInBuffer-=sizeof(DWORD);if(!cbInBuffer)goto end;
|
|
if(pIn->stat_BytesSent!=0xFFFFFFFF)stat_BytesSent=pIn->stat_BytesSent;
|
|
cbInBuffer-=sizeof(DWORD);if(!cbInBuffer)goto end;
|
|
if(pIn->stat_BackLog!=0xFFFFFFFF)stat_BackLog=pIn->stat_BackLog;
|
|
cbInBuffer-=sizeof(DWORD);if(!cbInBuffer)goto end;
|
|
if(pIn->stat_BytesLost!=0xFFFFFFFF)stat_BytesLost=pIn->stat_BytesLost;
|
|
cbInBuffer-=sizeof(DWORD);if(!cbInBuffer)goto end;
|
|
if(pIn->stat_RemBytesReceived!=0xFFFFFFFF)stat_RemBytesReceived=pIn->stat_RemBytesReceived;
|
|
cbInBuffer-=sizeof(DWORD);if(!cbInBuffer)goto end;
|
|
if(pIn->stat_Latency!=0xFFFFFFFF)stat_Latency=pIn->stat_Latency;
|
|
cbInBuffer-=sizeof(DWORD);if(!cbInBuffer)goto end;
|
|
if(pIn->stat_MinLatency!=0xFFFFFFFF)stat_MinLatency=pIn->stat_MinLatency;
|
|
cbInBuffer-=sizeof(DWORD);if(!cbInBuffer)goto end;
|
|
if(pIn->stat_AvgLatency!=0xFFFFFFFF)stat_AvgLatency=pIn->stat_AvgLatency;
|
|
cbInBuffer-=sizeof(DWORD);if(!cbInBuffer)goto end;
|
|
if(pIn->stat_AvgDevLatency!=0xFFFFFFFF)stat_AvgDevLatency=pIn->stat_AvgDevLatency;
|
|
cbInBuffer-=sizeof(DWORD);if(!cbInBuffer)goto end;
|
|
if(pIn->stat_USER1!=0xFFFFFFFF)stat_USER1=pIn->stat_USER1;
|
|
cbInBuffer-=sizeof(DWORD);if(!cbInBuffer)goto end;
|
|
if(pIn->stat_USER2!=0xFFFFFFFF)stat_USER2=pIn->stat_USER2;
|
|
cbInBuffer-=sizeof(DWORD);if(!cbInBuffer)goto end;
|
|
if(pIn->stat_USER3!=0xFFFFFFFF)stat_USER3=pIn->stat_USER3;
|
|
cbInBuffer-=sizeof(DWORD);if(!cbInBuffer)goto end;
|
|
if(pIn->stat_USER4!=0xFFFFFFFF)stat_USER4=pIn->stat_USER4;
|
|
cbInBuffer-=sizeof(DWORD);if(!cbInBuffer)goto end;
|
|
if(pIn->stat_USER5!=0xFFFFFFFF)stat_USER5=pIn->stat_USER5;
|
|
cbInBuffer-=sizeof(DWORD);if(!cbInBuffer)goto end;
|
|
if(pIn->stat_USER6!=0xFFFFFFFF)stat_USER6=pIn->stat_USER6;
|
|
end:
|
|
pOut->hr=ERROR_SUCCESS;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
VOID _stdcall ZeroStats()
|
|
{
|
|
stat_ThrottleRate=0;
|
|
stat_BytesSent=0;
|
|
stat_BackLog=0;
|
|
stat_BytesLost=0;
|
|
stat_RemBytesReceived=0;
|
|
stat_Latency=0;
|
|
stat_MinLatency=0;
|
|
stat_AvgLatency=0;
|
|
stat_AvgDevLatency=0;
|
|
stat_USER1=0;
|
|
stat_USER2=0;
|
|
stat_USER3=0;
|
|
stat_USER4=0;
|
|
stat_USER5=0;
|
|
stat_USER6=0;
|
|
}
|