~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/third_party/BaseClasses/wxdebug.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//------------------------------------------------------------------------------
2
 
// File: WXDebug.cpp
3
 
//
4
 
// Desc: DirectShow base classes - implements ActiveX system debugging
5
 
//       facilities.
6
 
//
7
 
// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
8
 
//------------------------------------------------------------------------------
9
 
 
10
 
#include <pjmedia-videodev/config.h>
11
 
 
12
 
#if defined(PJMEDIA_VIDEO_DEV_HAS_DSHOW) && PJMEDIA_VIDEO_DEV_HAS_DSHOW != 0
13
 
 
14
 
#define _WINDLL
15
 
 
16
 
#include <streams.h>
17
 
#include <stdarg.h>
18
 
#include <stdio.h>
19
 
#include <dvdmedia.h>
20
 
 
21
 
#ifdef DEBUG
22
 
#ifdef UNICODE
23
 
#ifndef _UNICODE
24
 
#define _UNICODE
25
 
#endif // _UNICODE
26
 
#endif // UNICODE
27
 
#endif // DEBUG
28
 
 
29
 
#include <tchar.h>
30
 
#include <strsafe.h>
31
 
 
32
 
#ifdef DEBUG
33
 
static void DisplayBITMAPINFO(const BITMAPINFOHEADER* pbmi);
34
 
static void DisplayRECT(LPCTSTR szLabel, const RECT& rc);
35
 
 
36
 
// The Win32 wsprintf() function writes a maximum of 1024 characters to it's output buffer.
37
 
// See the documentation for wsprintf()'s lpOut parameter for more information.
38
 
const INT iDEBUGINFO = 1024;                 // Used to format strings
39
 
 
40
 
/* For every module and executable we store a debugging level for each of
41
 
   the five categories (eg LOG_ERROR and LOG_TIMING). This makes it easy
42
 
   to isolate and debug individual modules without seeing everybody elses
43
 
   spurious debug output. The keys are stored in the registry under the
44
 
   HKEY_LOCAL_MACHINE\SOFTWARE\Debug\<Module Name>\<KeyName> key values
45
 
   NOTE these must be in the same order as their enumeration definition */
46
 
 
47
 
const LPCTSTR pKeyNames[] = {
48
 
    TEXT("TIMING"),      // Timing and performance measurements
49
 
    TEXT("TRACE"),       // General step point call tracing
50
 
    TEXT("MEMORY"),      // Memory and object allocation/destruction
51
 
    TEXT("LOCKING"),     // Locking/unlocking of critical sections
52
 
    TEXT("ERROR"),       // Debug error notification
53
 
    TEXT("CUSTOM1"),
54
 
    TEXT("CUSTOM2"),
55
 
    TEXT("CUSTOM3"),
56
 
    TEXT("CUSTOM4"),
57
 
    TEXT("CUSTOM5")
58
 
    };
59
 
 
60
 
const TCHAR CAutoTrace::_szEntering[] = TEXT("->: %s");
61
 
const TCHAR CAutoTrace::_szLeaving[]  = TEXT("<-: %s");
62
 
 
63
 
const INT iMAXLEVELS = NUMELMS(pKeyNames);  // Maximum debug categories
64
 
 
65
 
HINSTANCE m_hInst;                          // Module instance handle
66
 
TCHAR m_ModuleName[iDEBUGINFO];             // Cut down module name
67
 
DWORD m_Levels[iMAXLEVELS];                 // Debug level per category
68
 
CRITICAL_SECTION m_CSDebug;                 // Controls access to list
69
 
DWORD m_dwNextCookie;                       // Next active object ID
70
 
ObjectDesc *pListHead = NULL;               // First active object
71
 
DWORD m_dwObjectCount;                      // Active object count
72
 
BOOL m_bInit = FALSE;                       // Have we been initialised
73
 
HANDLE m_hOutput = INVALID_HANDLE_VALUE;    // Optional output written here
74
 
DWORD dwWaitTimeout = INFINITE;             // Default timeout value
75
 
DWORD dwTimeOffset;                         // Time of first DbgLog call
76
 
bool g_fUseKASSERT = false;                 // don't create messagebox
77
 
bool g_fDbgInDllEntryPoint = false;
78
 
bool g_fAutoRefreshLevels = false;
79
 
 
80
 
LPCTSTR pBaseKey = TEXT("SOFTWARE\\Microsoft\\DirectShow\\Debug");
81
 
LPCTSTR pGlobalKey = TEXT("GLOBAL");
82
 
static CHAR *pUnknownName = "UNKNOWN";
83
 
 
84
 
LPCTSTR TimeoutName = TEXT("TIMEOUT");
85
 
 
86
 
/* This sets the instance handle that the debug library uses to find
87
 
   the module's file name from the Win32 GetModuleFileName function */
88
 
 
89
 
void WINAPI DbgInitialise(HINSTANCE hInst)
90
 
{
91
 
    InitializeCriticalSection(&m_CSDebug);
92
 
    m_bInit = TRUE;
93
 
 
94
 
    m_hInst = hInst;
95
 
    DbgInitModuleName();
96
 
    if (GetProfileInt(m_ModuleName, TEXT("BreakOnLoad"), 0))
97
 
       DebugBreak();
98
 
    DbgInitModuleSettings(false);
99
 
    DbgInitGlobalSettings(true);
100
 
    dwTimeOffset = timeGetTime();
101
 
}
102
 
 
103
 
 
104
 
/* This is called to clear up any resources the debug library uses - at the
105
 
   moment we delete our critical section and the object list. The values we
106
 
   retrieve from the registry are all done during initialisation but we don't
107
 
   go looking for update notifications while we are running, if the values
108
 
   are changed then the application has to be restarted to pick them up */
109
 
 
110
 
void WINAPI DbgTerminate()
111
 
{
112
 
    if (m_hOutput != INVALID_HANDLE_VALUE) {
113
 
       EXECUTE_ASSERT(CloseHandle(m_hOutput));
114
 
       m_hOutput = INVALID_HANDLE_VALUE;
115
 
    }
116
 
    DeleteCriticalSection(&m_CSDebug);
117
 
    m_bInit = FALSE;
118
 
}
119
 
 
120
 
 
121
 
/* This is called by DbgInitLogLevels to read the debug settings
122
 
   for each logging category for this module from the registry */
123
 
 
124
 
void WINAPI DbgInitKeyLevels(HKEY hKey, bool fTakeMax)
125
 
{
126
 
    LONG lReturn;               // Create key return value
127
 
    LONG lKeyPos;               // Current key category
128
 
    DWORD dwKeySize;            // Size of the key value
129
 
    DWORD dwKeyType;            // Receives it's type
130
 
    DWORD dwKeyValue;           // This fields value
131
 
 
132
 
    /* Try and read a value for each key position in turn */
133
 
    for (lKeyPos = 0;lKeyPos < iMAXLEVELS;lKeyPos++) {
134
 
 
135
 
        dwKeySize = sizeof(DWORD);
136
 
        lReturn = RegQueryValueEx(
137
 
            hKey,                       // Handle to an open key
138
 
            pKeyNames[lKeyPos],         // Subkey name derivation
139
 
            NULL,                       // Reserved field
140
 
            &dwKeyType,                 // Returns the field type
141
 
            (LPBYTE) &dwKeyValue,       // Returns the field's value
142
 
            &dwKeySize );               // Number of bytes transferred
143
 
 
144
 
        /* If either the key was not available or it was not a DWORD value
145
 
           then we ensure only the high priority debug logging is output
146
 
           but we try and update the field to a zero filled DWORD value */
147
 
 
148
 
        if (lReturn != ERROR_SUCCESS || dwKeyType != REG_DWORD)  {
149
 
 
150
 
            dwKeyValue = 0;
151
 
            lReturn = RegSetValueEx(
152
 
                hKey,                   // Handle of an open key
153
 
                pKeyNames[lKeyPos],     // Address of subkey name
154
 
                (DWORD) 0,              // Reserved field
155
 
                REG_DWORD,              // Type of the key field
156
 
                (PBYTE) &dwKeyValue,    // Value for the field
157
 
                sizeof(DWORD));         // Size of the field buffer
158
 
 
159
 
            if (lReturn != ERROR_SUCCESS) {
160
 
                DbgLog((LOG_ERROR,1,TEXT("Could not create subkey %s"),pKeyNames[lKeyPos]));
161
 
                dwKeyValue = 0;
162
 
            }
163
 
        }
164
 
        if(fTakeMax)
165
 
        {
166
 
            m_Levels[lKeyPos] = max(dwKeyValue,m_Levels[lKeyPos]);
167
 
        }
168
 
        else
169
 
        {
170
 
            if((m_Levels[lKeyPos] & LOG_FORCIBLY_SET) == 0) {
171
 
                m_Levels[lKeyPos] = dwKeyValue;
172
 
            }
173
 
        }
174
 
    }
175
 
 
176
 
    /*  Read the timeout value for catching hangs */
177
 
    dwKeySize = sizeof(DWORD);
178
 
    lReturn = RegQueryValueEx(
179
 
        hKey,                       // Handle to an open key
180
 
        TimeoutName,                // Subkey name derivation
181
 
        NULL,                       // Reserved field
182
 
        &dwKeyType,                 // Returns the field type
183
 
        (LPBYTE) &dwWaitTimeout,    // Returns the field's value
184
 
        &dwKeySize );               // Number of bytes transferred
185
 
 
186
 
    /* If either the key was not available or it was not a DWORD value
187
 
       then we ensure only the high priority debug logging is output
188
 
       but we try and update the field to a zero filled DWORD value */
189
 
 
190
 
    if (lReturn != ERROR_SUCCESS || dwKeyType != REG_DWORD)  {
191
 
 
192
 
        dwWaitTimeout = INFINITE;
193
 
        lReturn = RegSetValueEx(
194
 
            hKey,                   // Handle of an open key
195
 
            TimeoutName,            // Address of subkey name
196
 
            (DWORD) 0,              // Reserved field
197
 
            REG_DWORD,              // Type of the key field
198
 
            (PBYTE) &dwWaitTimeout, // Value for the field
199
 
            sizeof(DWORD));         // Size of the field buffer
200
 
 
201
 
        if (lReturn != ERROR_SUCCESS) {
202
 
            DbgLog((LOG_ERROR,1,TEXT("Could not create subkey %s"),pKeyNames[lKeyPos]));
203
 
            dwWaitTimeout = INFINITE;
204
 
        }
205
 
    }
206
 
}
207
 
 
208
 
void WINAPI DbgOutString(LPCTSTR psz)
209
 
{
210
 
    if (m_hOutput != INVALID_HANDLE_VALUE) {
211
 
        UINT  cb = lstrlen(psz);
212
 
        DWORD dw;
213
 
#ifdef UNICODE
214
 
        CHAR szDest[2048];
215
 
        WideCharToMultiByte(CP_ACP, 0, psz, -1, szDest, NUMELMS(szDest), 0, 0);
216
 
        WriteFile (m_hOutput, szDest, cb, &dw, NULL);
217
 
#else
218
 
        WriteFile (m_hOutput, psz, cb, &dw, NULL);
219
 
#endif
220
 
    } else {
221
 
        OutputDebugString (psz);
222
 
    }
223
 
}
224
 
 
225
 
 
226
 
 
227
 
 
228
 
HRESULT  DbgUniqueProcessName(LPCTSTR inName, LPTSTR outName)
229
 
{
230
 
    HRESULT hr = S_OK;
231
 
    const TCHAR *pIn = inName;
232
 
    int dotPos = -1;
233
 
 
234
 
    //scan the input and record the last '.' position
235
 
    while (*pIn && (pIn - inName) < MAX_PATH)
236
 
    {
237
 
        if ( TEXT('.') == *pIn )
238
 
            dotPos = (int)(pIn-inName);
239
 
        ++pIn;
240
 
    }
241
 
 
242
 
    if (*pIn) //input should be zero-terminated within MAX_PATH
243
 
        return E_INVALIDARG;
244
 
 
245
 
    DWORD dwProcessId = GetCurrentProcessId();
246
 
 
247
 
    if (dotPos < 0)
248
 
    {
249
 
        //no extension in the input, appending process id to the input
250
 
        hr = StringCchPrintf(outName, MAX_PATH, TEXT("%s_%d"), inName, dwProcessId);
251
 
    }
252
 
    else
253
 
    {
254
 
        TCHAR pathAndBasename[MAX_PATH] = {0};
255
 
 
256
 
        //there's an extension  - zero-terminate the path and basename first by copying
257
 
        hr = StringCchCopyN(pathAndBasename, MAX_PATH, inName, (size_t)dotPos);
258
 
 
259
 
        //re-combine path, basename and extension with processId appended to a basename
260
 
        if (SUCCEEDED(hr))
261
 
            hr = StringCchPrintf(outName, MAX_PATH, TEXT("%s_%d%s"), pathAndBasename, dwProcessId, inName + dotPos);
262
 
    }
263
 
 
264
 
    return hr;
265
 
}
266
 
 
267
 
 
268
 
/* Called by DbgInitGlobalSettings to setup alternate logging destinations
269
 
 */
270
 
 
271
 
void WINAPI DbgInitLogTo (
272
 
    HKEY hKey)
273
 
{
274
 
    LONG  lReturn;
275
 
    DWORD dwKeyType;
276
 
    DWORD dwKeySize;
277
 
    TCHAR szFile[MAX_PATH] = {0};
278
 
    static const TCHAR cszKey[] = TEXT("LogToFile");
279
 
 
280
 
    dwKeySize = MAX_PATH;
281
 
    lReturn = RegQueryValueEx(
282
 
        hKey,                       // Handle to an open key
283
 
        cszKey,                     // Subkey name derivation
284
 
        NULL,                       // Reserved field
285
 
        &dwKeyType,                 // Returns the field type
286
 
        (LPBYTE) szFile,            // Returns the field's value
287
 
        &dwKeySize);                // Number of bytes transferred
288
 
 
289
 
    // create an empty key if it does not already exist
290
 
    //
291
 
    if (lReturn != ERROR_SUCCESS || dwKeyType != REG_SZ)
292
 
       {
293
 
       dwKeySize = sizeof(TCHAR);
294
 
       lReturn = RegSetValueEx(
295
 
            hKey,                   // Handle of an open key
296
 
            cszKey,                 // Address of subkey name
297
 
            (DWORD) 0,              // Reserved field
298
 
            REG_SZ,                 // Type of the key field
299
 
            (PBYTE)szFile,          // Value for the field
300
 
            dwKeySize);            // Size of the field buffer
301
 
       }
302
 
 
303
 
    // if an output-to was specified.  try to open it.
304
 
    //
305
 
    if (m_hOutput != INVALID_HANDLE_VALUE) {
306
 
       EXECUTE_ASSERT(CloseHandle (m_hOutput));
307
 
       m_hOutput = INVALID_HANDLE_VALUE;
308
 
    }
309
 
    if (szFile[0] != 0)
310
 
       {
311
 
       if (!lstrcmpi(szFile, TEXT("Console"))) {
312
 
          m_hOutput = GetStdHandle (STD_OUTPUT_HANDLE);
313
 
          if (m_hOutput == INVALID_HANDLE_VALUE) {
314
 
             AllocConsole ();
315
 
             m_hOutput = GetStdHandle (STD_OUTPUT_HANDLE);
316
 
          }
317
 
          SetConsoleTitle (TEXT("ActiveX Debug Output"));
318
 
       } else if (szFile[0] &&
319
 
                lstrcmpi(szFile, TEXT("Debug")) &&
320
 
                lstrcmpi(szFile, TEXT("Debugger")) &&
321
 
                lstrcmpi(szFile, TEXT("Deb")))
322
 
          {
323
 
            m_hOutput = CreateFile(szFile, GENERIC_WRITE,
324
 
                                 FILE_SHARE_READ,
325
 
                                 NULL, OPEN_ALWAYS,
326
 
                                 FILE_ATTRIBUTE_NORMAL,
327
 
                                 NULL);
328
 
 
329
 
            if (INVALID_HANDLE_VALUE == m_hOutput &&
330
 
                GetLastError() == ERROR_SHARING_VIOLATION)
331
 
            {
332
 
               TCHAR uniqueName[MAX_PATH] = {0};
333
 
               if (SUCCEEDED(DbgUniqueProcessName(szFile, uniqueName)))
334
 
               {
335
 
                    m_hOutput = CreateFile(uniqueName, GENERIC_WRITE,
336
 
                                         FILE_SHARE_READ,
337
 
                                         NULL, OPEN_ALWAYS,
338
 
                                         FILE_ATTRIBUTE_NORMAL,
339
 
                                         NULL);
340
 
               }
341
 
            }
342
 
 
343
 
            if (INVALID_HANDLE_VALUE != m_hOutput)
344
 
            {
345
 
              static const TCHAR cszBar[] = TEXT("\r\n\r\n=====DbgInitialize()=====\r\n\r\n");
346
 
              SetFilePointer (m_hOutput, 0, NULL, FILE_END);
347
 
              DbgOutString (cszBar);
348
 
            }
349
 
          }
350
 
       }
351
 
}
352
 
 
353
 
 
354
 
 
355
 
/* This is called by DbgInitLogLevels to read the global debug settings for
356
 
   each logging category for this module from the registry. Normally each
357
 
   module has it's own values set for it's different debug categories but
358
 
   setting the global SOFTWARE\Debug\Global applies them to ALL modules */
359
 
 
360
 
void WINAPI DbgInitGlobalSettings(bool fTakeMax)
361
 
{
362
 
    LONG lReturn;               // Create key return value
363
 
    TCHAR szInfo[iDEBUGINFO];   // Constructs key names
364
 
    HKEY hGlobalKey;            // Global override key
365
 
 
366
 
    /* Construct the global base key name */
367
 
    (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("%s\\%s"),pBaseKey,pGlobalKey);
368
 
 
369
 
    /* Create or open the key for this module */
370
 
    lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE,   // Handle of an open key
371
 
                             szInfo,               // Address of subkey name
372
 
                             (DWORD) 0,            // Reserved value
373
 
                             NULL,                 // Address of class name
374
 
                             (DWORD) 0,            // Special options flags
375
 
                             GENERIC_READ | GENERIC_WRITE,   // Desired security access
376
 
                             NULL,                 // Key security descriptor
377
 
                             &hGlobalKey,          // Opened handle buffer
378
 
                             NULL);                // What really happened
379
 
 
380
 
    if (lReturn != ERROR_SUCCESS) {
381
 
        lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE,   // Handle of an open key
382
 
                                 szInfo,               // Address of subkey name
383
 
                                 (DWORD) 0,            // Reserved value
384
 
                                 NULL,                 // Address of class name
385
 
                                 (DWORD) 0,            // Special options flags
386
 
                                 GENERIC_READ,         // Desired security access
387
 
                                 NULL,                 // Key security descriptor
388
 
                                 &hGlobalKey,          // Opened handle buffer
389
 
                                 NULL);                // What really happened
390
 
        if (lReturn != ERROR_SUCCESS) {
391
 
            DbgLog((LOG_ERROR,1,TEXT("Could not access GLOBAL module key")));
392
 
        }
393
 
        return;
394
 
    }
395
 
 
396
 
    DbgInitKeyLevels(hGlobalKey, fTakeMax);
397
 
    RegCloseKey(hGlobalKey);
398
 
}
399
 
 
400
 
 
401
 
/* This sets the debugging log levels for the different categories. We start
402
 
   by opening (or creating if not already available) the SOFTWARE\Debug key
403
 
   that all these settings live under. We then look at the global values
404
 
   set under SOFTWARE\Debug\Global which apply on top of the individual
405
 
   module settings. We then load the individual module registry settings */
406
 
 
407
 
void WINAPI DbgInitModuleSettings(bool fTakeMax)
408
 
{
409
 
    LONG lReturn;               // Create key return value
410
 
    TCHAR szInfo[iDEBUGINFO];   // Constructs key names
411
 
    HKEY hModuleKey;            // Module key handle
412
 
 
413
 
    /* Construct the base key name */
414
 
    (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("%s\\%s"),pBaseKey,m_ModuleName);
415
 
 
416
 
    /* Create or open the key for this module */
417
 
    lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE,   // Handle of an open key
418
 
                             szInfo,               // Address of subkey name
419
 
                             (DWORD) 0,            // Reserved value
420
 
                             NULL,                 // Address of class name
421
 
                             (DWORD) 0,            // Special options flags
422
 
                             GENERIC_READ | GENERIC_WRITE, // Desired security access
423
 
                             NULL,                 // Key security descriptor
424
 
                             &hModuleKey,          // Opened handle buffer
425
 
                             NULL);                // What really happened
426
 
 
427
 
    if (lReturn != ERROR_SUCCESS) {
428
 
        lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE,   // Handle of an open key
429
 
                                 szInfo,               // Address of subkey name
430
 
                                 (DWORD) 0,            // Reserved value
431
 
                                 NULL,                 // Address of class name
432
 
                                 (DWORD) 0,            // Special options flags
433
 
                                 GENERIC_READ,         // Desired security access
434
 
                                 NULL,                 // Key security descriptor
435
 
                                 &hModuleKey,          // Opened handle buffer
436
 
                                 NULL);                // What really happened
437
 
        if (lReturn != ERROR_SUCCESS) {
438
 
            DbgLog((LOG_ERROR,1,TEXT("Could not access module key")));
439
 
        }
440
 
        return;
441
 
    }
442
 
 
443
 
    DbgInitLogTo(hModuleKey);
444
 
    DbgInitKeyLevels(hModuleKey, fTakeMax);
445
 
    RegCloseKey(hModuleKey);
446
 
}
447
 
 
448
 
 
449
 
/* Initialise the module file name */
450
 
 
451
 
void WINAPI DbgInitModuleName()
452
 
{
453
 
    TCHAR FullName[iDEBUGINFO];     // Load the full path and module name
454
 
    LPTSTR pName;                   // Searches from the end for a backslash
455
 
 
456
 
    GetModuleFileName(m_hInst,FullName,iDEBUGINFO);
457
 
    pName = _tcsrchr(FullName,'\\');
458
 
    if (pName == NULL) {
459
 
        pName = FullName;
460
 
    } else {
461
 
        pName++;
462
 
    }
463
 
    (void)StringCchCopy(m_ModuleName,NUMELMS(m_ModuleName), pName);
464
 
}
465
 
 
466
 
struct MsgBoxMsg
467
 
{
468
 
    HWND hwnd;
469
 
    LPCTSTR szTitle;
470
 
    LPCTSTR szMessage;
471
 
    DWORD dwFlags;
472
 
    INT iResult;
473
 
};
474
 
 
475
 
//
476
 
// create a thread to call MessageBox(). calling MessageBox() on
477
 
// random threads at bad times can confuse the host (eg IE).
478
 
//
479
 
DWORD WINAPI MsgBoxThread(
480
 
  __inout LPVOID lpParameter   // thread data
481
 
  )
482
 
{
483
 
    MsgBoxMsg *pmsg = (MsgBoxMsg *)lpParameter;
484
 
    pmsg->iResult = MessageBox(
485
 
        pmsg->hwnd,
486
 
        pmsg->szTitle,
487
 
        pmsg->szMessage,
488
 
        pmsg->dwFlags);
489
 
 
490
 
    return 0;
491
 
}
492
 
 
493
 
INT MessageBoxOtherThread(
494
 
    HWND hwnd,
495
 
    LPCTSTR szTitle,
496
 
    LPCTSTR szMessage,
497
 
    DWORD dwFlags)
498
 
{
499
 
    if(g_fDbgInDllEntryPoint)
500
 
    {
501
 
        // can't wait on another thread because we have the loader
502
 
        // lock held in the dll entry point.
503
 
        // This can crash sometimes so just skip it
504
 
        // return MessageBox(hwnd, szTitle, szMessage, dwFlags);
505
 
        return IDCANCEL;
506
 
    }
507
 
    else
508
 
    {
509
 
        MsgBoxMsg msg = {hwnd, szTitle, szMessage, dwFlags, 0};
510
 
        DWORD dwid;
511
 
        HANDLE hThread = CreateThread(
512
 
            0,                      // security
513
 
            0,                      // stack size
514
 
            MsgBoxThread,
515
 
            (void *)&msg,           // arg
516
 
            0,                      // flags
517
 
            &dwid);
518
 
        if(hThread)
519
 
        {
520
 
            WaitForSingleObject(hThread, INFINITE);
521
 
            CloseHandle(hThread);
522
 
            return msg.iResult;
523
 
        }
524
 
 
525
 
        // break into debugger on failure.
526
 
        return IDCANCEL;
527
 
    }
528
 
}
529
 
 
530
 
/* Displays a message box if the condition evaluated to FALSE */
531
 
 
532
 
void WINAPI DbgAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine)
533
 
{
534
 
    if(g_fUseKASSERT)
535
 
    {
536
 
        DbgKernelAssert(pCondition, pFileName, iLine);
537
 
    }
538
 
    else
539
 
    {
540
 
 
541
 
        TCHAR szInfo[iDEBUGINFO];
542
 
 
543
 
        (void)StringCchPrintf(szInfo, NUMELMS(szInfo),TEXT("%s \nAt line %d of %s\nContinue? (Cancel to debug)"),
544
 
                 pCondition, iLine, pFileName);
545
 
 
546
 
        INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("ASSERT Failed"),
547
 
                                          MB_SYSTEMMODAL |
548
 
                                          MB_ICONHAND |
549
 
                                          MB_YESNOCANCEL |
550
 
                                          MB_SETFOREGROUND);
551
 
        switch (MsgId)
552
 
        {
553
 
          case IDNO:              /* Kill the application */
554
 
 
555
 
              FatalAppExit(FALSE, TEXT("Application terminated"));
556
 
              break;
557
 
 
558
 
          case IDCANCEL:          /* Break into the debugger */
559
 
 
560
 
              DebugBreak();
561
 
              break;
562
 
 
563
 
          case IDYES:             /* Ignore assertion continue execution */
564
 
              break;
565
 
        }
566
 
    }
567
 
}
568
 
 
569
 
/* Displays a message box at a break point */
570
 
 
571
 
void WINAPI DbgBreakPoint(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine)
572
 
{
573
 
    if(g_fUseKASSERT)
574
 
    {
575
 
        DbgKernelAssert(pCondition, pFileName, iLine);
576
 
    }
577
 
    else
578
 
    {
579
 
        TCHAR szInfo[iDEBUGINFO];
580
 
 
581
 
        (void)StringCchPrintf(szInfo, NUMELMS(szInfo),TEXT("%s \nAt line %d of %s\nContinue? (Cancel to debug)"),
582
 
                 pCondition, iLine, pFileName);
583
 
 
584
 
        INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("Hard coded break point"),
585
 
                                          MB_SYSTEMMODAL |
586
 
                                          MB_ICONHAND |
587
 
                                          MB_YESNOCANCEL |
588
 
                                          MB_SETFOREGROUND);
589
 
        switch (MsgId)
590
 
        {
591
 
          case IDNO:              /* Kill the application */
592
 
 
593
 
              FatalAppExit(FALSE, TEXT("Application terminated"));
594
 
              break;
595
 
 
596
 
          case IDCANCEL:          /* Break into the debugger */
597
 
 
598
 
              DebugBreak();
599
 
              break;
600
 
 
601
 
          case IDYES:             /* Ignore break point continue execution */
602
 
              break;
603
 
        }
604
 
    }
605
 
}
606
 
 
607
 
void WINAPI DbgBreakPoint(LPCTSTR pFileName,INT iLine,__format_string LPCTSTR szFormatString,...)
608
 
{
609
 
    // A debug break point message can have at most 2000 characters if
610
 
    // ANSI or UNICODE characters are being used.  A debug break point message
611
 
    // can have between 1000 and 2000 double byte characters in it.  If a
612
 
    // particular message needs more characters, then the value of this constant
613
 
    // should be increased.
614
 
    const DWORD MAX_BREAK_POINT_MESSAGE_SIZE = 2000;
615
 
 
616
 
    TCHAR szBreakPointMessage[MAX_BREAK_POINT_MESSAGE_SIZE];
617
 
 
618
 
    va_list va;
619
 
    va_start( va, szFormatString );
620
 
 
621
 
    HRESULT hr = StringCchVPrintf( szBreakPointMessage, NUMELMS(szBreakPointMessage), szFormatString, va );
622
 
 
623
 
    va_end(va);
624
 
 
625
 
    if( FAILED(hr) ) {
626
 
        DbgBreak( "ERROR in DbgBreakPoint().  The variable length debug message could not be displayed because StringCchVPrintf() failed." );
627
 
        return;
628
 
    }
629
 
 
630
 
    ::DbgBreakPoint( szBreakPointMessage, pFileName, iLine );
631
 
}
632
 
 
633
 
 
634
 
/* When we initialised the library we stored in the m_Levels array the current
635
 
   debug output level for this module for each of the five categories. When
636
 
   some debug logging is sent to us it can be sent with a combination of the
637
 
   categories (if it is applicable to many for example) in which case we map
638
 
   the type's categories into their current debug levels and see if any of
639
 
   them can be accepted. The function looks at each bit position in turn from
640
 
   the input type field and then compares it's debug level with the modules.
641
 
 
642
 
   A level of 0 means that output is always sent to the debugger.  This is
643
 
   due to producing output if the input level is <= m_Levels.
644
 
*/
645
 
 
646
 
 
647
 
BOOL WINAPI DbgCheckModuleLevel(DWORD Type,DWORD Level)
648
 
{
649
 
    if(g_fAutoRefreshLevels)
650
 
    {
651
 
        // re-read the registry every second. We cannot use RegNotify() to
652
 
        // notice registry changes because it's not available on win9x.
653
 
        static DWORD g_dwLastRefresh = 0;
654
 
        DWORD dwTime = timeGetTime();
655
 
        if(dwTime - g_dwLastRefresh > 1000) {
656
 
            g_dwLastRefresh = dwTime;
657
 
 
658
 
            // there's a race condition: multiple threads could update the
659
 
            // values. plus read and write not synchronized. no harm
660
 
            // though.
661
 
            DbgInitModuleSettings(false);
662
 
        }
663
 
    }
664
 
 
665
 
 
666
 
    DWORD Mask = 0x01;
667
 
 
668
 
    // If no valid bits are set return FALSE
669
 
    if ((Type & ((1<<iMAXLEVELS)-1))) {
670
 
 
671
 
        // speed up unconditional output.
672
 
        if (0==Level)
673
 
            return(TRUE);
674
 
 
675
 
        for (LONG lKeyPos = 0;lKeyPos < iMAXLEVELS;lKeyPos++) {
676
 
            if (Type & Mask) {
677
 
                if (Level <= (m_Levels[lKeyPos] & ~LOG_FORCIBLY_SET)) {
678
 
                    return TRUE;
679
 
                }
680
 
            }
681
 
            Mask <<= 1;
682
 
        }
683
 
    }
684
 
    return FALSE;
685
 
}
686
 
 
687
 
 
688
 
/* Set debug levels to a given value */
689
 
 
690
 
void WINAPI DbgSetModuleLevel(DWORD Type, DWORD Level)
691
 
{
692
 
    DWORD Mask = 0x01;
693
 
 
694
 
    for (LONG lKeyPos = 0;lKeyPos < iMAXLEVELS;lKeyPos++) {
695
 
        if (Type & Mask) {
696
 
            m_Levels[lKeyPos] = Level | LOG_FORCIBLY_SET;
697
 
        }
698
 
        Mask <<= 1;
699
 
    }
700
 
}
701
 
 
702
 
/* whether to check registry values periodically. this isn't turned
703
 
   automatically because of the potential performance hit. */
704
 
void WINAPI DbgSetAutoRefreshLevels(bool fAuto)
705
 
{
706
 
    g_fAutoRefreshLevels = fAuto;
707
 
}
708
 
 
709
 
#ifdef UNICODE
710
 
//
711
 
// warning -- this function is implemented twice for ansi applications
712
 
// linking to the unicode library
713
 
//
714
 
void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCSTR pFormat,...)
715
 
{
716
 
    /* Check the current level for this type combination */
717
 
 
718
 
    BOOL bAccept = DbgCheckModuleLevel(Type,Level);
719
 
    if (bAccept == FALSE) {
720
 
        return;
721
 
    }
722
 
 
723
 
    TCHAR szInfo[2000];
724
 
 
725
 
    /* Format the variable length parameter list */
726
 
 
727
 
    va_list va;
728
 
    va_start(va, pFormat);
729
 
 
730
 
    (void)StringCchPrintf(szInfo, NUMELMS(szInfo),
731
 
             TEXT("%s(tid %x) %8d : "),
732
 
             m_ModuleName,
733
 
             GetCurrentThreadId(), timeGetTime() - dwTimeOffset);
734
 
 
735
 
    CHAR szInfoA[2000];
736
 
    WideCharToMultiByte(CP_ACP, 0, szInfo, -1, szInfoA, NUMELMS(szInfoA), 0, 0);
737
 
 
738
 
    (void)StringCchVPrintfA(szInfoA + lstrlenA(szInfoA), NUMELMS(szInfoA) - lstrlenA(szInfoA), pFormat, va);
739
 
    (void)StringCchCatA(szInfoA, NUMELMS(szInfoA), "\r\n");
740
 
 
741
 
    WCHAR wszOutString[2000];
742
 
    MultiByteToWideChar(CP_ACP, 0, szInfoA, -1, wszOutString, NUMELMS(wszOutString));
743
 
    DbgOutString(wszOutString);
744
 
 
745
 
    va_end(va);
746
 
}
747
 
 
748
 
void WINAPI DbgAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine)
749
 
{
750
 
    if(g_fUseKASSERT)
751
 
    {
752
 
        DbgKernelAssert(pCondition, pFileName, iLine);
753
 
    }
754
 
    else
755
 
    {
756
 
 
757
 
        TCHAR szInfo[iDEBUGINFO];
758
 
 
759
 
        (void)StringCchPrintf(szInfo, NUMELMS(szInfo), TEXT("%hs \nAt line %d of %hs\nContinue? (Cancel to debug)"),
760
 
                 pCondition, iLine, pFileName);
761
 
 
762
 
        INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("ASSERT Failed"),
763
 
                                          MB_SYSTEMMODAL |
764
 
                                          MB_ICONHAND |
765
 
                                          MB_YESNOCANCEL |
766
 
                                          MB_SETFOREGROUND);
767
 
        switch (MsgId)
768
 
        {
769
 
          case IDNO:              /* Kill the application */
770
 
 
771
 
              FatalAppExit(FALSE, TEXT("Application terminated"));
772
 
              break;
773
 
 
774
 
          case IDCANCEL:          /* Break into the debugger */
775
 
 
776
 
              DebugBreak();
777
 
              break;
778
 
 
779
 
          case IDYES:             /* Ignore assertion continue execution */
780
 
              break;
781
 
        }
782
 
    }
783
 
}
784
 
 
785
 
/* Displays a message box at a break point */
786
 
 
787
 
void WINAPI DbgBreakPoint(LPCSTR pCondition,LPCSTR pFileName,INT iLine)
788
 
{
789
 
    if(g_fUseKASSERT)
790
 
    {
791
 
        DbgKernelAssert(pCondition, pFileName, iLine);
792
 
    }
793
 
    else
794
 
    {
795
 
        TCHAR szInfo[iDEBUGINFO];
796
 
 
797
 
        (void)StringCchPrintf(szInfo, NUMELMS(szInfo),TEXT("%hs \nAt line %d of %hs\nContinue? (Cancel to debug)"),
798
 
                 pCondition, iLine, pFileName);
799
 
 
800
 
        INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("Hard coded break point"),
801
 
                                          MB_SYSTEMMODAL |
802
 
                                          MB_ICONHAND |
803
 
                                          MB_YESNOCANCEL |
804
 
                                          MB_SETFOREGROUND);
805
 
        switch (MsgId)
806
 
        {
807
 
          case IDNO:              /* Kill the application */
808
 
 
809
 
              FatalAppExit(FALSE, TEXT("Application terminated"));
810
 
              break;
811
 
 
812
 
          case IDCANCEL:          /* Break into the debugger */
813
 
 
814
 
              DebugBreak();
815
 
              break;
816
 
 
817
 
          case IDYES:             /* Ignore break point continue execution */
818
 
              break;
819
 
        }
820
 
    }
821
 
}
822
 
 
823
 
void WINAPI DbgKernelAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine)
824
 
{
825
 
    DbgLog((LOG_ERROR,0,TEXT("Assertion FAILED (%hs) at line %d in file %hs"),
826
 
           pCondition, iLine, pFileName));
827
 
    DebugBreak();
828
 
}
829
 
 
830
 
#endif
831
 
 
832
 
/* Print a formatted string to the debugger prefixed with this module's name
833
 
   Because the COMBASE classes are linked statically every module loaded will
834
 
   have their own copy of this code. It therefore helps if the module name is
835
 
   included on the output so that the offending code can be easily found */
836
 
 
837
 
//
838
 
// warning -- this function is implemented twice for ansi applications
839
 
// linking to the unicode library
840
 
//
841
 
void WINAPI DbgLogInfo(DWORD Type,DWORD Level,LPCTSTR pFormat,...)
842
 
{
843
 
 
844
 
    /* Check the current level for this type combination */
845
 
 
846
 
    BOOL bAccept = DbgCheckModuleLevel(Type,Level);
847
 
    if (bAccept == FALSE) {
848
 
        return;
849
 
    }
850
 
 
851
 
    TCHAR szInfo[2000];
852
 
 
853
 
    /* Format the variable length parameter list */
854
 
 
855
 
    va_list va;
856
 
    va_start(va, pFormat);
857
 
 
858
 
    (void)StringCchPrintf(szInfo, NUMELMS(szInfo),
859
 
             TEXT("%s(tid %x) %8d : "),
860
 
             m_ModuleName,
861
 
             GetCurrentThreadId(), timeGetTime() - dwTimeOffset);
862
 
 
863
 
    (void)StringCchVPrintf(szInfo + lstrlen(szInfo), NUMELMS(szInfo) - lstrlen(szInfo), pFormat, va);
864
 
    (void)StringCchCat(szInfo, NUMELMS(szInfo), TEXT("\r\n"));
865
 
    DbgOutString(szInfo);
866
 
 
867
 
    va_end(va);
868
 
}
869
 
 
870
 
 
871
 
/* If we are executing as a pure kernel filter we cannot display message
872
 
   boxes to the user, this provides an alternative which puts the error
873
 
   condition on the debugger output with a suitable eye catching message */
874
 
 
875
 
void WINAPI DbgKernelAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine)
876
 
{
877
 
    DbgLog((LOG_ERROR,0,TEXT("Assertion FAILED (%s) at line %d in file %s"),
878
 
           pCondition, iLine, pFileName));
879
 
    DebugBreak();
880
 
}
881
 
 
882
 
 
883
 
 
884
 
/* Each time we create an object derived from CBaseObject the constructor will
885
 
   call us to register the creation of the new object. We are passed a string
886
 
   description which we store away. We return a cookie that the constructor
887
 
   uses to identify the object when it is destroyed later on. We update the
888
 
   total number of active objects in the DLL mainly for debugging purposes */
889
 
 
890
 
DWORD WINAPI DbgRegisterObjectCreation(LPCSTR szObjectName,
891
 
                                       LPCWSTR wszObjectName)
892
 
{
893
 
    /* If this fires you have a mixed DEBUG/RETAIL build */
894
 
 
895
 
    ASSERT(!!szObjectName ^ !!wszObjectName);
896
 
 
897
 
    /* Create a place holder for this object description */
898
 
 
899
 
    ObjectDesc *pObject = new ObjectDesc;
900
 
    ASSERT(pObject);
901
 
 
902
 
    /* It is valid to pass a NULL object name */
903
 
    if (pObject == NULL) {
904
 
        return FALSE;
905
 
    }
906
 
 
907
 
    /* Check we have been initialised - we may not be initialised when we are
908
 
       being pulled in from an executable which has globally defined objects
909
 
       as they are created by the C++ run time before WinMain is called */
910
 
 
911
 
    if (m_bInit == FALSE) {
912
 
        DbgInitialise(GetModuleHandle(NULL));
913
 
    }
914
 
 
915
 
    /* Grab the list critical section */
916
 
    EnterCriticalSection(&m_CSDebug);
917
 
 
918
 
    /* If no name then default to UNKNOWN */
919
 
    if (!szObjectName && !wszObjectName) {
920
 
        szObjectName = pUnknownName;
921
 
    }
922
 
 
923
 
    /* Put the new description at the head of the list */
924
 
 
925
 
    pObject->m_szName = szObjectName;
926
 
    pObject->m_wszName = wszObjectName;
927
 
    pObject->m_dwCookie = ++m_dwNextCookie;
928
 
    pObject->m_pNext = pListHead;
929
 
 
930
 
    pListHead = pObject;
931
 
    m_dwObjectCount++;
932
 
 
933
 
    DWORD ObjectCookie = pObject->m_dwCookie;
934
 
    ASSERT(ObjectCookie);
935
 
 
936
 
    if(wszObjectName) {
937
 
        DbgLog((LOG_MEMORY,2,TEXT("Object created   %d (%ls) %d Active"),
938
 
                pObject->m_dwCookie, wszObjectName, m_dwObjectCount));
939
 
    } else {
940
 
        DbgLog((LOG_MEMORY,2,TEXT("Object created   %d (%hs) %d Active"),
941
 
                pObject->m_dwCookie, szObjectName, m_dwObjectCount));
942
 
    }
943
 
 
944
 
    LeaveCriticalSection(&m_CSDebug);
945
 
    return ObjectCookie;
946
 
}
947
 
 
948
 
 
949
 
/* This is called by the CBaseObject destructor when an object is about to be
950
 
   destroyed, we are passed the cookie we returned during construction that
951
 
   identifies this object. We scan the object list for a matching cookie and
952
 
   remove the object if successful. We also update the active object count */
953
 
 
954
 
BOOL WINAPI DbgRegisterObjectDestruction(DWORD dwCookie)
955
 
{
956
 
    /* Grab the list critical section */
957
 
    EnterCriticalSection(&m_CSDebug);
958
 
 
959
 
    ObjectDesc *pObject = pListHead;
960
 
    ObjectDesc *pPrevious = NULL;
961
 
 
962
 
    /* Scan the object list looking for a cookie match */
963
 
 
964
 
    while (pObject) {
965
 
        if (pObject->m_dwCookie == dwCookie) {
966
 
            break;
967
 
        }
968
 
        pPrevious = pObject;
969
 
        pObject = pObject->m_pNext;
970
 
    }
971
 
 
972
 
    if (pObject == NULL) {
973
 
        DbgBreak("Apparently destroying a bogus object");
974
 
        LeaveCriticalSection(&m_CSDebug);
975
 
        return FALSE;
976
 
    }
977
 
 
978
 
    /* Is the object at the head of the list */
979
 
 
980
 
    if (pPrevious == NULL) {
981
 
        pListHead = pObject->m_pNext;
982
 
    } else {
983
 
        pPrevious->m_pNext = pObject->m_pNext;
984
 
    }
985
 
 
986
 
    /* Delete the object and update the housekeeping information */
987
 
 
988
 
    m_dwObjectCount--;
989
 
 
990
 
    if(pObject->m_wszName) {
991
 
        DbgLog((LOG_MEMORY,2,TEXT("Object destroyed %d (%ls) %d Active"),
992
 
                pObject->m_dwCookie, pObject->m_wszName, m_dwObjectCount));
993
 
    } else {
994
 
        DbgLog((LOG_MEMORY,2,TEXT("Object destroyed %d (%hs) %d Active"),
995
 
                pObject->m_dwCookie, pObject->m_szName, m_dwObjectCount));
996
 
    }
997
 
 
998
 
    delete pObject;
999
 
    LeaveCriticalSection(&m_CSDebug);
1000
 
    return TRUE;
1001
 
}
1002
 
 
1003
 
 
1004
 
/* This runs through the active object list displaying their details */
1005
 
 
1006
 
void WINAPI DbgDumpObjectRegister()
1007
 
{
1008
 
    TCHAR szInfo[iDEBUGINFO];
1009
 
 
1010
 
    /* Grab the list critical section */
1011
 
 
1012
 
    EnterCriticalSection(&m_CSDebug);
1013
 
    ObjectDesc *pObject = pListHead;
1014
 
 
1015
 
    /* Scan the object list displaying the name and cookie */
1016
 
 
1017
 
    DbgLog((LOG_MEMORY,2,TEXT("")));
1018
 
    DbgLog((LOG_MEMORY,2,TEXT("   ID             Object Description")));
1019
 
    DbgLog((LOG_MEMORY,2,TEXT("")));
1020
 
 
1021
 
    while (pObject) {
1022
 
        if(pObject->m_wszName) {
1023
 
            (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("%5d (%p) %30ls"),pObject->m_dwCookie, &pObject, pObject->m_wszName);
1024
 
        } else {
1025
 
            (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("%5d (%p) %30hs"),pObject->m_dwCookie, &pObject, pObject->m_szName);
1026
 
        }
1027
 
        DbgLog((LOG_MEMORY,2,szInfo));
1028
 
        pObject = pObject->m_pNext;
1029
 
    }
1030
 
 
1031
 
    (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("Total object count %5d"),m_dwObjectCount);
1032
 
    DbgLog((LOG_MEMORY,2,TEXT("")));
1033
 
    DbgLog((LOG_MEMORY,1,szInfo));
1034
 
    LeaveCriticalSection(&m_CSDebug);
1035
 
}
1036
 
 
1037
 
/*  Debug infinite wait stuff */
1038
 
DWORD WINAPI DbgWaitForSingleObject(HANDLE h)
1039
 
{
1040
 
    DWORD dwWaitResult;
1041
 
    do {
1042
 
        dwWaitResult = WaitForSingleObject(h, dwWaitTimeout);
1043
 
        ASSERT(dwWaitResult == WAIT_OBJECT_0);
1044
 
    } while (dwWaitResult == WAIT_TIMEOUT);
1045
 
    return dwWaitResult;
1046
 
}
1047
 
DWORD WINAPI DbgWaitForMultipleObjects(DWORD nCount,
1048
 
                                __in_ecount(nCount) CONST HANDLE *lpHandles,
1049
 
                                BOOL bWaitAll)
1050
 
{
1051
 
    DWORD dwWaitResult;
1052
 
    do {
1053
 
        dwWaitResult = WaitForMultipleObjects(nCount,
1054
 
                                              lpHandles,
1055
 
                                              bWaitAll,
1056
 
                                              dwWaitTimeout);
1057
 
        ASSERT((DWORD)(dwWaitResult - WAIT_OBJECT_0) < MAXIMUM_WAIT_OBJECTS);
1058
 
    } while (dwWaitResult == WAIT_TIMEOUT);
1059
 
    return dwWaitResult;
1060
 
}
1061
 
 
1062
 
void WINAPI DbgSetWaitTimeout(DWORD dwTimeout)
1063
 
{
1064
 
    dwWaitTimeout = dwTimeout;
1065
 
}
1066
 
 
1067
 
#endif /* DEBUG */
1068
 
 
1069
 
#ifdef _OBJBASE_H_
1070
 
 
1071
 
    /*  Stuff for printing out our GUID names */
1072
 
 
1073
 
    GUID_STRING_ENTRY g_GuidNames[] = {
1074
 
    #define OUR_GUID_ENTRY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
1075
 
    { #name, { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } } },
1076
 
        #include <uuids.h>
1077
 
    };
1078
 
 
1079
 
    CGuidNameList GuidNames;
1080
 
    int g_cGuidNames = sizeof(g_GuidNames) / sizeof(g_GuidNames[0]);
1081
 
 
1082
 
    char *CGuidNameList::operator [] (const GUID &guid)
1083
 
    {
1084
 
        for (int i = 0; i < g_cGuidNames; i++) {
1085
 
            if (g_GuidNames[i].guid == guid) {
1086
 
                return g_GuidNames[i].szName;
1087
 
            }
1088
 
        }
1089
 
        if (guid == GUID_NULL) {
1090
 
            return "GUID_NULL";
1091
 
        }
1092
 
 
1093
 
        // !!! add something to print FOURCC guids?
1094
 
 
1095
 
        // shouldn't this print the hex CLSID?
1096
 
        return "Unknown GUID Name";
1097
 
    }
1098
 
 
1099
 
#endif /* _OBJBASE_H_ */
1100
 
 
1101
 
/*  CDisp class - display our data types */
1102
 
 
1103
 
// clashes with REFERENCE_TIME
1104
 
CDisp::CDisp(LONGLONG ll, int Format)
1105
 
{
1106
 
    // note: this could be combined with CDisp(LONGLONG) by
1107
 
    // introducing a default format of CDISP_REFTIME
1108
 
    LARGE_INTEGER li;
1109
 
    li.QuadPart = ll;
1110
 
    switch (Format) {
1111
 
        case CDISP_DEC:
1112
 
        {
1113
 
            TCHAR  temp[20];
1114
 
            int pos=20;
1115
 
            temp[--pos] = 0;
1116
 
            int digit;
1117
 
            // always output at least one digit
1118
 
            do {
1119
 
                // Get the rightmost digit - we only need the low word
1120
 
                digit = li.LowPart % 10;
1121
 
                li.QuadPart /= 10;
1122
 
                temp[--pos] = (TCHAR) digit+L'0';
1123
 
            } while (li.QuadPart);
1124
 
            (void)StringCchCopy(m_String, NUMELMS(m_String), temp+pos);
1125
 
            break;
1126
 
        }
1127
 
        case CDISP_HEX:
1128
 
        default:
1129
 
            (void)StringCchPrintf(m_String, NUMELMS(m_String), TEXT("0x%X%8.8X"), li.HighPart, li.LowPart);
1130
 
    }
1131
 
};
1132
 
 
1133
 
CDisp::CDisp(REFCLSID clsid)
1134
 
{
1135
 
#ifdef UNICODE
1136
 
    (void)StringFromGUID2(clsid, m_String, NUMELMS(m_String));
1137
 
#else
1138
 
    WCHAR wszTemp[50];
1139
 
    (void)StringFromGUID2(clsid, wszTemp, NUMELMS(wszTemp));
1140
 
    (void)StringCchPrintf(m_String, NUMELMS(m_String), TEXT("%S"), wszTemp);
1141
 
#endif
1142
 
};
1143
 
 
1144
 
#ifdef __STREAMS__
1145
 
/*  Display stuff */
1146
 
CDisp::CDisp(CRefTime llTime)
1147
 
{
1148
 
    LONGLONG llDiv;
1149
 
    if (llTime < 0) {
1150
 
        llTime = -llTime;
1151
 
        (void)StringCchCopy(m_String, NUMELMS(m_String), TEXT("-"));
1152
 
    }
1153
 
    llDiv = (LONGLONG)24 * 3600 * 10000000;
1154
 
    if (llTime >= llDiv) {
1155
 
        (void)StringCchPrintf(m_String + lstrlen(m_String), NUMELMS(m_String) - lstrlen(m_String), TEXT("%d days "), (LONG)(llTime / llDiv));
1156
 
        llTime = llTime % llDiv;
1157
 
    }
1158
 
    llDiv = (LONGLONG)3600 * 10000000;
1159
 
    if (llTime >= llDiv) {
1160
 
        (void)StringCchPrintf(m_String + lstrlen(m_String), NUMELMS(m_String) - lstrlen(m_String), TEXT("%d hrs "), (LONG)(llTime / llDiv));
1161
 
        llTime = llTime % llDiv;
1162
 
    }
1163
 
    llDiv = (LONGLONG)60 * 10000000;
1164
 
    if (llTime >= llDiv) {
1165
 
        (void)StringCchPrintf(m_String + lstrlen(m_String), NUMELMS(m_String) - lstrlen(m_String), TEXT("%d mins "), (LONG)(llTime / llDiv));
1166
 
        llTime = llTime % llDiv;
1167
 
    }
1168
 
    (void)StringCchPrintf(m_String + lstrlen(m_String), NUMELMS(m_String) - lstrlen(m_String), TEXT("%d.%3.3d sec"),
1169
 
             (LONG)llTime / 10000000,
1170
 
             (LONG)((llTime % 10000000) / 10000));
1171
 
};
1172
 
 
1173
 
#endif // __STREAMS__
1174
 
 
1175
 
 
1176
 
/*  Display pin */
1177
 
CDisp::CDisp(IPin *pPin)
1178
 
{
1179
 
    PIN_INFO pi;
1180
 
    TCHAR str[MAX_PIN_NAME];
1181
 
    CLSID clsid;
1182
 
 
1183
 
    if (pPin) {
1184
 
       pPin->QueryPinInfo(&pi);
1185
 
       pi.pFilter->GetClassID(&clsid);
1186
 
       QueryPinInfoReleaseFilter(pi);
1187
 
      #ifndef UNICODE
1188
 
       WideCharToMultiByte(GetACP(), 0, pi.achName, lstrlenW(pi.achName) + 1,
1189
 
                           str, MAX_PIN_NAME, NULL, NULL);
1190
 
      #else
1191
 
       (void)StringCchCopy(str, NUMELMS(str), pi.achName);
1192
 
      #endif
1193
 
    } else {
1194
 
       (void)StringCchCopy(str, NUMELMS(str), TEXT("NULL IPin"));
1195
 
    }
1196
 
 
1197
 
    m_pString = (PTCHAR) new TCHAR[lstrlen(str)+64];
1198
 
    if (!m_pString) {
1199
 
        return;
1200
 
    }
1201
 
 
1202
 
    (void)StringCchPrintf(m_pString, lstrlen(str) + 64, TEXT("%hs(%s)"), GuidNames[clsid], str);
1203
 
}
1204
 
 
1205
 
/*  Display filter or pin */
1206
 
CDisp::CDisp(IUnknown *pUnk)
1207
 
{
1208
 
    IBaseFilter *pf;
1209
 
    HRESULT hr = pUnk->QueryInterface(IID_IBaseFilter, (void **)&pf);
1210
 
    if(SUCCEEDED(hr))
1211
 
    {
1212
 
        FILTER_INFO fi;
1213
 
        hr = pf->QueryFilterInfo(&fi);
1214
 
        if(SUCCEEDED(hr))
1215
 
        {
1216
 
            QueryFilterInfoReleaseGraph(fi);
1217
 
 
1218
 
            size_t len = lstrlenW(fi.achName)  + 1;
1219
 
 
1220
 
            m_pString = new TCHAR[len];
1221
 
            if(m_pString)
1222
 
            {
1223
 
#ifdef UNICODE
1224
 
                (void)StringCchCopy(m_pString, len, fi.achName);
1225
 
#else
1226
 
                (void)StringCchPrintf(m_pString, len, "%S", fi.achName);
1227
 
#endif
1228
 
            }
1229
 
        }
1230
 
 
1231
 
        pf->Release();
1232
 
 
1233
 
        return;
1234
 
    }
1235
 
 
1236
 
    IPin *pp;
1237
 
    hr = pUnk->QueryInterface(IID_IPin, (void **)&pp);
1238
 
    if(SUCCEEDED(hr))
1239
 
    {
1240
 
        CDisp::CDisp(pp);
1241
 
        pp->Release();
1242
 
        return;
1243
 
    }
1244
 
}
1245
 
 
1246
 
 
1247
 
CDisp::~CDisp()
1248
 
{
1249
 
}
1250
 
 
1251
 
CDispBasic::~CDispBasic()
1252
 
{
1253
 
    if (m_pString != m_String) {
1254
 
        delete [] m_pString;
1255
 
    }
1256
 
}
1257
 
 
1258
 
CDisp::CDisp(double d)
1259
 
{
1260
 
    (void)StringCchPrintf(m_String, NUMELMS(m_String), TEXT("%d.%03d"), (int) d, (int) ((d - (int) d) * 1000));
1261
 
}
1262
 
 
1263
 
 
1264
 
/* If built for debug this will display the media type details. We convert the
1265
 
   major and subtypes into strings and also ask the base classes for a string
1266
 
   description of the subtype, so MEDIASUBTYPE_RGB565 becomes RGB 565 16 bit
1267
 
   We also display the fields in the BITMAPINFOHEADER structure, this should
1268
 
   succeed as we do not accept input types unless the format is big enough */
1269
 
 
1270
 
#ifdef DEBUG
1271
 
void WINAPI DisplayType(LPCTSTR label, const AM_MEDIA_TYPE *pmtIn)
1272
 
{
1273
 
 
1274
 
    /* Dump the GUID types and a short description */
1275
 
 
1276
 
    DbgLog((LOG_TRACE,5,TEXT("")));
1277
 
    DbgLog((LOG_TRACE,2,TEXT("%s  M type %hs  S type %hs"), label,
1278
 
            GuidNames[pmtIn->majortype],
1279
 
            GuidNames[pmtIn->subtype]));
1280
 
    DbgLog((LOG_TRACE,5,TEXT("Subtype description %s"),GetSubtypeName(&pmtIn->subtype)));
1281
 
 
1282
 
    /* Dump the generic media types */
1283
 
 
1284
 
    if (pmtIn->bTemporalCompression) {
1285
 
        DbgLog((LOG_TRACE,5,TEXT("Temporally compressed")));
1286
 
    } else {
1287
 
        DbgLog((LOG_TRACE,5,TEXT("Not temporally compressed")));
1288
 
    }
1289
 
 
1290
 
    if (pmtIn->bFixedSizeSamples) {
1291
 
        DbgLog((LOG_TRACE,5,TEXT("Sample size %d"),pmtIn->lSampleSize));
1292
 
    } else {
1293
 
        DbgLog((LOG_TRACE,5,TEXT("Variable size samples")));
1294
 
    }
1295
 
 
1296
 
    if (pmtIn->formattype == FORMAT_VideoInfo) {
1297
 
 
1298
 
        VIDEOINFOHEADER *pVideoInfo = (VIDEOINFOHEADER *)pmtIn->pbFormat;
1299
 
 
1300
 
        DisplayRECT(TEXT("Source rectangle"),pVideoInfo->rcSource);
1301
 
        DisplayRECT(TEXT("Target rectangle"),pVideoInfo->rcTarget);
1302
 
        DisplayBITMAPINFO(HEADER(pmtIn->pbFormat));
1303
 
 
1304
 
    } if (pmtIn->formattype == FORMAT_VideoInfo2) {
1305
 
 
1306
 
        VIDEOINFOHEADER2 *pVideoInfo2 = (VIDEOINFOHEADER2 *)pmtIn->pbFormat;
1307
 
 
1308
 
        DisplayRECT(TEXT("Source rectangle"),pVideoInfo2->rcSource);
1309
 
        DisplayRECT(TEXT("Target rectangle"),pVideoInfo2->rcTarget);
1310
 
        DbgLog((LOG_TRACE, 5, TEXT("Aspect Ratio: %d:%d"),
1311
 
            pVideoInfo2->dwPictAspectRatioX,
1312
 
            pVideoInfo2->dwPictAspectRatioY));
1313
 
        DisplayBITMAPINFO(&pVideoInfo2->bmiHeader);
1314
 
 
1315
 
    } else if (pmtIn->majortype == MEDIATYPE_Audio) {
1316
 
        DbgLog((LOG_TRACE,2,TEXT("     Format type %hs"),
1317
 
            GuidNames[pmtIn->formattype]));
1318
 
        DbgLog((LOG_TRACE,2,TEXT("     Subtype %hs"),
1319
 
            GuidNames[pmtIn->subtype]));
1320
 
 
1321
 
        if ((pmtIn->subtype != MEDIASUBTYPE_MPEG1Packet)
1322
 
          && (pmtIn->cbFormat >= sizeof(PCMWAVEFORMAT)))
1323
 
        {
1324
 
            /* Dump the contents of the WAVEFORMATEX type-specific format structure */
1325
 
 
1326
 
            WAVEFORMATEX *pwfx = (WAVEFORMATEX *) pmtIn->pbFormat;
1327
 
            DbgLog((LOG_TRACE,2,TEXT("wFormatTag %u"), pwfx->wFormatTag));
1328
 
            DbgLog((LOG_TRACE,2,TEXT("nChannels %u"), pwfx->nChannels));
1329
 
            DbgLog((LOG_TRACE,2,TEXT("nSamplesPerSec %lu"), pwfx->nSamplesPerSec));
1330
 
            DbgLog((LOG_TRACE,2,TEXT("nAvgBytesPerSec %lu"), pwfx->nAvgBytesPerSec));
1331
 
            DbgLog((LOG_TRACE,2,TEXT("nBlockAlign %u"), pwfx->nBlockAlign));
1332
 
            DbgLog((LOG_TRACE,2,TEXT("wBitsPerSample %u"), pwfx->wBitsPerSample));
1333
 
 
1334
 
            /* PCM uses a WAVEFORMAT and does not have the extra size field */
1335
 
 
1336
 
            if (pmtIn->cbFormat >= sizeof(WAVEFORMATEX)) {
1337
 
                DbgLog((LOG_TRACE,2,TEXT("cbSize %u"), pwfx->cbSize));
1338
 
            }
1339
 
        } else {
1340
 
        }
1341
 
 
1342
 
    } else {
1343
 
        DbgLog((LOG_TRACE,2,TEXT("     Format type %hs"),
1344
 
            GuidNames[pmtIn->formattype]));
1345
 
    }
1346
 
}
1347
 
 
1348
 
 
1349
 
void DisplayBITMAPINFO(const BITMAPINFOHEADER* pbmi)
1350
 
{
1351
 
    DbgLog((LOG_TRACE,5,TEXT("Size of BITMAPINFO structure %d"),pbmi->biSize));
1352
 
    if (pbmi->biCompression < 256) {
1353
 
        DbgLog((LOG_TRACE,2,TEXT("%dx%dx%d bit  (%d)"),
1354
 
                pbmi->biWidth, pbmi->biHeight,
1355
 
                pbmi->biBitCount, pbmi->biCompression));
1356
 
    } else {
1357
 
        DbgLog((LOG_TRACE,2,TEXT("%dx%dx%d bit '%4.4hs'"),
1358
 
                pbmi->biWidth, pbmi->biHeight,
1359
 
                pbmi->biBitCount, &pbmi->biCompression));
1360
 
    }
1361
 
 
1362
 
    DbgLog((LOG_TRACE,2,TEXT("Image size %d"),pbmi->biSizeImage));
1363
 
    DbgLog((LOG_TRACE,5,TEXT("Planes %d"),pbmi->biPlanes));
1364
 
    DbgLog((LOG_TRACE,5,TEXT("X Pels per metre %d"),pbmi->biXPelsPerMeter));
1365
 
    DbgLog((LOG_TRACE,5,TEXT("Y Pels per metre %d"),pbmi->biYPelsPerMeter));
1366
 
    DbgLog((LOG_TRACE,5,TEXT("Colours used %d"),pbmi->biClrUsed));
1367
 
}
1368
 
 
1369
 
 
1370
 
void DisplayRECT(LPCTSTR szLabel, const RECT& rc)
1371
 
{
1372
 
    DbgLog((LOG_TRACE,5,TEXT("%s (Left %d Top %d Right %d Bottom %d)"),
1373
 
            szLabel,
1374
 
            rc.left,
1375
 
            rc.top,
1376
 
            rc.right,
1377
 
            rc.bottom));
1378
 
}
1379
 
 
1380
 
 
1381
 
void WINAPI DumpGraph(IFilterGraph *pGraph, DWORD dwLevel)
1382
 
{
1383
 
    if( !pGraph )
1384
 
    {
1385
 
        return;
1386
 
    }
1387
 
 
1388
 
    IEnumFilters *pFilters;
1389
 
 
1390
 
    DbgLog((LOG_TRACE,dwLevel,TEXT("DumpGraph [%x]"), pGraph));
1391
 
 
1392
 
    if (FAILED(pGraph->EnumFilters(&pFilters))) {
1393
 
        DbgLog((LOG_TRACE,dwLevel,TEXT("EnumFilters failed!")));
1394
 
    }
1395
 
 
1396
 
    IBaseFilter *pFilter;
1397
 
    ULONG       n;
1398
 
    while (pFilters->Next(1, &pFilter, &n) == S_OK) {
1399
 
        FILTER_INFO     info;
1400
 
 
1401
 
        if (FAILED(pFilter->QueryFilterInfo(&info))) {
1402
 
            DbgLog((LOG_TRACE,dwLevel,TEXT("    Filter [%p]  -- failed QueryFilterInfo"), pFilter));
1403
 
        } else {
1404
 
            QueryFilterInfoReleaseGraph(info);
1405
 
 
1406
 
            // !!! should QueryVendorInfo here!
1407
 
 
1408
 
            DbgLog((LOG_TRACE,dwLevel,TEXT("    Filter [%p]  '%ls'"), pFilter, info.achName));
1409
 
 
1410
 
            IEnumPins *pins;
1411
 
 
1412
 
            if (FAILED(pFilter->EnumPins(&pins))) {
1413
 
                DbgLog((LOG_TRACE,dwLevel,TEXT("EnumPins failed!")));
1414
 
            } else {
1415
 
 
1416
 
                IPin *pPin;
1417
 
                while (pins->Next(1, &pPin, &n) == S_OK) {
1418
 
                    PIN_INFO    pinInfo;
1419
 
 
1420
 
                    if (FAILED(pPin->QueryPinInfo(&pinInfo))) {
1421
 
                        DbgLog((LOG_TRACE,dwLevel,TEXT("          Pin [%x]  -- failed QueryPinInfo"), pPin));
1422
 
                    } else {
1423
 
                        QueryPinInfoReleaseFilter(pinInfo);
1424
 
 
1425
 
                        IPin *pPinConnected = NULL;
1426
 
 
1427
 
                        HRESULT hr = pPin->ConnectedTo(&pPinConnected);
1428
 
 
1429
 
                        if (pPinConnected) {
1430
 
                            DbgLog((LOG_TRACE,dwLevel,TEXT("          Pin [%p]  '%ls' [%sput]")
1431
 
                                                           TEXT("  Connected to pin [%p]"),
1432
 
                                    pPin, pinInfo.achName,
1433
 
                                    pinInfo.dir == PINDIR_INPUT ? TEXT("In") : TEXT("Out"),
1434
 
                                    pPinConnected));
1435
 
 
1436
 
                            pPinConnected->Release();
1437
 
 
1438
 
                            // perhaps we should really dump the type both ways as a sanity
1439
 
                            // check?
1440
 
                            if (pinInfo.dir == PINDIR_OUTPUT) {
1441
 
                                AM_MEDIA_TYPE mt;
1442
 
 
1443
 
                                hr = pPin->ConnectionMediaType(&mt);
1444
 
 
1445
 
                                if (SUCCEEDED(hr)) {
1446
 
                                    DisplayType(TEXT("Connection type"), &mt);
1447
 
 
1448
 
                                    FreeMediaType(mt);
1449
 
                                }
1450
 
                            }
1451
 
                        } else {
1452
 
                            DbgLog((LOG_TRACE,dwLevel,
1453
 
                                    TEXT("          Pin [%x]  '%ls' [%sput]"),
1454
 
                                    pPin, pinInfo.achName,
1455
 
                                    pinInfo.dir == PINDIR_INPUT ? TEXT("In") : TEXT("Out")));
1456
 
 
1457
 
                        }
1458
 
                    }
1459
 
 
1460
 
                    pPin->Release();
1461
 
 
1462
 
                }
1463
 
 
1464
 
                pins->Release();
1465
 
            }
1466
 
 
1467
 
        }
1468
 
 
1469
 
        pFilter->Release();
1470
 
    }
1471
 
 
1472
 
    pFilters->Release();
1473
 
 
1474
 
}
1475
 
 
1476
 
#endif
1477
 
 
1478
 
#endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */