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

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Francois Marier, Francois Marier, Mark Purcell
  • Date: 2014-10-18 15:08:50 UTC
  • mfrom: (1.1.12)
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20141018150850-2exfk34ckb15pcwi
Tags: 1.4.1-0.1
[ Francois Marier ]
* Non-maintainer upload
* New upstream release (closes: #759576, #741130)
  - debian/rules +PJPROJECT_VERSION := 2.2.1
  - add upstream patch to fix broken TLS support
  - add patch to fix pjproject regression

[ Mark Purcell ]
* Build-Depends:
  - sflphone-daemon + libavformat-dev, libavcodec-dev, libswscale-dev,
  libavdevice-dev, libavutil-dev
  - sflphone-gnome + libclutter-gtk-1.0-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 */