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

📄 wxdebug.cpp

📁 basic class basic classbasic class
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//==========================================================================;
//
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
//  PURPOSE.
//
//
//--------------------------------------------------------------------------;

// ActiveX system debugging facilities

#define _WINDLL

#include <streams.h>
#include <stdarg.h>
#ifndef UNDER_CE
#include <stdio.h>
#endif // UNDER_CE

#ifdef DEBUG
#ifdef UNICODE
#ifndef _UNICODE
#define _UNICODE
#endif // _UNICODE
#endif // UNICODE
#endif // DEBUG

#include <tchar.h>

#ifdef DEBUG

const INT iDEBUGINFO = 512;                 // Used to format strings

HINSTANCE m_hInst;                          // Module instance handle
TCHAR m_ModuleName[iDEBUGINFO];             // Cut down module name

CRITICAL_SECTION m_CSDebug;                 // Controls access to list
DWORD m_dwNextCookie;                       // Next active object ID
ObjectDesc *pListHead = NULL;               // First active object
DWORD m_dwObjectCount;                      // Active object count
BOOL m_bInit = FALSE;                       // Have we been initialised
DWORD dwWaitTimeout = INFINITE;             // Default timeout value
DWORD dwTimeOffset;             // Time of first DbgLog call
bool g_fUseKASSERT = false;                 // don't create messagebox
bool g_fDbgInDllEntryPoint = false;


const TCHAR *pBaseKey = TEXT("SOFTWARE\\Debug");
const TCHAR *pGlobalKey = TEXT("GLOBAL");
static TCHAR *pUnknownName = TEXT("UNKNOWN");

TCHAR *TimeoutName = TEXT("TIMEOUT");

/* This sets the instance handle that the debug library uses to find
the module's file name from the Win32 GetModuleFileName function */


void WINAPI DbgInitialise(HINSTANCE hInst)
{
    InitializeCriticalSection(&m_CSDebug);
    m_bInit = TRUE;
    m_hInst = hInst;
    DbgInitModuleName();

	/*
	 * We can get to this point from (at least) two different code paths:
	 * Either DbgInitialise() is called by the base class DLL entry point,
	 * in which case hInst is a DLL instance handle, or we're called by
	 * DbgRegisterObjectCreation, in which case hInst is a proc handle.
	 * We don't want pass our handle to DEBUGREGISTER in the proc case
	 * since RegisterDbgZones only takes a DLL handle or NULL. We don't
	 * want to pass NULL either since that could cause a clash with
	 * debug zones defined by the application.
	 *
	 * If users want to take advantage of the debug zone implementation
	 * in the DirectShow base classes, then they either need to:
	 * 1. Implement their own DllMain() which calls DbgInitialise, or
	 * 2. Set their DLLENTRY=DllEntryPoint to use the base class default.
	 *
	 * NOTE: Option #2 above will not call static ctors/dtors, so if you
	 * have global C++ objects in your module you need to use option #1.
	 * You may also want to define your own dpCurSettings.
	 *
	 */

	if (hInst != (HINSTANCE)GetModuleHandle(NULL))
	{
		// only set up zones if hInst is a *DLL* instance handle
		DEBUGREGISTER((HINSTANCE)hInst);
	}
}


/* This is called to clear up any resources the debug library uses - at the
moment we delete our critical section and the object list. The values we
retrieve from the registry are all done during initialisation but we don't
go looking for update notifications while we are running, if the values
are changed then the application has to be restarted to pick them up */

void WINAPI DbgTerminate()
{
    DeleteCriticalSection(&m_CSDebug);
    m_bInit = FALSE;
}

/* This function has been deprecated, use DebugZones instead of registry keys */

void WINAPI DbgInitKeyLevels(HKEY hKey)
{
    DEBUGMSG(ZONE_ERROR,(TEXT("DbgInitKeyLevels() deprecated, use DebugZones instead\n")));
}


void WINAPI DbgOutString(LPCTSTR psz)
{
    OutputDebugString (psz);
}

/* This function has been deprecated, use DebugZones instead of registry keys */
void WINAPI DbgInitLogTo (
                          HKEY hKey)
{
    DEBUGMSG(ZONE_ERROR,(TEXT("DbgInitLogTo() deprecated, use DebugZones instead\n")));
}




/* Initialise the module file name */

void WINAPI DbgInitModuleName()
{
    TCHAR FullName[iDEBUGINFO];     // Load the full path and module name
    TCHAR *pName;                   // Searches from the end for a backslash
    
    GetModuleFileName(m_hInst,FullName,iDEBUGINFO);
    pName = _tcsrchr(FullName,'\\');
    if (pName == NULL) {
        pName = FullName;
    } else {
        pName++;
    }
    lstrcpy(m_ModuleName,pName);
}


/* Displays a message box if the condition evaluated to FALSE */

void WINAPI DbgAssert(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine)
{
    TCHAR szInfo[iDEBUGINFO];
    
#ifndef UNDER_CE
    wsprintf(szInfo, TEXT("%s \nAt line %d of %s\nContinue? (Cancel to debug)"),
        pCondition, iLine, pFileName);
    
    INT MsgId = MessageBox(NULL,szInfo,TEXT("ASSERT Failed"),
        MB_SYSTEMMODAL |
        MB_ICONHAND |
        MB_YESNOCANCEL |
        MB_SETFOREGROUND);
    switch (MsgId)
    {
    case IDNO:              /* Kill the application */
        
        FatalAppExit(FALSE, TEXT("Application terminated"));
        break;
        
    case IDCANCEL:          /* Break into the debugger */
        
        DebugBreak();
        break;
        
    case IDYES:             /* Ignore assertion continue execution */
        break;
    }
#else // !UNDER_CE
    wsprintf(szInfo, TEXT("%s \nAt line %d of %s\n"),
        pCondition, iLine, pFileName);
    OutputDebugString(szInfo);
    DebugBreak();
#endif // !UNDER_CE
}

/* Displays a message box at a break point */

void WINAPI DbgBreakPoint(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine)
{
    TCHAR szInfo[iDEBUGINFO];
    
#ifndef UNDER_CE
    wsprintf(szInfo, TEXT("%s \nAt line %d of %s\nContinue? (Cancel to debug)"),
        pCondition, iLine, pFileName);
    
    INT MsgId = MessageBox(NULL,szInfo,TEXT("Hard coded break point"),
        MB_SYSTEMMODAL |
        MB_ICONHAND |
        MB_YESNOCANCEL |
        MB_SETFOREGROUND);
    switch (MsgId)
    {
    case IDNO:              /* Kill the application */
        
        FatalAppExit(FALSE, TEXT("Application terminated"));
        break;
        
    case IDCANCEL:          /* Break into the debugger */
        
        DebugBreak();
        break;
        
    case IDYES:             /* Ignore break point continue execution */
        break;
    }
#else // !UNDER_CE
    wsprintf(szInfo, TEXT("%s \nAt line %d of %s\n"),
        pCondition, iLine, pFileName);
    OutputDebugString(szInfo);
    DebugBreak();
#endif // !UNDER_CE
}


/* 
 * Deprecated: Place-holder to pass the debugging info onto the console output
 *
 * Please Use DEBUGMSG instead of DbgLog & DbgLogInfo
 */
void WINAPI DbgLogInfo(DWORD Type, DWORD Level, const TCHAR *pFormat,...)
{
    if (Type) 
    {
        va_list va;
        va_start(va, pFormat);

        //
        // We're just "implementing" the Level argument for the LOG_TRACE parameter.
        // 
        // For the LOG_TRACE parameter, we need to verify if ZONE_INFO_MAX is also
        // turned on. If it is, all tracing information should be sent to output.
        // Otherwise, just send to output if user wanted selective info
        // (0 means more info; 5 means less info).
        //
        //   For all other LOG_<>, send it straight to NKDbgPrintfW.
        //
        if (Type != LOG_TRACE ||             // anything different than LOG_TRACE
            (Level < 3  ||  ZONE_INFO_MAX))  // LOG_TRACE is on and user wants high level of information, so verify if ZONE_INFO_MAX is turned on...
            
        {
            TCHAR rgchBuf[MAX_DEBUG_STR];
            _vsntprintf (rgchBuf, (sizeof(rgchBuf)/sizeof(rgchBuf[0])), pFormat, va);
            rgchBuf[MAX_DEBUG_STR-1] = '\0';
            OutputDebugStringW(rgchBuf);
        }
        va_end(va);
    }
}


/* 
 * Deprecated: Place-holder to pass the debugging info onto the console output.
 *
 * Please Use DEBUGMSG instead of DbgLog & DbgLogInfo
 */
void WINAPI DbgLogInfo(DWORD Type, const char *pFormat,...)
{
    if (Type)
    {
        char rgchBuf[MAX_DEBUG_STR];
        WCHAR wzBuf[MAX_DEBUG_STR];
        va_list va;
        va_start(va, pFormat);
        
        _vsnprintf (rgchBuf, MAX_DEBUG_STR, pFormat, va);
        rgchBuf[MAX_DEBUG_STR - 1] = '\0';      // guarantees NULL-terminated string
        MultiByteToWideChar(CP_ACP, 0, rgchBuf, MAX_DEBUG_STR, wzBuf, MAX_DEBUG_STR);
        OutputDebugString(wzBuf);
        va_end(va);
    }
}


/* If we are executing as a pure kernel filter we cannot display message
boxes to the user, this provides an alternative which puts the error
condition on the debugger output with a suitable eye catching message */

void WINAPI DbgKernelAssert(const TCHAR *pCondition,const TCHAR *pFileName,INT iLine)
{
    DbgLog((LOG_ERROR,0,TEXT("Assertion FAILED (%s) at line %d in file %s"),
        pCondition, iLine, pFileName));
    DebugBreak();
}



/* Each time we create an object derived from CBaseObject the constructor will
call us to register the creation of the new object. We are passed a string
description which we store away. We return a cookie that the constructor
uses to identify the object when it is destroyed later on. We update the
total number of active objects in the DLL mainly for debugging purposes */

DWORD WINAPI DbgRegisterObjectCreation(const TCHAR *pObjectName)
{
    /* If this fires you have a mixed DEBUG/RETAIL build */
    
    ASSERT(pObjectName);
    
    /* Create a place holder for this object description */
    
    ObjectDesc *pObject = new ObjectDesc;
    ASSERT(pObject);
    
    /* It is valid to pass a NULL object name */
    if (pObject == NULL) {
        return FALSE;
    }
    
    /* Check we have been initialised - we may not be initialised when we are
    being pulled in from an executable which has globally defined objects
    as they are created by the C++ run time before WinMain is called */
    
    if (m_bInit == FALSE) {
        DbgInitialise(GetModuleHandle(NULL));
    }
    
    /* Grab the list critical section */
    EnterCriticalSection(&m_CSDebug);
    
    /* If no name then default to UNKNOWN */
    if (pObjectName == NULL) {
        pObjectName = pUnknownName;
    }
    
    /* Put the new description at the head of the list */
    
    pObject->m_pName = pObjectName;
    pObject->m_dwCookie = ++m_dwNextCookie;
    pObject->m_pNext = pListHead;
    
    pListHead = pObject;
    m_dwObjectCount++;
    
    DWORD ObjectCookie = pObject->m_dwCookie;
    ASSERT(ObjectCookie);
    
    DbgLog((LOG_MEMORY,2,TEXT("Object created   %d (%s) %d Active"),
        pObject->m_dwCookie, pObjectName, m_dwObjectCount));
    
    LeaveCriticalSection(&m_CSDebug);
    return ObjectCookie;
}


/* This is called by the CBaseObject destructor when an object is about to be
destroyed, we are passed the cookie we returned during construction that
identifies this object. We scan the object list for a matching cookie and
remove the object if successful. We also update the active object count */

BOOL WINAPI DbgRegisterObjectDestruction(DWORD dwCookie)
{
    /* Grab the list critical section */
    EnterCriticalSection(&m_CSDebug);
    
    ObjectDesc *pObject = pListHead;
    ObjectDesc *pPrevious = NULL;
    
    /* Scan the object list looking for a cookie match */
    
    while (pObject) {
        if (pObject->m_dwCookie == dwCookie) {
            break;
        }
        pPrevious = pObject;
        pObject = pObject->m_pNext;
    }
    
    if (pObject == NULL) {
        DbgBreak("Apparently destroying a bogus object");
        LeaveCriticalSection(&m_CSDebug);
        return FALSE;
    }
    
    /* Is the object at the head of the list */
    
    if (pPrevious == NULL) {
        pListHead = pObject->m_pNext;
    } else {
        pPrevious->m_pNext = pObject->m_pNext;
    }
    
    /* Delete the object and update the housekeeping information */
    
    m_dwObjectCount--;
    DbgLog((LOG_MEMORY,2,TEXT("Object destroyed %d (%s) %d Active"),
        pObject->m_dwCookie, pObject->m_pName, m_dwObjectCount));
    
    delete pObject;
    LeaveCriticalSection(&m_CSDebug);
    return TRUE;
}


/* This runs through the active object list displaying their details */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -