00001
00002
00003
00004
00005
00006 #define _WINDLL
00007
00008 #include <streams.h>
00009 #include <stdarg.h>
00010 #include <stdio.h>
00011
00012 #ifdef DEBUG
00013 #ifdef UNICODE
00014 #ifndef _UNICODE
00015 #define _UNICODE
00016 #endif
00017 #endif
00018 #endif
00019
00020 #include <tchar.h>
00021
00022 #ifdef DEBUG
00023
00024 const INT iDEBUGINFO = 1024;
00025
00026 TCHAR *pKeyNames[] = {
00027 TEXT("TIMING"),
00028 TEXT("TRACE"),
00029 TEXT("MEMORY"),
00030 TEXT("LOCKING"),
00031 TEXT("ERROR"),
00032 TEXT("CUSTOM1"),
00033 TEXT("CUSTOM2"),
00034 TEXT("CUSTOM3"),
00035 TEXT("CUSTOM4"),
00036 TEXT("CUSTOM5")
00037 };
00038
00039 const TCHAR CAutoTrace::_szEntering[] = TEXT("Entering: %s");
00040 const TCHAR CAutoTrace::_szLeaving[] = TEXT("Leaving: %s");
00041
00042 const INT iMAXLEVELS = NUMELMS(pKeyNames);
00043
00044 HINSTANCE m_hInst;
00045 TCHAR m_ModuleName[iDEBUGINFO];
00046 DWORD m_Levels[iMAXLEVELS];
00047 CRITICAL_SECTION m_CSDebug;
00048 DWORD m_dwNextCookie;
00049 ObjectDesc *pListHead = NULL;
00050 DWORD m_dwObjectCount;
00051 BOOL m_bInit = FALSE;
00052 HANDLE m_hOutput = INVALID_HANDLE_VALUE;
00053 DWORD dwWaitTimeout = INFINITE;
00054 DWORD dwTimeOffset;
00055 bool g_fUseKASSERT = false;
00056 bool g_fDbgInDllEntryPoint = false;
00057 bool g_fAutoRefreshLevels = false;
00058
00059 const TCHAR *pBaseKey = TEXT("SOFTWARE\\Debug");
00060 const TCHAR *pGlobalKey = TEXT("GLOBAL");
00061 static CHAR *pUnknownName = "UNKNOWN";
00062
00063 TCHAR *TimeoutName = TEXT("TIMEOUT");
00064
00065 void WINAPI DbgInitialise(HINSTANCE hInst)
00066 {
00067 InitializeCriticalSection(&m_CSDebug);
00068 m_bInit = TRUE;
00069
00070 m_hInst = hInst;
00071 DbgInitModuleName();
00072 if (GetProfileInt(m_ModuleName, TEXT("BreakOnLoad"), 0))
00073 DebugBreak();
00074 DbgInitModuleSettings(false);
00075 DbgInitGlobalSettings(true);
00076 dwTimeOffset = timeGetTime();
00077 }
00078
00079 void WINAPI DbgTerminate()
00080 {
00081 if (m_hOutput != INVALID_HANDLE_VALUE) {
00082 EXECUTE_ASSERT(CloseHandle(m_hOutput));
00083 m_hOutput = INVALID_HANDLE_VALUE;
00084 }
00085 DeleteCriticalSection(&m_CSDebug);
00086 m_bInit = FALSE;
00087 }
00088
00089 void WINAPI DbgInitKeyLevels(HKEY hKey, bool fTakeMax)
00090 {
00091 LONG lReturn;
00092 LONG lKeyPos;
00093 DWORD dwKeySize;
00094 DWORD dwKeyType;
00095 DWORD dwKeyValue;
00096
00097
00098 for (lKeyPos = 0;lKeyPos < iMAXLEVELS;lKeyPos++) {
00099
00100 dwKeySize = sizeof(DWORD);
00101 lReturn = RegQueryValueEx(
00102 hKey,
00103 pKeyNames[lKeyPos],
00104 NULL,
00105 &dwKeyType,
00106 (LPBYTE) &dwKeyValue,
00107 &dwKeySize );
00108
00109
00110
00111 if (lReturn != ERROR_SUCCESS || dwKeyType != REG_DWORD) {
00112
00113 dwKeyValue = 0;
00114 lReturn = RegSetValueEx(
00115 hKey,
00116 pKeyNames[lKeyPos],
00117 (DWORD) 0,
00118 REG_DWORD,
00119 (PBYTE) &dwKeyValue,
00120 sizeof(DWORD));
00121
00122 if (lReturn != ERROR_SUCCESS) {
00123 DbgLog((LOG_ERROR,0,TEXT("Could not create subkey %s"),pKeyNames[lKeyPos]));
00124 dwKeyValue = 0;
00125 }
00126 }
00127 if(fTakeMax)
00128 {
00129 m_Levels[lKeyPos] = max(dwKeyValue,m_Levels[lKeyPos]);
00130 }
00131 else
00132 {
00133 if((m_Levels[lKeyPos] & LOG_FORCIBLY_SET) == 0) {
00134 m_Levels[lKeyPos] = dwKeyValue;
00135 }
00136 }
00137 }
00138
00139
00140 dwKeySize = sizeof(DWORD);
00141 lReturn = RegQueryValueEx(
00142 hKey,
00143 TimeoutName,
00144 NULL,
00145 &dwKeyType,
00146 (LPBYTE) &dwWaitTimeout,
00147 &dwKeySize );
00148
00149
00150
00151 if (lReturn != ERROR_SUCCESS || dwKeyType != REG_DWORD) {
00152
00153 dwWaitTimeout = INFINITE;
00154 lReturn = RegSetValueEx(
00155 hKey,
00156 TimeoutName,
00157 (DWORD) 0,
00158 REG_DWORD,
00159 (PBYTE) &dwWaitTimeout,
00160 sizeof(DWORD));
00161
00162 if (lReturn != ERROR_SUCCESS) {
00163 DbgLog((LOG_ERROR,0,TEXT("Could not create subkey %s"),pKeyNames[lKeyPos]));
00164 dwWaitTimeout = INFINITE;
00165 }
00166 }
00167 }
00168
00169 void WINAPI DbgOutString(LPCTSTR psz)
00170 {
00171 if (m_hOutput != INVALID_HANDLE_VALUE) {
00172 UINT cb = lstrlen(psz);
00173 DWORD dw;
00174 #ifdef UNICODE
00175 CHAR szDest[2048];
00176 WideCharToMultiByte(CP_ACP, 0, psz, -1, szDest, NUMELMS(szDest), 0, 0);
00177 WriteFile (m_hOutput, szDest, cb, &dw, NULL);
00178 #else
00179 WriteFile (m_hOutput, psz, cb, &dw, NULL);
00180 #endif
00181 } else {
00182 OutputDebugString (psz);
00183 }
00184 }
00185
00186 void WINAPI DbgInitLogTo (
00187 HKEY hKey)
00188 {
00189 LONG lReturn;
00190 DWORD dwKeyType;
00191 DWORD dwKeySize;
00192 TCHAR szFile[MAX_PATH] = {0};
00193 static const TCHAR cszKey[] = TEXT("LogToFile");
00194
00195 dwKeySize = MAX_PATH;
00196 lReturn = RegQueryValueEx(
00197 hKey,
00198 cszKey,
00199 NULL,
00200 &dwKeyType,
00201 (LPBYTE) szFile,
00202 &dwKeySize);
00203
00204
00205
00206 if (lReturn != ERROR_SUCCESS || dwKeyType != REG_SZ)
00207 {
00208 dwKeySize = 1;
00209 lReturn = RegSetValueEx(
00210 hKey,
00211 cszKey,
00212 (DWORD) 0,
00213 REG_SZ,
00214 (PBYTE)szFile,
00215 dwKeySize);
00216 }
00217
00218
00219
00220 if (m_hOutput != INVALID_HANDLE_VALUE) {
00221 EXECUTE_ASSERT(CloseHandle (m_hOutput));
00222 m_hOutput = INVALID_HANDLE_VALUE;
00223 }
00224 if (szFile[0] != 0)
00225 {
00226 if (!lstrcmpi(szFile, TEXT("Console"))) {
00227 m_hOutput = GetStdHandle (STD_OUTPUT_HANDLE);
00228 if (m_hOutput == INVALID_HANDLE_VALUE) {
00229 AllocConsole ();
00230 m_hOutput = GetStdHandle (STD_OUTPUT_HANDLE);
00231 }
00232 SetConsoleTitle (TEXT("ActiveX Debug Output"));
00233 } else if (szFile[0] &&
00234 lstrcmpi(szFile, TEXT("Debug")) &&
00235 lstrcmpi(szFile, TEXT("Debugger")) &&
00236 lstrcmpi(szFile, TEXT("Deb")))
00237 {
00238 m_hOutput = CreateFile(szFile, GENERIC_WRITE,
00239 FILE_SHARE_READ,
00240 NULL, OPEN_ALWAYS,
00241 FILE_ATTRIBUTE_NORMAL,
00242 NULL);
00243 if (INVALID_HANDLE_VALUE != m_hOutput)
00244 {
00245 static const TCHAR cszBar[] = TEXT("\r\n\r\n=====DbgInitialize()=====\r\n\r\n");
00246 SetFilePointer (m_hOutput, 0, NULL, FILE_END);
00247 DbgOutString (cszBar);
00248 }
00249 }
00250 }
00251 }
00252
00253 void WINAPI DbgInitGlobalSettings(bool fTakeMax)
00254 {
00255 LONG lReturn;
00256 TCHAR szInfo[iDEBUGINFO];
00257 HKEY hGlobalKey;
00258
00259
00260 wsprintf(szInfo,TEXT("%s\\%s"),pBaseKey,pGlobalKey);
00261
00262
00263 lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
00264 szInfo,
00265 (DWORD) 0,
00266 NULL,
00267 (DWORD) 0,
00268 KEY_ALL_ACCESS,
00269 NULL,
00270 &hGlobalKey,
00271 NULL);
00272
00273 if (lReturn != ERROR_SUCCESS) {
00274 DbgLog((LOG_ERROR,0,TEXT("Could not access GLOBAL module key")));
00275 return;
00276 }
00277
00278 DbgInitKeyLevels(hGlobalKey, fTakeMax);
00279 RegCloseKey(hGlobalKey);
00280 }
00281
00282 void WINAPI DbgInitModuleSettings(bool fTakeMax)
00283 {
00284 LONG lReturn;
00285 TCHAR szInfo[iDEBUGINFO];
00286 HKEY hModuleKey;
00287
00288
00289 wsprintf(szInfo,TEXT("%s\\%s"),pBaseKey,m_ModuleName);
00290
00291
00292 lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
00293 szInfo,
00294 (DWORD) 0,
00295 NULL,
00296 (DWORD) 0,
00297 KEY_ALL_ACCESS,
00298 NULL,
00299 &hModuleKey,
00300 NULL);
00301
00302 if (lReturn != ERROR_SUCCESS) {
00303 DbgLog((LOG_ERROR,0,TEXT("Could not access module key")));
00304 return;
00305 }
00306
00307 DbgInitLogTo(hModuleKey);
00308 DbgInitKeyLevels(hModuleKey, fTakeMax);
00309 RegCloseKey(hModuleKey);
00310 }
00311
00312 void WINAPI DbgInitModuleName()
00313 {
00314 TCHAR FullName[iDEBUGINFO];
00315 TCHAR *pName;
00316
00317 GetModuleFileName(m_hInst,FullName,iDEBUGINFO);
00318 pName = _tcsrchr(FullName,'\\');
00319 if (pName == NULL) {
00320 pName = FullName;
00321 } else {
00322 pName++;
00323 }
00324 lstrcpy(m_ModuleName,pName);
00325 }
00326
00327 struct MsgBoxMsg
00328 {
00329 HWND hwnd;
00330 TCHAR *szTitle;
00331 TCHAR *szMessage;
00332 DWORD dwFlags;
00333 INT iResult;
00334 };
00335
00336 DWORD WINAPI MsgBoxThread(
00337 LPVOID lpParameter
00338 )
00339 {
00340 MsgBoxMsg *pmsg = (MsgBoxMsg *)lpParameter;
00341 pmsg->iResult = MessageBox(
00342 pmsg->hwnd,
00343 pmsg->szTitle,
00344 pmsg->szMessage,
00345 pmsg->dwFlags);
00346
00347 return 0;
00348 }
00349
00350 INT MessageBoxOtherThread(
00351 HWND hwnd,
00352 TCHAR *szTitle,
00353 TCHAR *szMessage,
00354 DWORD dwFlags)
00355 {
00356 if(g_fDbgInDllEntryPoint)
00357 {
00358
00359
00360 return MessageBox(hwnd, szTitle, szMessage, dwFlags);
00361 }
00362 else
00363 {
00364 MsgBoxMsg msg = {hwnd, szTitle, szMessage, dwFlags, 0};
00365 DWORD dwid;
00366 HANDLE hThread = CreateThread(
00367 0,
00368 0,
00369 MsgBoxThread,
00370 (void *)&msg,
00371 0,
00372 &dwid);
00373 if(hThread)
00374 {
00375 WaitForSingleObject(hThread, INFINITE);
00376 CloseHandle(hThread);
00377 return msg.iResult;
00378 }
00379
00380
00381 return IDCANCEL;
00382 }
00383 }
00384
00385 void WINAPI DbgAssert(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine)
00386 {
00387 if(g_fUseKASSERT)
00388 {
00389 DbgKernelAssert(pCondition, pFileName, iLine);
00390 }
00391 else
00392 {
00393
00394 TCHAR szInfo[iDEBUGINFO];
00395
00396 wsprintf(szInfo, TEXT("%s \nAt line %d of %s\nContinue? (Cancel to debug)"),
00397 pCondition, iLine, pFileName);
00398
00399 INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("ASSERT Failed"),
00400 MB_SYSTEMMODAL |
00401 MB_ICONHAND |
00402 MB_YESNOCANCEL |
00403 MB_SETFOREGROUND);
00404 switch (MsgId)
00405 {
00406 case IDNO:
00407
00408 FatalAppExit(FALSE, TEXT("Application terminated"));
00409 break;
00410
00411 case IDCANCEL:
00412
00413 DebugBreak();
00414 break;
00415
00416 case IDYES:
00417 break;
00418 }
00419 }
00420 }
00421
00422 void WINAPI DbgBreakPoint(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine)
00423 {
00424 if(g_fUseKASSERT)
00425 {
00426 DbgKernelAssert(pCondition, pFileName, iLine);
00427 }
00428 else
00429 {
00430 TCHAR szInfo[iDEBUGINFO];
00431
00432 wsprintf(szInfo, TEXT("%s \nAt line %d of %s\nContinue? (Cancel to debug)"),
00433 pCondition, iLine, pFileName);
00434
00435 INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("Hard coded break point"),
00436 MB_SYSTEMMODAL |
00437 MB_ICONHAND |
00438 MB_YESNOCANCEL |
00439 MB_SETFOREGROUND);
00440 switch (MsgId)
00441 {
00442 case IDNO:
00443
00444 FatalAppExit(FALSE, TEXT("Application terminated"));
00445 break;
00446
00447 case IDCANCEL:
00448
00449 DebugBreak();
00450 break;
00451
00452 case IDYES:
00453 break;
00454 }
00455 }
00456 }
00457
00458 void WINAPI DbgBreakPoint(const TCHAR *pFileName,INT iLine,const TCHAR* szFormatString,...)
00459 {
00460
00461
00462
00463
00464
00465 const DWORD MAX_BREAK_POINT_MESSAGE_SIZE = 2000;
00466
00467 TCHAR szBreakPointMessage[MAX_BREAK_POINT_MESSAGE_SIZE];
00468
00469 const DWORD MAX_CHARS_IN_BREAK_POINT_MESSAGE = sizeof(szBreakPointMessage) / sizeof(TCHAR);
00470
00471 va_list va;
00472 va_start( va, szFormatString );
00473
00474 int nReturnValue = _vsntprintf( szBreakPointMessage, MAX_CHARS_IN_BREAK_POINT_MESSAGE, szFormatString, va );
00475
00476 va_end(va);
00477
00478
00479 if( -1 == nReturnValue ) {
00480 DbgBreak( "ERROR in DbgBreakPoint(). The variable length debug message could not be displayed because _vsnprintf() failed." );
00481 return;
00482 }
00483
00484 ::DbgBreakPoint( szBreakPointMessage, pFileName, iLine );
00485 }
00486
00487 BOOL WINAPI DbgCheckModuleLevel(DWORD Type,DWORD Level)
00488 {
00489 if(g_fAutoRefreshLevels)
00490 {
00491
00492
00493 static g_dwLastRefresh = 0;
00494 DWORD dwTime = timeGetTime();
00495 if(dwTime - g_dwLastRefresh > 1000) {
00496 g_dwLastRefresh = dwTime;
00497
00498
00499
00500
00501 DbgInitModuleSettings(false);
00502 }
00503 }
00504
00505 DWORD Mask = 0x01;
00506
00507
00508 if ((Type & ((1<<iMAXLEVELS)-1))) {
00509
00510
00511 if (0==Level)
00512 return(TRUE);
00513
00514 for (LONG lKeyPos = 0;lKeyPos < iMAXLEVELS;lKeyPos++) {
00515 if (Type & Mask) {
00516 if (Level <= (m_Levels[lKeyPos] & ~LOG_FORCIBLY_SET)) {
00517 return TRUE;
00518 }
00519 }
00520 Mask <<= 1;
00521 }
00522 }
00523 return FALSE;
00524 }
00525
00526 void WINAPI DbgSetModuleLevel(DWORD Type, DWORD Level)
00527 {
00528 DWORD Mask = 0x01;
00529
00530 for (LONG lKeyPos = 0;lKeyPos < iMAXLEVELS;lKeyPos++) {
00531 if (Type & Mask) {
00532 m_Levels[lKeyPos] = Level | LOG_FORCIBLY_SET;
00533 }
00534 Mask <<= 1;
00535 }
00536 }
00537
00538 void WINAPI DbgSetAutoRefreshLevels(bool fAuto)
00539 {
00540 g_fAutoRefreshLevels = fAuto;
00541 }
00542
00543 #ifdef UNICODE
00544
00545 void WINAPI DbgLogInfo(DWORD Type,DWORD Level,const CHAR *pFormat,...)
00546 {
00547
00548
00549 BOOL bAccept = DbgCheckModuleLevel(Type,Level);
00550 if (bAccept == FALSE) {
00551 return;
00552 }
00553
00554 TCHAR szInfo[2000];
00555
00556
00557
00558 va_list va;
00559 va_start(va, pFormat);
00560
00561 lstrcpy(szInfo,m_ModuleName);
00562 wsprintf(szInfo + lstrlen(szInfo),
00563 TEXT("(tid %x) %8d : "),
00564 GetCurrentThreadId(), timeGetTime() - dwTimeOffset);
00565
00566 CHAR szInfoA[2000];
00567 WideCharToMultiByte(CP_ACP, 0, szInfo, -1, szInfoA, NUMELMS(szInfoA), 0, 0);
00568
00569 wvsprintfA(szInfoA + lstrlenA(szInfoA), pFormat, va);
00570 lstrcatA(szInfoA, "\r\n");
00571
00572 WCHAR wszOutString[2000];
00573 MultiByteToWideChar(CP_ACP, 0, szInfoA, -1, wszOutString, NUMELMS(wszOutString));
00574 DbgOutString(wszOutString);
00575
00576 va_end(va);
00577 }
00578
00579 void DbgAssert(const CHAR *pCondition,const CHAR *pFileName,INT iLine)
00580 {
00581 if(g_fUseKASSERT)
00582 {
00583 DbgKernelAssert(pCondition, pFileName, iLine);
00584 }
00585 else
00586 {
00587
00588 TCHAR szInfo[iDEBUGINFO];
00589
00590 wsprintf(szInfo, TEXT("%hs \nAt line %d of %hs\nContinue? (Cancel to debug)"),
00591 pCondition, iLine, pFileName);
00592
00593 INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("ASSERT Failed"),
00594 MB_SYSTEMMODAL |
00595 MB_ICONHAND |
00596 MB_YESNOCANCEL |
00597 MB_SETFOREGROUND);
00598 switch (MsgId)
00599 {
00600 case IDNO:
00601
00602 FatalAppExit(FALSE, TEXT("Application terminated"));
00603 break;
00604
00605 case IDCANCEL:
00606
00607 DebugBreak();
00608 break;
00609
00610 case IDYES:
00611 break;
00612 }
00613 }
00614 }
00615
00616 void WINAPI DbgBreakPoint(const CHAR *pCondition,const CHAR *pFileName,INT iLine)
00617 {
00618 if(g_fUseKASSERT)
00619 {
00620 DbgKernelAssert(pCondition, pFileName, iLine);
00621 }
00622 else
00623 {
00624 TCHAR szInfo[iDEBUGINFO];
00625
00626 wsprintf(szInfo, TEXT("%hs \nAt line %d of %hs\nContinue? (Cancel to debug)"),
00627 pCondition, iLine, pFileName);
00628
00629 INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("Hard coded break point"),
00630 MB_SYSTEMMODAL |
00631 MB_ICONHAND |
00632 MB_YESNOCANCEL |
00633 MB_SETFOREGROUND);
00634 switch (MsgId)
00635 {
00636 case IDNO:
00637
00638 FatalAppExit(FALSE, TEXT("Application terminated"));
00639 break;
00640
00641 case IDCANCEL:
00642
00643 DebugBreak();
00644 break;
00645
00646 case IDYES:
00647 break;
00648 }
00649 }
00650 }
00651
00652 void WINAPI DbgKernelAssert(const CHAR *pCondition,const CHAR *pFileName,INT iLine)
00653 {
00654 DbgLog((LOG_ERROR,0,TEXT("Assertion FAILED (%hs) at line %d in file %hs"),
00655 pCondition, iLine, pFileName));
00656 DebugBreak();
00657 }
00658
00659 #endif
00660
00661 void WINAPI DbgLogInfo(DWORD Type,DWORD Level,const TCHAR *pFormat,...)
00662 {
00663
00664
00665
00666 BOOL bAccept = DbgCheckModuleLevel(Type,Level);
00667 if (bAccept == FALSE) {
00668 return;
00669 }
00670
00671 TCHAR szInfo[2000];
00672
00673
00674
00675 va_list va;
00676 va_start(va, pFormat);
00677
00678 lstrcpy(szInfo,m_ModuleName);
00679 wsprintf(szInfo + lstrlen(szInfo),
00680 TEXT("(tid %x) %8d : "),
00681 GetCurrentThreadId(), timeGetTime() - dwTimeOffset);
00682
00683 _vstprintf(szInfo + lstrlen(szInfo), pFormat, va);
00684 lstrcat(szInfo, TEXT("\r\n"));
00685 DbgOutString(szInfo);
00686
00687 va_end(va);
00688 }
00689
00690 void WINAPI DbgKernelAssert(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine)
00691 {
00692 DbgLog((LOG_ERROR,0,TEXT("Assertion FAILED (%s) at line %d in file %s"),
00693 pCondition, iLine, pFileName));
00694 DebugBreak();
00695 }
00696
00697 DWORD WINAPI DbgRegisterObjectCreation(const CHAR *szObjectName,
00698 const WCHAR *wszObjectName)
00699 {
00700
00701
00702 ASSERT(!!szObjectName ^ !!wszObjectName);
00703
00704
00705
00706 ObjectDesc *pObject = new ObjectDesc;
00707 ASSERT(pObject);
00708
00709
00710 if (pObject == NULL) {
00711 return FALSE;
00712 }
00713
00714
00715
00716 if (m_bInit == FALSE) {
00717 DbgInitialise(GetModuleHandle(NULL));
00718 }
00719
00720
00721 EnterCriticalSection(&m_CSDebug);
00722
00723
00724 if (!szObjectName && !wszObjectName) {
00725 szObjectName = pUnknownName;
00726 }
00727
00728
00729
00730 pObject->m_szName = szObjectName;
00731 pObject->m_wszName = wszObjectName;
00732 pObject->m_dwCookie = ++m_dwNextCookie;
00733 pObject->m_pNext = pListHead;
00734
00735 pListHead = pObject;
00736 m_dwObjectCount++;
00737
00738 DWORD ObjectCookie = pObject->m_dwCookie;
00739 ASSERT(ObjectCookie);
00740
00741 if(wszObjectName) {
00742 DbgLog((LOG_MEMORY,2,TEXT("Object created %d (%ls) %d Active"),
00743 pObject->m_dwCookie, wszObjectName, m_dwObjectCount));
00744 } else {
00745 DbgLog((LOG_MEMORY,2,TEXT("Object created %d (%hs) %d Active"),
00746 pObject->m_dwCookie, szObjectName, m_dwObjectCount));
00747 }
00748
00749 LeaveCriticalSection(&m_CSDebug);
00750 return ObjectCookie;
00751 }
00752
00753 BOOL WINAPI DbgRegisterObjectDestruction(DWORD dwCookie)
00754 {
00755
00756 EnterCriticalSection(&m_CSDebug);
00757
00758 ObjectDesc *pObject = pListHead;
00759 ObjectDesc *pPrevious = NULL;
00760
00761
00762
00763 while (pObject) {
00764 if (pObject->m_dwCookie == dwCookie) {
00765 break;
00766 }
00767 pPrevious = pObject;
00768 pObject = pObject->m_pNext;
00769 }
00770
00771 if (pObject == NULL) {
00772 DbgBreak("Apparently destroying a bogus object");
00773 LeaveCriticalSection(&m_CSDebug);
00774 return FALSE;
00775 }
00776
00777
00778
00779 if (pPrevious == NULL) {
00780 pListHead = pObject->m_pNext;
00781 } else {
00782 pPrevious->m_pNext = pObject->m_pNext;
00783 }
00784
00785
00786
00787 m_dwObjectCount--;
00788
00789 if(pObject->m_wszName) {
00790 DbgLog((LOG_MEMORY,2,TEXT("Object destroyed %d (%ls) %d Active"),
00791 pObject->m_dwCookie, pObject->m_wszName, m_dwObjectCount));
00792 } else {
00793 DbgLog((LOG_MEMORY,2,TEXT("Object destroyed %d (%hs) %d Active"),
00794 pObject->m_dwCookie, pObject->m_szName, m_dwObjectCount));
00795 }
00796
00797 delete pObject;
00798 LeaveCriticalSection(&m_CSDebug);
00799 return TRUE;
00800 }
00801
00802 void WINAPI DbgDumpObjectRegister()
00803 {
00804 TCHAR szInfo[iDEBUGINFO];
00805
00806
00807
00808 EnterCriticalSection(&m_CSDebug);
00809 ObjectDesc *pObject = pListHead;
00810
00811
00812
00813 DbgLog((LOG_MEMORY,2,TEXT("")));
00814 DbgLog((LOG_MEMORY,2,TEXT(" ID Object Description")));
00815 DbgLog((LOG_MEMORY,2,TEXT("")));
00816
00817 while (pObject) {
00818 if(pObject->m_wszName) {
00819 wsprintf(szInfo,TEXT("%5d (%8x) %30ls"),pObject->m_dwCookie, &pObject, pObject->m_wszName);
00820 } else {
00821 wsprintf(szInfo,TEXT("%5d (%8x) %30hs"),pObject->m_dwCookie, &pObject, pObject->m_szName);
00822 }
00823 DbgLog((LOG_MEMORY,2,szInfo));
00824 pObject = pObject->m_pNext;
00825 }
00826
00827 wsprintf(szInfo,TEXT("Total object count %5d"),m_dwObjectCount);
00828 DbgLog((LOG_MEMORY,2,TEXT("")));
00829 DbgLog((LOG_MEMORY,1,szInfo));
00830 LeaveCriticalSection(&m_CSDebug);
00831 }
00832
00833 DWORD WINAPI DbgWaitForSingleObject(HANDLE h)
00834 {
00835 DWORD dwWaitResult;
00836 do {
00837 dwWaitResult = WaitForSingleObject(h, dwWaitTimeout);
00838 ASSERT(dwWaitResult == WAIT_OBJECT_0);
00839 } while (dwWaitResult == WAIT_TIMEOUT);
00840 return dwWaitResult;
00841 }
00842 DWORD WINAPI DbgWaitForMultipleObjects(DWORD nCount,
00843 CONST HANDLE *lpHandles,
00844 BOOL bWaitAll)
00845 {
00846 DWORD dwWaitResult;
00847 do {
00848 dwWaitResult = WaitForMultipleObjects(nCount,
00849 lpHandles,
00850 bWaitAll,
00851 dwWaitTimeout);
00852 ASSERT((DWORD)(dwWaitResult - WAIT_OBJECT_0) < MAXIMUM_WAIT_OBJECTS);
00853 } while (dwWaitResult == WAIT_TIMEOUT);
00854 return dwWaitResult;
00855 }
00856
00857 void WINAPI DbgSetWaitTimeout(DWORD dwTimeout)
00858 {
00859 dwWaitTimeout = dwTimeout;
00860 }
00861
00862 #endif
00863
00864 #ifdef _OBJBASE_H_
00865
00866
00867
00868 GUID_STRING_ENTRY g_GuidNames[] = {
00869 #define OUR_GUID_ENTRY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
00870 { #name, { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } },
00871 #include <uuids.h>
00872 };
00873
00874 CGuidNameList GuidNames;
00875 int g_cGuidNames = sizeof(g_GuidNames) / sizeof(g_GuidNames[0]);
00876
00877 char *CGuidNameList::operator [] (const GUID &guid)
00878 {
00879 for (int i = 0; i < g_cGuidNames; i++) {
00880 if (g_GuidNames[i].guid == guid) {
00881 return g_GuidNames[i].szName;
00882 }
00883 }
00884 if (guid == GUID_NULL) {
00885 return "GUID_NULL";
00886 }
00887
00888
00889
00890
00891 return "Unknown GUID Name";
00892 }
00893
00894 #endif
00895
00896 CDisp::CDisp(LONGLONG ll, int Format)
00897 {
00898
00899
00900 LARGE_INTEGER li;
00901 li.QuadPart = ll;
00902 switch (Format) {
00903 case CDISP_DEC:
00904 {
00905 TCHAR temp[20];
00906 int pos=20;
00907 temp[--pos] = 0;
00908 int digit;
00909
00910 do {
00911
00912 digit = li.LowPart % 10;
00913 li.QuadPart /= 10;
00914 temp[--pos] = (TCHAR) digit+L'0';
00915 } while (li.QuadPart);
00916 wsprintf(m_String, TEXT("%s"), temp+pos);
00917 break;
00918 }
00919 case CDISP_HEX:
00920 default:
00921 wsprintf(m_String, TEXT("0x%X%8.8X"), li.HighPart, li.LowPart);
00922 }
00923 };
00924
00925 CDisp::CDisp(REFCLSID clsid)
00926 {
00927 WCHAR strClass[CHARS_IN_GUID+1];
00928 StringFromGUID2(clsid, strClass, sizeof(strClass) / sizeof(strClass[0]));
00929 ASSERT(sizeof(m_String)/sizeof(m_String[0]) >= CHARS_IN_GUID+1);
00930 wsprintf(m_String, TEXT("%ls"), strClass);
00931 };
00932
00933 #ifdef __STREAMS__
00934
00935 CDisp::CDisp(CRefTime llTime)
00936 {
00937 LPTSTR lpsz = m_String;
00938 LONGLONG llDiv;
00939 if (llTime < 0) {
00940 llTime = -llTime;
00941 lpsz += wsprintf(lpsz, TEXT("-"));
00942 }
00943 llDiv = (LONGLONG)24 * 3600 * 10000000;
00944 if (llTime >= llDiv) {
00945 lpsz += wsprintf(lpsz, TEXT("%d days "), (LONG)(llTime / llDiv));
00946 llTime = llTime % llDiv;
00947 }
00948 llDiv = (LONGLONG)3600 * 10000000;
00949 if (llTime >= llDiv) {
00950 lpsz += wsprintf(lpsz, TEXT("%d hrs "), (LONG)(llTime / llDiv));
00951 llTime = llTime % llDiv;
00952 }
00953 llDiv = (LONGLONG)60 * 10000000;
00954 if (llTime >= llDiv) {
00955 lpsz += wsprintf(lpsz, TEXT("%d mins "), (LONG)(llTime / llDiv));
00956 llTime = llTime % llDiv;
00957 }
00958 wsprintf(lpsz, TEXT("%d.%3.3d sec"),
00959 (LONG)llTime / 10000000,
00960 (LONG)((llTime % 10000000) / 10000));
00961 };
00962
00963 #endif
00964
00965 CDisp::CDisp(IPin *pPin)
00966 {
00967 PIN_INFO pi;
00968 TCHAR str[MAX_PIN_NAME];
00969 CLSID clsid;
00970
00971 if (pPin) {
00972 pPin->QueryPinInfo(&pi);
00973 pi.pFilter->GetClassID(&clsid);
00974 QueryPinInfoReleaseFilter(pi);
00975 #ifndef UNICODE
00976 WideCharToMultiByte(GetACP(), 0, pi.achName, lstrlenW(pi.achName) + 1,
00977 str, MAX_PIN_NAME, NULL, NULL);
00978 #else
00979 lstrcpy(str, pi.achName);
00980 #endif
00981 } else {
00982 lstrcpy(str, TEXT("NULL IPin"));
00983 }
00984
00985 m_pString = (PTCHAR) new TCHAR[lstrlen(str)+64];
00986 if (!m_pString) {
00987 return;
00988 }
00989
00990 wsprintf(m_pString, TEXT("%hs(%s)"), GuidNames[clsid], str);
00991 }
00992
00993 CDisp::CDisp(IUnknown *pUnk)
00994 {
00995 IBaseFilter *pf;
00996 HRESULT hr = pUnk->QueryInterface(IID_IBaseFilter, (void **)&pf);
00997 if(SUCCEEDED(hr))
00998 {
00999 FILTER_INFO fi;
01000 hr = pf->QueryFilterInfo(&fi);
01001 if(SUCCEEDED(hr))
01002 {
01003 QueryFilterInfoReleaseGraph(fi);
01004
01005 m_pString = new TCHAR[lstrlenW(fi.achName) + 1];
01006 if(m_pString)
01007 {
01008 wsprintf(m_pString, TEXT("%ls"), fi.achName);
01009 }
01010 }
01011
01012 pf->Release();
01013
01014 return;
01015 }
01016
01017 IPin *pp;
01018 hr = pUnk->QueryInterface(IID_IPin, (void **)&pp);
01019 if(SUCCEEDED(hr))
01020 {
01021 CDisp::CDisp(pp);
01022 pp->Release();
01023 return;
01024 }
01025 }
01026
01027 CDisp::~CDisp()
01028 {
01029 }
01030
01031 CDispBasic::~CDispBasic()
01032 {
01033 if (m_pString != m_String) {
01034 delete [] m_pString;
01035 }
01036 }
01037
01038 CDisp::CDisp(double d)
01039 {
01040 #ifdef DEBUG
01041 _stprintf(m_String, TEXT("%.16g"), d);
01042 #else
01043 wsprintf(m_String, TEXT("%d.%03d"), (int) d, (int) ((d - (int) d) * 1000));
01044 #endif
01045 }
01046
01047 #ifdef DEBUG
01048 void WINAPI DisplayType(LPTSTR label, const AM_MEDIA_TYPE *pmtIn)
01049 {
01050
01051
01052
01053 DbgLog((LOG_TRACE,5,TEXT("")));
01054 DbgLog((LOG_TRACE,2,TEXT("%s M type %s S type %s"), label,
01055 GuidNames[pmtIn->majortype],
01056 GuidNames[pmtIn->subtype]));
01057 DbgLog((LOG_TRACE,5,TEXT("Subtype description %s"),GetSubtypeName(&pmtIn->subtype)));
01058
01059
01060
01061 if (pmtIn->bTemporalCompression) {
01062 DbgLog((LOG_TRACE,5,TEXT("Temporally compressed")));
01063 } else {
01064 DbgLog((LOG_TRACE,5,TEXT("Not temporally compressed")));
01065 }
01066
01067 if (pmtIn->bFixedSizeSamples) {
01068 DbgLog((LOG_TRACE,5,TEXT("Sample size %d"),pmtIn->lSampleSize));
01069 } else {
01070 DbgLog((LOG_TRACE,5,TEXT("Variable size samples")));
01071 }
01072
01073 if (pmtIn->formattype == FORMAT_VideoInfo) {
01074
01075 BITMAPINFOHEADER *pbmi = HEADER(pmtIn->pbFormat);
01076 VIDEOINFOHEADER *pVideoInfo = (VIDEOINFOHEADER *)pmtIn->pbFormat;
01077
01078 DbgLog((LOG_TRACE,5,TEXT("Source rectangle (Left %d Top %d Right %d Bottom %d)"),
01079 pVideoInfo->rcSource.left,
01080 pVideoInfo->rcSource.top,
01081 pVideoInfo->rcSource.right,
01082 pVideoInfo->rcSource.bottom));
01083
01084 DbgLog((LOG_TRACE,5,TEXT("Target rectangle (Left %d Top %d Right %d Bottom %d)"),
01085 pVideoInfo->rcTarget.left,
01086 pVideoInfo->rcTarget.top,
01087 pVideoInfo->rcTarget.right,
01088 pVideoInfo->rcTarget.bottom));
01089
01090 DbgLog((LOG_TRACE,5,TEXT("Size of BITMAPINFO structure %d"),pbmi->biSize));
01091 if (pbmi->biCompression < 256) {
01092 DbgLog((LOG_TRACE,2,TEXT("%dx%dx%d bit (%d)"),
01093 pbmi->biWidth, pbmi->biHeight,
01094 pbmi->biBitCount, pbmi->biCompression));
01095 } else {
01096 DbgLog((LOG_TRACE,2,TEXT("%dx%dx%d bit '%4.4hs'"),
01097 pbmi->biWidth, pbmi->biHeight,
01098 pbmi->biBitCount, &pbmi->biCompression));
01099 }
01100
01101 DbgLog((LOG_TRACE,2,TEXT("Image size %d"),pbmi->biSizeImage));
01102 DbgLog((LOG_TRACE,5,TEXT("Planes %d"),pbmi->biPlanes));
01103 DbgLog((LOG_TRACE,5,TEXT("X Pels per metre %d"),pbmi->biXPelsPerMeter));
01104 DbgLog((LOG_TRACE,5,TEXT("Y Pels per metre %d"),pbmi->biYPelsPerMeter));
01105 DbgLog((LOG_TRACE,5,TEXT("Colours used %d"),pbmi->biClrUsed));
01106
01107 } else if (pmtIn->majortype == MEDIATYPE_Audio) {
01108 DbgLog((LOG_TRACE,2,TEXT(" Format type %hs"),
01109 GuidNames[pmtIn->formattype]));
01110 DbgLog((LOG_TRACE,2,TEXT(" Subtype %hs"),
01111 GuidNames[pmtIn->subtype]));
01112
01113 if ((pmtIn->subtype != MEDIASUBTYPE_MPEG1Packet)
01114 && (pmtIn->cbFormat >= sizeof(PCMWAVEFORMAT)))
01115 {
01116
01117
01118 WAVEFORMATEX *pwfx = (WAVEFORMATEX *) pmtIn->pbFormat;
01119 DbgLog((LOG_TRACE,2,TEXT("wFormatTag %u"), pwfx->wFormatTag));
01120 DbgLog((LOG_TRACE,2,TEXT("nChannels %u"), pwfx->nChannels));
01121 DbgLog((LOG_TRACE,2,TEXT("nSamplesPerSec %lu"), pwfx->nSamplesPerSec));
01122 DbgLog((LOG_TRACE,2,TEXT("nAvgBytesPerSec %lu"), pwfx->nAvgBytesPerSec));
01123 DbgLog((LOG_TRACE,2,TEXT("nBlockAlign %u"), pwfx->nBlockAlign));
01124 DbgLog((LOG_TRACE,2,TEXT("wBitsPerSample %u"), pwfx->wBitsPerSample));
01125
01126
01127
01128 if (pmtIn->cbFormat >= sizeof(WAVEFORMATEX)) {
01129 DbgLog((LOG_TRACE,2,TEXT("cbSize %u"), pwfx->cbSize));
01130 }
01131 } else {
01132 }
01133
01134 } else {
01135 DbgLog((LOG_TRACE,2,TEXT(" Format type %hs"),
01136 GuidNames[pmtIn->formattype]));
01137
01138 }
01139 }
01140
01141 void WINAPI DumpGraph(IFilterGraph *pGraph, DWORD dwLevel)
01142 {
01143 if( !pGraph )
01144 {
01145 return;
01146 }
01147
01148 IEnumFilters *pFilters;
01149
01150 DbgLog((LOG_TRACE,dwLevel,TEXT("DumpGraph [%x]"), pGraph));
01151
01152 if (FAILED(pGraph->EnumFilters(&pFilters))) {
01153 DbgLog((LOG_TRACE,dwLevel,TEXT("EnumFilters failed!")));
01154 }
01155
01156 IBaseFilter *pFilter;
01157 ULONG n;
01158 while (pFilters->Next(1, &pFilter, &n) == S_OK) {
01159 FILTER_INFO info;
01160
01161 if (FAILED(pFilter->QueryFilterInfo(&info))) {
01162 DbgLog((LOG_TRACE,dwLevel,TEXT(" Filter [%x] -- failed QueryFilterInfo"), pFilter));
01163 } else {
01164 QueryFilterInfoReleaseGraph(info);
01165
01166
01167
01168 DbgLog((LOG_TRACE,dwLevel,TEXT(" Filter [%x] '%ls'"), pFilter, info.achName));
01169
01170 IEnumPins *pins;
01171
01172 if (FAILED(pFilter->EnumPins(&pins))) {
01173 DbgLog((LOG_TRACE,dwLevel,TEXT("EnumPins failed!")));
01174 } else {
01175
01176 IPin *pPin;
01177 while (pins->Next(1, &pPin, &n) == S_OK) {
01178 PIN_INFO info;
01179
01180 if (FAILED(pPin->QueryPinInfo(&info))) {
01181 DbgLog((LOG_TRACE,dwLevel,TEXT(" Pin [%x] -- failed QueryPinInfo"), pPin));
01182 } else {
01183 QueryPinInfoReleaseFilter(info);
01184
01185 IPin *pPinConnected = NULL;
01186
01187 HRESULT hr = pPin->ConnectedTo(&pPinConnected);
01188
01189 if (pPinConnected) {
01190 DbgLog((LOG_TRACE,dwLevel,TEXT(" Pin [%x] '%ls' [%sput]")
01191 TEXT(" Connected to pin [%x]"),
01192 pPin, info.achName,
01193 info.dir == PINDIR_INPUT ? TEXT("In") : TEXT("Out"),
01194 pPinConnected));
01195
01196 pPinConnected->Release();
01197
01198
01199
01200 if (info.dir == PINDIR_OUTPUT) {
01201 AM_MEDIA_TYPE mt;
01202
01203 hr = pPin->ConnectionMediaType(&mt);
01204
01205 if (SUCCEEDED(hr)) {
01206 DisplayType(TEXT("Connection type"), &mt);
01207
01208 FreeMediaType(mt);
01209 }
01210 }
01211 } else {
01212 DbgLog((LOG_TRACE,dwLevel,
01213 TEXT(" Pin [%x] '%ls' [%sput]"),
01214 pPin, info.achName,
01215 info.dir == PINDIR_INPUT ? TEXT("In") : TEXT("Out")));
01216
01217 }
01218 }
01219
01220 pPin->Release();
01221
01222 }
01223
01224 pins->Release();
01225 }
01226
01227 }
01228
01229 pFilter->Release();
01230 }
01231
01232 pFilters->Release();
01233
01234 }
01235
01236 #endif
01237