Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1116 lines
27 KiB

  1. /*++
  2. Copyright (c) 1998 - 1999 Microsoft Corporation
  3. Module Name:
  4. utils.cpp
  5. Abstract:
  6. Author:
  7. mquinton - 6/30/98
  8. Notes:
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. HRESULT
  13. ProcessMessage(
  14. PT3INIT_DATA,
  15. PASYNCEVENTMSG
  16. );
  17. ////////////////////////////////////////////////////////////////////
  18. // CRetryQueue::QueueEvent
  19. //
  20. // Queues a TAPI event message object to be processed later
  21. ////////////////////////////////////////////////////////////////////
  22. BOOL CRetryQueue::QueueEvent(PASYNCEVENTMSG pEvent)
  23. {
  24. PRETRY_QUEUE_ENTRY pNewQueueEntry;
  25. PASYNCEVENTMSG pEventCopy;
  26. LOG((TL_TRACE, "QueueEvent - enter"));
  27. //
  28. // we want to do as little as possible inside the lock so preallocate
  29. // everything we can before acquiring it
  30. //
  31. //
  32. // create a new queue entry
  33. //
  34. pNewQueueEntry = (PRETRY_QUEUE_ENTRY)ClientAlloc( sizeof(RETRY_QUEUE_ENTRY) );
  35. if (pNewQueueEntry == NULL)
  36. {
  37. LOG((TL_ERROR, "QueueEvent - out of memory for new entry - losing message"));
  38. return FALSE;
  39. }
  40. //
  41. // create a copy of the event
  42. //
  43. pEventCopy = (PASYNCEVENTMSG)ClientAlloc(pEvent->TotalSize);
  44. if ( pEventCopy == NULL)
  45. {
  46. LOG((TL_ERROR, "QueueEvent - out of memory for pEventCopy - losing message"));
  47. ClientFree(pNewQueueEntry);
  48. return FALSE;
  49. }
  50. //
  51. // initialize the copy of the event that we have created
  52. //
  53. memcpy( pEventCopy, pEvent, pEvent->TotalSize );
  54. //
  55. // initialize queue entry with our copy of the event
  56. //
  57. pNewQueueEntry->dwRetryCount = MAX_REQUEUE_TRIES;
  58. pNewQueueEntry->pMessage = pEventCopy;
  59. Lock();
  60. //
  61. // is the queue accepting new entries?
  62. //
  63. if (!m_bAcceptNewEntries)
  64. {
  65. LOG((TL_TRACE,
  66. "QueueEvent - can't queue -- the queue is closed"));
  67. ClientFree(pNewQueueEntry);
  68. ClientFree(pEventCopy);
  69. Unlock();
  70. return FALSE;
  71. }
  72. //
  73. // attempt to add queue entry to the list
  74. //
  75. try
  76. {
  77. m_RetryQueueList.push_back(pNewQueueEntry);
  78. }
  79. catch(...)
  80. {
  81. LOG((TL_ERROR, "QueueEvent - out of memory - losing message"));
  82. ClientFree(pNewQueueEntry);
  83. ClientFree(pEventCopy);
  84. Unlock();
  85. return FALSE;
  86. }
  87. Unlock();
  88. LOG((TL_INFO, "QueueEvent - Queued pEntry ----> %p", pNewQueueEntry ));
  89. LOG((TL_INFO, " pEvent ----> %p", pEventCopy ));
  90. return TRUE;
  91. }
  92. ////////////////////////////////////////////////////////////////////
  93. // CRetryQueue::QueueEvent
  94. //
  95. // Requeues a TAPI event message object to be processed later
  96. ////////////////////////////////////////////////////////////////////
  97. void CRetryQueue::RequeueEvent(PRETRY_QUEUE_ENTRY pQueueEntry)
  98. {
  99. LOG((TL_TRACE, "RequeueEvent - enter"));
  100. // just reuse the old entry
  101. // add to list
  102. Lock();
  103. if (!m_bAcceptNewEntries)
  104. {
  105. LOG((TL_ERROR,
  106. "RequeueEvent - attemped to requeue after the queue was closed"));
  107. //
  108. // this should not have happened -- see how we got here
  109. //
  110. _ASSERTE(FALSE);
  111. Unlock();
  112. return;
  113. }
  114. try
  115. {
  116. m_RetryQueueList.push_back(pQueueEntry);
  117. }
  118. catch(...)
  119. {
  120. LOG((TL_ERROR, "RequeueEvent - out of memory - losing message"));
  121. }
  122. Unlock();
  123. LOG((TL_INFO, "RequeueEvent - Requeuing pEntry is ----> %p", pQueueEntry ));
  124. LOG((TL_INFO, " Requeuing pEvent is ----> %p", pQueueEntry->pMessage ));
  125. LOG((TL_INFO, " Requeuing count is ----> %lx", pQueueEntry->dwRetryCount ));
  126. }
  127. ////////////////////////////////////////////////////////////////////
  128. // CRetryQueue::DequeueEvent
  129. //
  130. // Pulls an event from the queue
  131. ////////////////////////////////////////////////////////////////////
  132. BOOL CRetryQueue::DequeueEvent(PRETRY_QUEUE_ENTRY * ppEvent)
  133. {
  134. BOOL bResult = TRUE;
  135. LOG((TL_TRACE, "DequeueEvent - enter"));
  136. Lock();
  137. if (m_RetryQueueList.size() > 0)
  138. {
  139. *ppEvent = m_RetryQueueList.front();
  140. try
  141. {
  142. m_RetryQueueList.pop_front();
  143. }
  144. catch(...)
  145. {
  146. LOG((TL_INFO, "DequeueEvent - pop m_RetryQueueList failed"));
  147. bResult = FALSE;
  148. }
  149. if( bResult )
  150. {
  151. bResult = !IsBadReadPtr(*ppEvent, sizeof( RETRY_QUEUE_ENTRY ) );
  152. }
  153. LOG((TL_INFO, "DequeueEvent - returning %p", *ppEvent));
  154. }
  155. else
  156. {
  157. LOG((TL_INFO, "DequeueEvent - no event"));
  158. // return false if there are no more messages
  159. bResult = FALSE;
  160. }
  161. Unlock();
  162. return bResult;
  163. }
  164. ////////////////////////////////////////////////////////////////////
  165. // CRetryQueue::ProcessQueue
  166. //
  167. ////////////////////////////////////////////////////////////////////
  168. void CRetryQueue::ProcessQueue()
  169. {
  170. PRETRY_QUEUE_ENTRY pQueueEntry;
  171. PASYNCEVENTMSG pAsyncEventMsg;
  172. PT3INIT_DATA pInitData = NULL;
  173. DWORD dwCount;
  174. Lock();
  175. dwCount = m_RetryQueueList.size();
  176. Unlock();
  177. LOG((TL_TRACE, "ProcessQueue - enter dwCount----> %lx",dwCount));
  178. while(dwCount-- > 0 )
  179. {
  180. if( DequeueEvent(&pQueueEntry) )
  181. {
  182. pAsyncEventMsg = pQueueEntry->pMessage;
  183. //
  184. // InitContext contains the handle. get the original pointer from the handle
  185. //
  186. pInitData = (PT3INIT_DATA)GetHandleTableEntry(pAsyncEventMsg->InitContext);
  187. LOG(( TL_INFO,
  188. "ProcessQueue - msg=%d, hDev=x%x, p1=x%x, p2=x%x, p3=x%x, pInitData=%p",
  189. pAsyncEventMsg->Msg,
  190. pAsyncEventMsg->hDevice,
  191. pAsyncEventMsg->Param1,
  192. pAsyncEventMsg->Param2,
  193. pAsyncEventMsg->Param3,
  194. pInitData
  195. ));
  196. if SUCCEEDED(ProcessMessage(
  197. pInitData,
  198. pAsyncEventMsg
  199. ) )
  200. {
  201. // We're Done with the message so free it & the used queue entry
  202. LOG((TL_INFO, "ProcessQueue - sucessfully processed event message ----> %p",
  203. pAsyncEventMsg ));
  204. ClientFree(pAsyncEventMsg);
  205. ClientFree(pQueueEntry);
  206. }
  207. else
  208. {
  209. //
  210. // if we don't have any retries left for this entry or if the
  211. // queue is now closed, do cleanup. otherwise, requeue
  212. //
  213. if( (--(pQueueEntry->dwRetryCount) == 0) || (!m_bAcceptNewEntries))
  214. {
  215. // We're giving up with this one, so free the message & the used queue entry
  216. //
  217. // note that we can have potential leaks here if queue entry is
  218. // holding references to other things that we don't know how to
  219. // free
  220. //
  221. LOG((TL_ERROR, "ProcessQueue - used all retries, deleting event message ----> %p",
  222. pAsyncEventMsg ));
  223. ClientFree(pAsyncEventMsg);
  224. ClientFree(pQueueEntry);
  225. }
  226. else
  227. {
  228. // Queue it one more time, reuse the queu entry ....
  229. RequeueEvent(pQueueEntry);
  230. //
  231. // we failed to process the workitem. it is possible that
  232. // another thread is waiting for a timeslot so it is
  233. // scheduled and gets a chance to prepare everything so our
  234. // next processing attempt is successful.
  235. //
  236. // to increase the chances of that thread being scheduled
  237. // (and out success on the next processing attempt), sleep
  238. // a little.
  239. //
  240. extern DWORD gdwTapi3RetryProcessingSleep;
  241. LOG((TL_INFO,
  242. "ProcessQueue - requeued item. Sleeping for %ld ms",
  243. gdwTapi3RetryProcessingSleep));
  244. Sleep(gdwTapi3RetryProcessingSleep);
  245. }
  246. }
  247. }
  248. }
  249. LOG((TL_TRACE, "ProcessQueue - exit"));
  250. }
  251. void
  252. CRetryQueue::RemoveNewCallHub(DWORD dwCallHub)
  253. {
  254. RetryQueueListType::iterator iter, end;
  255. Lock();
  256. iter = m_RetryQueueList.begin();
  257. end = m_RetryQueueList.end();
  258. for ( ; iter != end; iter++ )
  259. {
  260. PRETRY_QUEUE_ENTRY pEntry = *iter;
  261. if(pEntry->pMessage != NULL)
  262. {
  263. if ( (pEntry->pMessage->Msg == LINE_APPNEWCALLHUB) &&
  264. (pEntry->pMessage->Param1 == dwCallHub) )
  265. {
  266. ClientFree(pEntry->pMessage);
  267. ClientFree(pEntry);
  268. m_RetryQueueList.erase( iter ); // erase appears to create a problem with
  269. // the iter so that we loop too many times & AV.
  270. iter = m_RetryQueueList.begin(); // Restarting at beginning again fixs this.
  271. }
  272. }
  273. }
  274. Unlock();
  275. }
  276. ////////////////////////////////////////////////////////////////////
  277. //
  278. // CRetryQueue::OpenForNewEntries
  279. //
  280. // after this function returns, the queue will accept new entries
  281. //
  282. ////////////////////////////////////////////////////////////////////
  283. void CRetryQueue::OpenForNewEntries()
  284. {
  285. LOG((TL_TRACE, "OpenForNewEntries - enter"));
  286. Lock();
  287. m_bAcceptNewEntries = TRUE;
  288. Unlock();
  289. LOG((TL_TRACE, "OpenForNewEntries - exit"));
  290. }
  291. ////////////////////////////////////////////////////////////////////
  292. //
  293. // CRetryQueue::CloseForNewEntries
  294. //
  295. // new entries will be denied after this function returns
  296. //
  297. ////////////////////////////////////////////////////////////////////
  298. void CRetryQueue::CloseForNewEntries()
  299. {
  300. LOG((TL_TRACE, "CloseForNewEntries - enter"));
  301. Lock();
  302. m_bAcceptNewEntries = FALSE;
  303. Unlock();
  304. LOG((TL_TRACE, "CloseForNewEntries - exit"));
  305. }
  306. ////////////////////////////////////////////////////////////////////
  307. // CRetryQueue::~CRetryQueue
  308. //
  309. ////////////////////////////////////////////////////////////////////
  310. CRetryQueue::~CRetryQueue()
  311. {
  312. RetryQueueListType::iterator i,j;
  313. PRETRY_QUEUE_ENTRY pQueueEntry;
  314. Lock();
  315. // walk list deleting entries
  316. i = m_RetryQueueList.begin();
  317. j = m_RetryQueueList.end();
  318. while ( i != j )
  319. {
  320. pQueueEntry = *i++;
  321. if(pQueueEntry->pMessage != NULL)
  322. ClientFree(pQueueEntry->pMessage);
  323. ClientFree(pQueueEntry);
  324. }
  325. m_RetryQueueList.clear();
  326. Unlock();
  327. DeleteCriticalSection( &m_cs );
  328. };
  329. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  330. //
  331. // Initialize
  332. //
  333. // dwMaxEntries - max entries in the array
  334. // dwSize - size of buffers ( may grow )
  335. // dwType - type of buffer ( see BUFFERTYPE_ constants above )
  336. //
  337. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  338. HRESULT CStructCache::Initialize( DWORD dwMaxEntries, DWORD dwSize, DWORD dwType )
  339. {
  340. DWORD dw;
  341. Lock();
  342. m_dwMaxEntries = min( MAXCACHEENTRIES, dwMaxEntries );
  343. m_dwUsedEntries = 0;
  344. m_dwType = dwType;
  345. // zero the array
  346. ZeroMemory( &m_aEntries, sizeof (CACHEENTRY) * MAXCACHEENTRIES );
  347. // go through an allocate buffers
  348. for ( dw = 0; dw < m_dwMaxEntries; dw++ )
  349. {
  350. LPDWORD pdwBuffer;
  351. pdwBuffer = (LPDWORD) ClientAlloc( dwSize );
  352. if ( NULL == pdwBuffer )
  353. {
  354. LOG((TL_ERROR, "Initialize - out of memory"));
  355. //
  356. // cleanup -- free whatever was allocated
  357. //
  358. for (int i = 0; i < dw; i++)
  359. {
  360. ClientFree(m_aEntries[i].pBuffer);
  361. m_aEntries[i].pBuffer = NULL;
  362. }
  363. m_dwMaxEntries = 0;
  364. Unlock();
  365. return E_OUTOFMEMORY;
  366. }
  367. // tapi structures have the size as the first
  368. // DWORD. Initialize this here
  369. pdwBuffer[0] = dwSize;
  370. // save the buffer
  371. m_aEntries[dw].pBuffer = (LPVOID)pdwBuffer;
  372. }
  373. Unlock();
  374. return S_OK;
  375. }
  376. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  377. //
  378. // Shutdown
  379. //
  380. // free the memory
  381. //
  382. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  383. HRESULT CStructCache::Shutdown()
  384. {
  385. DWORD dw;
  386. Lock();
  387. for (dw = 0; dw < m_dwMaxEntries; dw++)
  388. {
  389. if ( NULL != m_aEntries[dw].pBuffer )
  390. {
  391. ClientFree( m_aEntries[dw].pBuffer );
  392. m_aEntries[dw].pBuffer = NULL;
  393. }
  394. }
  395. Unlock();
  396. return S_OK;
  397. }
  398. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  399. //
  400. // GetBuffer
  401. //
  402. // pNewObject - object to get the buffer
  403. // ppReturnStuct - buffer for pNewObject to use
  404. //
  405. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  406. HRESULT CStructCache::GetBuffer( UINT_PTR pNewObject, LPVOID * ppReturnStruct )
  407. {
  408. Lock();
  409. // have we used all the entries?
  410. if ( m_dwUsedEntries < m_dwMaxEntries )
  411. {
  412. // nope - so just take the first free one
  413. *ppReturnStruct = m_aEntries[m_dwUsedEntries].pBuffer;
  414. m_aEntries[m_dwUsedEntries].pObject = pNewObject;
  415. // in number used
  416. m_dwUsedEntries++;
  417. }
  418. else
  419. {
  420. // yes, so take the buffer from the LRU one
  421. UINT_PTR pObject;
  422. // get the object that is losing it's buffer
  423. // and the buffer
  424. pObject = m_aEntries[m_dwMaxEntries-1].pObject;
  425. *ppReturnStruct = m_aEntries[m_dwMaxEntries-1].pBuffer;
  426. switch ( m_dwType )
  427. {
  428. // inform the object that it's losing
  429. // it's buffer
  430. case BUFFERTYPE_ADDRCAP:
  431. {
  432. CAddress * pAddress;
  433. pAddress = (CAddress *)pObject;
  434. if( pAddress != NULL)
  435. {
  436. pAddress->SetAddrCapBuffer( NULL );
  437. }
  438. break;
  439. }
  440. case BUFFERTYPE_LINEDEVCAP:
  441. {
  442. CAddress * pAddress;
  443. pAddress = (CAddress *)pObject;
  444. if( pAddress != NULL)
  445. {
  446. pAddress->SetLineDevCapBuffer( NULL );
  447. }
  448. break;
  449. }
  450. case BUFFERTYPE_PHONECAP:
  451. {
  452. CPhone * pPhone;
  453. pPhone = (CPhone *)pObject;
  454. if( pPhone != NULL)
  455. {
  456. pPhone->SetPhoneCapBuffer( NULL );
  457. }
  458. break;
  459. }
  460. default:
  461. break;
  462. }
  463. // move all elements in the array "down" one
  464. MoveMemory(
  465. &(m_aEntries[1]),
  466. &(m_aEntries[0]),
  467. (m_dwMaxEntries-1) * sizeof(CACHEENTRY)
  468. );
  469. // put the new object at the front of the array
  470. m_aEntries[0].pObject = pNewObject;
  471. m_aEntries[0].pBuffer = *ppReturnStruct;
  472. ZeroMemory(
  473. ((LPDWORD)(*ppReturnStruct)) + 1,
  474. ((LPDWORD)(*ppReturnStruct))[0] - sizeof(DWORD)
  475. );
  476. }
  477. Unlock();
  478. return S_OK;
  479. }
  480. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  481. //
  482. // SetBuffer
  483. //
  484. // this is called when the buffer had to be realloced. The
  485. // owning object freed the original buffer, and is setting the
  486. // newly alloced buffer.
  487. //
  488. // pObject - object that realloc'd
  489. // pNewStruct - new struct
  490. //
  491. // Note the implementation is straightforward here - just run
  492. // through the array looking for the object
  493. //
  494. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  495. HRESULT CStructCache::SetBuffer( UINT_PTR pObject, LPVOID pNewStruct )
  496. {
  497. DWORD dw;
  498. Lock();
  499. for ( dw = 0; dw < m_dwUsedEntries; dw++ )
  500. {
  501. if ( m_aEntries[dw].pObject == pObject )
  502. {
  503. m_aEntries[dw].pBuffer = pNewStruct;
  504. break;
  505. }
  506. }
  507. Unlock();
  508. return S_OK;
  509. }
  510. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  511. //
  512. // InvalidateBuffer
  513. //
  514. // This is called when the owning object (pObject) is being released
  515. // to prevent problems in getBuffer() when a cache entry is reused &
  516. // we inform the object that it's losing it's buffer.
  517. // We set the pObject member in the cache entry to 0 & prevent
  518. // getBuffer from accessing the original owner object which may have
  519. // been released.
  520. //
  521. // pObject - object that realloc'd
  522. // pNewStruct - new struct
  523. //
  524. // Note the implementation is straightforward here - just run
  525. // through the array looking for the object
  526. //
  527. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  528. HRESULT CStructCache::InvalidateBuffer( UINT_PTR pObject )
  529. {
  530. DWORD dw;
  531. Lock();
  532. for ( dw = 0; dw < m_dwUsedEntries; dw++ )
  533. {
  534. if ( m_aEntries[dw].pObject == pObject )
  535. {
  536. m_aEntries[dw].pObject = NULL;
  537. break;
  538. }
  539. }
  540. Unlock();
  541. return S_OK;
  542. }
  543. PWSTR
  544. MyLoadString( UINT uID )
  545. {
  546. PWSTR pTempBuffer = NULL;
  547. int iSize, iCurrentSize = 128;
  548. do
  549. {
  550. if ( NULL != pTempBuffer )
  551. {
  552. ClientFree( pTempBuffer );
  553. }
  554. iCurrentSize *= 2;
  555. pTempBuffer = (PWSTR) ClientAlloc( iCurrentSize * sizeof( WCHAR ) );
  556. if (NULL == pTempBuffer)
  557. {
  558. LOG((TL_ERROR, "MyLoadString - alloc failed" ));
  559. return NULL;
  560. }
  561. iSize = ::LoadStringW(
  562. _Module.GetResourceInstance(),
  563. uID,
  564. pTempBuffer,
  565. iCurrentSize
  566. );
  567. if ( 0 == iSize )
  568. {
  569. LOG((
  570. TL_ERROR,
  571. "MyLoadString - LoadString failed - %lx",
  572. GetLastError()
  573. ));
  574. return NULL;
  575. }
  576. } while ( (iSize >= (iCurrentSize - 1) ) );
  577. return pTempBuffer;
  578. }
  579. #ifdef TRACELOG
  580. BOOL g_bLoggingEnabled = FALSE;
  581. DWORD sg_dwTraceID = INVALID_TRACEID;
  582. char sg_szTraceName[100]; // saves name of dll
  583. DWORD sg_dwTracingToDebugger = 0;
  584. DWORD sg_dwTracingToConsole = 0;
  585. DWORD sg_dwTracingToFile = 0;
  586. DWORD sg_dwDebuggerMask = 0;
  587. BOOL TRACELogRegister(LPCTSTR szName)
  588. {
  589. HKEY hTracingKey;
  590. char szTracingKey[100];
  591. const char szDebuggerTracingEnableValue[] = "EnableDebuggerTracing";
  592. const char szConsoleTracingEnableValue[] = "EnableConsoleTracing";
  593. const char szFileTracingEnableValue[] = "EnableFileTracing";
  594. const char szTracingMaskValue[] = "ConsoleTracingMask";
  595. sg_dwTracingToDebugger = 0;
  596. sg_dwTracingToConsole = 0;
  597. sg_dwTracingToFile = 0;
  598. #ifdef UNICODE
  599. wsprintfA(szTracingKey, "Software\\Microsoft\\Tracing\\%ls", szName);
  600. #else
  601. wsprintfA(szTracingKey, "Software\\Microsoft\\Tracing\\%s", szName);
  602. #endif
  603. if ( ERROR_SUCCESS == RegOpenKeyExA(HKEY_LOCAL_MACHINE,
  604. szTracingKey,
  605. 0,
  606. KEY_READ,
  607. &hTracingKey) )
  608. {
  609. DWORD dwDataSize = sizeof (DWORD);
  610. DWORD dwDataType;
  611. RegQueryValueExA(hTracingKey,
  612. szDebuggerTracingEnableValue,
  613. 0,
  614. &dwDataType,
  615. (LPBYTE) &sg_dwTracingToDebugger,
  616. &dwDataSize);
  617. RegQueryValueExA(hTracingKey,
  618. szConsoleTracingEnableValue,
  619. 0,
  620. &dwDataType,
  621. (LPBYTE) &sg_dwTracingToConsole,
  622. &dwDataSize);
  623. RegQueryValueExA(hTracingKey,
  624. szFileTracingEnableValue,
  625. 0,
  626. &dwDataType,
  627. (LPBYTE) &sg_dwTracingToFile,
  628. &dwDataSize);
  629. RegQueryValueExA(hTracingKey,
  630. szTracingMaskValue,
  631. 0,
  632. &dwDataType,
  633. (LPBYTE) &sg_dwDebuggerMask,
  634. &dwDataSize);
  635. RegCloseKey (hTracingKey);
  636. }
  637. else
  638. {
  639. //
  640. // the key could not be opened. in case the key does not exist,
  641. // register with rtutils so that the reg keys get created
  642. //
  643. #ifdef UNICODE
  644. wsprintfA(sg_szTraceName, "%ls", szName);
  645. #else
  646. wsprintfA(sg_szTraceName, "%s", szName);
  647. #endif
  648. //
  649. // tracing should not have been initialized
  650. //
  651. _ASSERTE(sg_dwTraceID == INVALID_TRACEID);
  652. //
  653. // note that this trace id will not be cleaned up. this is ok -- this
  654. // is a leak of one registration "handle" and it only happens the
  655. // first time the dll gets loaded.
  656. //
  657. sg_dwTraceID = TraceRegister(szName);
  658. sg_dwTraceID = INVALID_TRACEID;
  659. }
  660. if (sg_dwTracingToDebugger || sg_dwTracingToConsole || sg_dwTracingToFile)
  661. {
  662. //
  663. // we want to try to initialize logging
  664. //
  665. if (sg_dwTracingToConsole || sg_dwTracingToFile)
  666. {
  667. #ifdef UNICODE
  668. wsprintfA(sg_szTraceName, "%ls", szName);
  669. #else
  670. wsprintfA(sg_szTraceName, "%s", szName);
  671. #endif
  672. //
  673. // tracing should not have been initialized
  674. //
  675. _ASSERTE(sg_dwTraceID == INVALID_TRACEID);
  676. //
  677. // register
  678. //
  679. sg_dwTraceID = TraceRegister(szName);
  680. }
  681. //
  682. // if tracing registration succeeded or debug tracing is on, set the
  683. // global logging flag
  684. //
  685. if ( sg_dwTracingToDebugger || (sg_dwTraceID != INVALID_TRACEID) )
  686. {
  687. g_bLoggingEnabled = TRUE;
  688. LOG((TL_TRACE, "TRACELogRegister - logging configured" ));
  689. return TRUE;
  690. }
  691. else
  692. {
  693. //
  694. // TraceRegister failed and debugger logging is off
  695. //
  696. return FALSE;
  697. }
  698. }
  699. //
  700. // logging is not enabled
  701. //
  702. return TRUE;
  703. }
  704. void TRACELogDeRegister()
  705. {
  706. if (g_bLoggingEnabled)
  707. {
  708. LOG((TL_TRACE, "TRACELogDeRegister - disabling logging" ));
  709. sg_dwTracingToDebugger = 0;
  710. sg_dwTracingToConsole = 0;
  711. sg_dwTracingToFile = 0;
  712. if (sg_dwTraceID != INVALID_TRACEID)
  713. {
  714. TraceDeregister(sg_dwTraceID);
  715. sg_dwTraceID = INVALID_TRACEID;
  716. }
  717. g_bLoggingEnabled = FALSE;
  718. }
  719. }
  720. void TRACELogPrint(IN DWORD dwDbgLevel, IN LPCSTR lpszFormat, IN ...)
  721. {
  722. char szTraceBuf[MAXDEBUGSTRINGLENGTH + 1];
  723. va_list arglist;
  724. if ( ( sg_dwTracingToDebugger > 0 ) &&
  725. ( 0 != ( dwDbgLevel & sg_dwDebuggerMask ) ) )
  726. {
  727. // retrieve local time
  728. SYSTEMTIME SystemTime;
  729. GetLocalTime(&SystemTime);
  730. wsprintfA(szTraceBuf,
  731. "%s:[%02u:%02u:%02u.%03u,tid=%x:] [%s] ",
  732. sg_szTraceName,
  733. SystemTime.wHour,
  734. SystemTime.wMinute,
  735. SystemTime.wSecond,
  736. SystemTime.wMilliseconds,
  737. GetCurrentThreadId(),
  738. TraceLevel(dwDbgLevel));
  739. va_list ap;
  740. va_start(ap, lpszFormat);
  741. _vsnprintf(&szTraceBuf[lstrlenA(szTraceBuf)],
  742. MAXDEBUGSTRINGLENGTH - lstrlenA(szTraceBuf),
  743. lpszFormat,
  744. ap
  745. );
  746. lstrcatA (szTraceBuf, "\n");
  747. OutputDebugStringA (szTraceBuf);
  748. va_end(ap);
  749. }
  750. if (sg_dwTraceID != INVALID_TRACEID)
  751. {
  752. wsprintfA(szTraceBuf, "[%s] %s", TraceLevel(dwDbgLevel), lpszFormat);
  753. va_start(arglist, lpszFormat);
  754. TraceVprintfExA(sg_dwTraceID, dwDbgLevel | TRACE_USE_MSEC, szTraceBuf, arglist);
  755. va_end(arglist);
  756. }
  757. }
  758. void TRACELogPrint(IN DWORD dwDbgLevel, HRESULT hr, IN LPCSTR lpszFormat, IN ...)
  759. {
  760. char szTraceBuf[MAXDEBUGSTRINGLENGTH + 1];
  761. LPVOID lpMsgBuf = NULL; // Temp buffer for error code
  762. va_list arglist;
  763. // Get the error message relating to our HRESULT
  764. TAPIFormatMessage(hr, &lpMsgBuf);
  765. if ( ( sg_dwTracingToDebugger > 0 ) &&
  766. ( 0 != ( dwDbgLevel & sg_dwDebuggerMask ) ) )
  767. {
  768. // retrieve local time
  769. SYSTEMTIME SystemTime;
  770. GetLocalTime(&SystemTime);
  771. wsprintfA(szTraceBuf,
  772. "%s:[%02u:%02u:%02u.%03u,tid=%x:] [%s] ",
  773. sg_szTraceName,
  774. SystemTime.wHour,
  775. SystemTime.wMinute,
  776. SystemTime.wSecond,
  777. SystemTime.wMilliseconds,
  778. GetCurrentThreadId(),
  779. TraceLevel(dwDbgLevel)
  780. );
  781. va_list ap;
  782. va_start(ap, lpszFormat);
  783. _vsnprintf(&szTraceBuf[lstrlenA(szTraceBuf)],
  784. MAXDEBUGSTRINGLENGTH - lstrlenA(szTraceBuf),
  785. lpszFormat,
  786. ap
  787. );
  788. wsprintfA(&szTraceBuf[lstrlenA(szTraceBuf)],
  789. " Returned[%lx] %s\n",
  790. hr,
  791. lpMsgBuf);
  792. OutputDebugStringA (szTraceBuf);
  793. va_end(ap);
  794. }
  795. if (sg_dwTraceID != INVALID_TRACEID)
  796. {
  797. wsprintfA(szTraceBuf, "[%s] %s Returned[%lx] %s", TraceLevel(dwDbgLevel), lpszFormat,hr, lpMsgBuf );
  798. va_start(arglist, lpszFormat);
  799. TraceVprintfExA(sg_dwTraceID, dwDbgLevel | TRACE_USE_MSEC, szTraceBuf, arglist);
  800. va_end(arglist);
  801. }
  802. if(lpMsgBuf != NULL)
  803. {
  804. LocalFree( lpMsgBuf ); // Free the temp buffer.
  805. }
  806. }
  807. char *TraceLevel(DWORD dwDbgLevel)
  808. {
  809. switch(dwDbgLevel)
  810. {
  811. case TL_ERROR: return "ERROR";
  812. case TL_WARN: return "WARN ";
  813. case TL_INFO: return "INFO ";
  814. case TL_TRACE: return "TRACE";
  815. case TL_EVENT: return "EVENT";
  816. default: return " ??? ";
  817. }
  818. }
  819. #endif // TRACELOG