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.

984 lines
28 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. utils.h
  5. Abstract:
  6. Author:
  7. mquinton 06-30-98
  8. Notes:
  9. Revision History:
  10. --*/
  11. #ifndef __UTILS_H__
  12. #define __UTILS_H__
  13. #ifdef TRACELOG
  14. #include <rtutils.h>
  15. //#include <windef.h>
  16. //#include <winnt.h>
  17. extern BOOL g_bLoggingEnabled;
  18. #define MAXDEBUGSTRINGLENGTH 1024
  19. #define TL_ERROR ((DWORD)0x00010000 | TRACE_USE_MASK)
  20. #define TL_WARN ((DWORD)0x00020000 | TRACE_USE_MASK)
  21. #define TL_INFO ((DWORD)0x00040000 | TRACE_USE_MASK)
  22. #define TL_TRACE ((DWORD)0x00080000 | TRACE_USE_MASK)
  23. #define TL_EVENT ((DWORD)0x00100000 | TRACE_USE_MASK)
  24. BOOL TRACELogRegister(LPCTSTR szName);
  25. void TRACELogDeRegister();
  26. void TRACELogPrint(IN DWORD dwDbgLevel, IN LPCSTR DbgMessage, IN ...);
  27. void TRACELogPrint(IN DWORD dwDbgLevel, HRESULT hr, IN LPCSTR lpszFormat, IN ...);
  28. extern char *TraceLevel(DWORD dwDbgLevel);
  29. extern void TAPIFormatMessage(HRESULT hr, LPVOID lpMsgBuf);
  30. #define TRACELOGREGISTER(arg) TRACELogRegister(arg)
  31. #define TRACELOGDEREGISTER() g_bLoggingEnabled?TRACELogDeRegister():0
  32. #define LOG(arg) g_bLoggingEnabled?TRACELogPrint arg:0
  33. #define STATICLOG(arg) g_bLoggingEnabled?StaticTRACELogPrint arg:0
  34. extern char sg_szTraceName[100];
  35. extern DWORD sg_dwTracingToDebugger;
  36. extern DWORD sg_dwDebuggerMask;
  37. extern DWORD sg_dwTraceID;
  38. #define DECLARE_DEBUG_ADDREF_RELEASE(x) \
  39. void LogDebugAddRef(DWORD dw) \
  40. { TRACELogPrint(TL_INFO, "%s::AddRef() = %d - this %lx", _T(#x), dw, this); } \
  41. void LogDebugRelease(DWORD dw) \
  42. { TRACELogPrint(TL_INFO, "%s::Release() = %d - this %lx", _T(#x), dw, this); }
  43. #define DECLARE_TRACELOG_CLASS(x) \
  44. void TRACELogPrint(IN DWORD dwDbgLevel, IN LPCSTR lpszFormat, IN ...) \
  45. { \
  46. char szTraceBuf[MAXDEBUGSTRINGLENGTH + 1]; \
  47. va_list arglist; \
  48. \
  49. if ( ( sg_dwTracingToDebugger > 0 ) && \
  50. ( 0 != ( dwDbgLevel & sg_dwDebuggerMask ) ) ) \
  51. { \
  52. SYSTEMTIME SystemTime; \
  53. GetLocalTime(&SystemTime); \
  54. \
  55. wsprintfA(szTraceBuf, \
  56. "%s:[%02u:%02u:%02u.%03u,tid=%x:] [%s] (%p) %s::", \
  57. sg_szTraceName, \
  58. SystemTime.wHour, \
  59. SystemTime.wMinute, \
  60. SystemTime.wSecond, \
  61. SystemTime.wMilliseconds, \
  62. GetCurrentThreadId(), \
  63. TraceLevel(dwDbgLevel), \
  64. this, \
  65. _T(#x)); \
  66. \
  67. va_list ap; \
  68. va_start(ap, lpszFormat); \
  69. \
  70. _vsnprintf(&szTraceBuf[lstrlenA(szTraceBuf)], \
  71. MAXDEBUGSTRINGLENGTH - lstrlenA(szTraceBuf), \
  72. lpszFormat, \
  73. ap \
  74. ); \
  75. \
  76. lstrcatA (szTraceBuf, "\n"); \
  77. \
  78. OutputDebugStringA (szTraceBuf); \
  79. \
  80. va_end(ap); \
  81. } \
  82. \
  83. if (sg_dwTraceID != INVALID_TRACEID) \
  84. { \
  85. wsprintfA(szTraceBuf, "[%s] (%p) %s::%s", TraceLevel(dwDbgLevel), this, _T(#x), lpszFormat); \
  86. \
  87. va_start(arglist, lpszFormat); \
  88. TraceVprintfExA(sg_dwTraceID, dwDbgLevel | TRACE_USE_MSEC, szTraceBuf, arglist); \
  89. va_end(arglist); \
  90. } \
  91. } \
  92. \
  93. void TRACELogPrint(IN DWORD dwDbgLevel,IN HRESULT hr, IN LPCSTR lpszFormat, IN ...) \
  94. { \
  95. char szTraceBuf[MAXDEBUGSTRINGLENGTH + 1]; \
  96. LPVOID lpMsgBuf = NULL; \
  97. va_list arglist; \
  98. \
  99. TAPIFormatMessage(hr, &lpMsgBuf); \
  100. \
  101. if ( ( sg_dwTracingToDebugger > 0 ) && \
  102. ( 0 != ( dwDbgLevel & sg_dwDebuggerMask ) ) ) \
  103. { \
  104. SYSTEMTIME SystemTime; \
  105. GetLocalTime(&SystemTime); \
  106. \
  107. wsprintfA(szTraceBuf, \
  108. "%s:[%02u:%02u:%02u.%03u,tid=%x:] [%s] (%p) %s::", \
  109. sg_szTraceName, \
  110. SystemTime.wHour, \
  111. SystemTime.wMinute, \
  112. SystemTime.wSecond, \
  113. SystemTime.wMilliseconds, \
  114. GetCurrentThreadId(), \
  115. TraceLevel(dwDbgLevel), \
  116. this, \
  117. _T(#x) \
  118. ); \
  119. \
  120. va_list ap; \
  121. va_start(ap, lpszFormat); \
  122. \
  123. _vsnprintf(&szTraceBuf[lstrlenA(szTraceBuf)], \
  124. MAXDEBUGSTRINGLENGTH - lstrlenA(szTraceBuf), \
  125. lpszFormat, \
  126. ap \
  127. ); \
  128. \
  129. wsprintfA(&szTraceBuf[lstrlenA(szTraceBuf)], \
  130. " Returned[%lx] %s\n", \
  131. hr, \
  132. lpMsgBuf); \
  133. \
  134. OutputDebugStringA (szTraceBuf); \
  135. \
  136. va_end(ap); \
  137. } \
  138. \
  139. if (sg_dwTraceID != INVALID_TRACEID) \
  140. { \
  141. wsprintfA(szTraceBuf, "[%s] (%p) %s::%s Returned[%lx] %s", TraceLevel(dwDbgLevel), this, _T(#x), lpszFormat,hr, lpMsgBuf ); \
  142. \
  143. va_start(arglist, lpszFormat); \
  144. TraceVprintfExA(sg_dwTraceID, dwDbgLevel | TRACE_USE_MSEC, szTraceBuf, arglist); \
  145. va_end(arglist); \
  146. } \
  147. \
  148. if(lpMsgBuf != NULL) \
  149. { \
  150. LocalFree( lpMsgBuf ); \
  151. } \
  152. } \
  153. \
  154. static void StaticTRACELogPrint(IN DWORD dwDbgLevel, IN LPCSTR lpszFormat, IN ...) \
  155. { \
  156. char szTraceBuf[MAXDEBUGSTRINGLENGTH + 1]; \
  157. va_list arglist; \
  158. \
  159. if ( ( sg_dwTracingToDebugger > 0 ) && \
  160. ( 0 != ( dwDbgLevel & sg_dwDebuggerMask ) ) ) \
  161. { \
  162. SYSTEMTIME SystemTime; \
  163. GetLocalTime(&SystemTime); \
  164. \
  165. wsprintfA(szTraceBuf, \
  166. "%s:[%02u:%02u:%02u.%03u,tid=%x:] [%s] %s::", \
  167. sg_szTraceName, \
  168. SystemTime.wHour, \
  169. SystemTime.wMinute, \
  170. SystemTime.wSecond, \
  171. SystemTime.wMilliseconds, \
  172. GetCurrentThreadId(), \
  173. TraceLevel(dwDbgLevel), \
  174. _T(#x)); \
  175. \
  176. va_list ap; \
  177. va_start(ap, lpszFormat); \
  178. \
  179. _vsnprintf(&szTraceBuf[lstrlenA(szTraceBuf)], \
  180. MAXDEBUGSTRINGLENGTH - lstrlenA(szTraceBuf), \
  181. lpszFormat, \
  182. ap \
  183. ); \
  184. \
  185. lstrcatA (szTraceBuf, "\n"); \
  186. \
  187. OutputDebugStringA (szTraceBuf); \
  188. \
  189. va_end(ap); \
  190. } \
  191. \
  192. if (sg_dwTraceID != INVALID_TRACEID) \
  193. { \
  194. wsprintfA(szTraceBuf, "[%s] %s::%s", TraceLevel(dwDbgLevel), _T(#x), lpszFormat); \
  195. \
  196. va_start(arglist, lpszFormat); \
  197. TraceVprintfExA(sg_dwTraceID, dwDbgLevel | TRACE_USE_MSEC, szTraceBuf, arglist); \
  198. va_end(arglist); \
  199. } \
  200. } \
  201. \
  202. static void StaticTRACELogPrint(IN DWORD dwDbgLevel,IN HRESULT hr, IN LPCSTR lpszFormat, IN ...) \
  203. { \
  204. char szTraceBuf[MAXDEBUGSTRINGLENGTH + 1]; \
  205. LPVOID lpMsgBuf = NULL; \
  206. va_list arglist; \
  207. \
  208. TAPIFormatMessage(hr, &lpMsgBuf); \
  209. \
  210. if ( ( sg_dwTracingToDebugger > 0 ) && \
  211. ( 0 != ( dwDbgLevel & sg_dwDebuggerMask ) ) ) \
  212. { \
  213. SYSTEMTIME SystemTime; \
  214. GetLocalTime(&SystemTime); \
  215. \
  216. wsprintfA(szTraceBuf, \
  217. "%s:[%02u:%02u:%02u.%03u,tid=%x:] [%s] %s::", \
  218. sg_szTraceName, \
  219. SystemTime.wHour, \
  220. SystemTime.wMinute, \
  221. SystemTime.wSecond, \
  222. SystemTime.wMilliseconds, \
  223. GetCurrentThreadId(), \
  224. TraceLevel(dwDbgLevel), \
  225. _T(#x) \
  226. ); \
  227. \
  228. va_list ap; \
  229. va_start(ap, lpszFormat); \
  230. \
  231. _vsnprintf(&szTraceBuf[lstrlenA(szTraceBuf)], \
  232. MAXDEBUGSTRINGLENGTH - lstrlenA(szTraceBuf), \
  233. lpszFormat, \
  234. ap \
  235. ); \
  236. \
  237. wsprintfA(&szTraceBuf[lstrlenA(szTraceBuf)], \
  238. " Returned[%lx] %s\n", \
  239. hr, \
  240. lpMsgBuf); \
  241. \
  242. OutputDebugStringA (szTraceBuf); \
  243. \
  244. va_end(ap); \
  245. } \
  246. \
  247. if (sg_dwTraceID != INVALID_TRACEID) \
  248. { \
  249. wsprintfA(szTraceBuf, "[%s] %s::%s Returned[%lx] %s", TraceLevel(dwDbgLevel), _T(#x), lpszFormat,hr, lpMsgBuf ); \
  250. \
  251. va_start(arglist, lpszFormat); \
  252. TraceVprintfExA(sg_dwTraceID, dwDbgLevel | TRACE_USE_MSEC, szTraceBuf, arglist); \
  253. va_end(arglist); \
  254. } \
  255. \
  256. if(lpMsgBuf != NULL) \
  257. { \
  258. LocalFree( lpMsgBuf ); \
  259. } \
  260. }
  261. #else // TRACELOG not defined
  262. #define TRACELOGREGISTER(arg)
  263. #define TRACELOGDEREGISTER()
  264. #define LOG(arg)
  265. #define STATICLOG(arg)
  266. #define DECLARE_DEBUG_ADDREF_RELEASE(x)
  267. #define DECLARE_TRACELOG_CLASS(x)
  268. #endif // TRACELOG
  269. class CAsyncRequestReply
  270. {
  271. private:
  272. HANDLE hRepliedSemaphore;
  273. DWORD dwID;
  274. BOOL bReply;
  275. HRESULT hResult;
  276. public:
  277. DECLARE_TRACELOG_CLASS(CAsyncRequestReply)
  278. CAsyncRequestReply(DWORD id, BOOL b, HRESULT hr)
  279. {
  280. if( (hRepliedSemaphore = CreateSemaphore(NULL,0,1,NULL)) == NULL )
  281. {
  282. LOG((TL_INFO, "create CAsyncRequest - CreateSemaphore failed"));
  283. hResult = E_OUTOFMEMORY;
  284. }
  285. else
  286. {
  287. dwID = id;
  288. bReply = b;
  289. hResult = hr;
  290. LOG((TL_INFO, "create CAsyncRequest %d ",dwID));
  291. }
  292. }
  293. ~CAsyncRequestReply()
  294. {
  295. LOG((TL_INFO, "delete CAsyncRequest %d ",dwID));
  296. if( NULL != hRepliedSemaphore )
  297. {
  298. CloseHandle(hRepliedSemaphore);
  299. }
  300. }
  301. inline DWORD getID() {return dwID;};
  302. inline BOOL IsReply() {return bReply;};
  303. inline HRESULT getResult() {return hResult;};
  304. inline void setResult(HRESULT hr) {hResult = hr;};
  305. HRESULT wait()
  306. {
  307. LOG((TL_INFO, "wait CAsyncRequest %d ",dwID));
  308. extern DWORD gdwTapi2AsynchronousCallTimeout;
  309. DWORD rc = WaitForSingleObject(hRepliedSemaphore, gdwTapi2AsynchronousCallTimeout);
  310. switch (rc)
  311. {
  312. case WAIT_ABANDONED:
  313. LOG((TL_ERROR, "wait CAsyncRequest %d WaitForSingle object returned WAIT_ABANDONED",dwID));
  314. hResult = TAPIERR_REQUESTFAILED;
  315. break;
  316. case WAIT_OBJECT_0:
  317. break;
  318. case WAIT_TIMEOUT:
  319. LOG((TL_WARN, "wait CAsyncRequest %d WaitForSingle object returned WAIT_TIMEOUT",dwID));
  320. // -1 won't overlap with any value that may be returned from tapi2 calls.
  321. hResult = -1;
  322. break;
  323. case WAIT_FAILED:
  324. {
  325. DWORD nLastError = GetLastError();
  326. LOG((TL_ERROR, "wait CAsyncRequest %d WaitForSingle object returned WAIT_FAILED, LastError = %d", dwID, nLastError));
  327. hResult = TAPIERR_REQUESTFAILED;
  328. break;
  329. }
  330. default:
  331. break;
  332. }
  333. return hResult;
  334. }
  335. void signal()
  336. {
  337. LOG((TL_INFO, "signal CAsyncRequest %d ",dwID));
  338. ReleaseSemaphore(hRepliedSemaphore, 1, NULL);
  339. }
  340. };
  341. typedef list<CAsyncRequestReply *> RequestReplyList;
  342. class CAsyncReplyList
  343. {
  344. public:
  345. DECLARE_TRACELOG_CLASS(CAsyncReplyList)
  346. private:
  347. RequestReplyList replyList;
  348. CRITICAL_SECTION csReply;
  349. CAsyncRequestReply *find(DWORD dwID)
  350. {
  351. RequestReplyList::iterator i;
  352. CAsyncRequestReply *pResult = NULL;
  353. // walk list searching for match
  354. i = replyList.begin();
  355. // iterate over current replies
  356. while ( i != replyList.end() )
  357. {
  358. // found it
  359. if ((*i)->getID() == dwID )
  360. {
  361. pResult = *i;
  362. break;
  363. }
  364. i++;
  365. }
  366. //returning pointer to matching entry or NULL
  367. return pResult;
  368. }
  369. public:
  370. CAsyncReplyList() {InitializeCriticalSection( &csReply );};
  371. ~CAsyncReplyList()
  372. {
  373. FreeList();
  374. DeleteCriticalSection( &csReply );
  375. }
  376. void FreeList()
  377. {
  378. RequestReplyList::iterator i;
  379. EnterCriticalSection( &csReply );
  380. // walk list deleting entries
  381. i = replyList.begin();
  382. while ( i != replyList.end() )
  383. delete *i++;
  384. replyList.clear();
  385. LeaveCriticalSection( &csReply );
  386. };
  387. void remove(CAsyncRequestReply *a)
  388. {
  389. EnterCriticalSection( &csReply );
  390. replyList.remove(a);
  391. LeaveCriticalSection( &csReply );
  392. }
  393. CAsyncRequestReply *addRequest(DWORD id)
  394. {
  395. CAsyncRequestReply *pReply;
  396. EnterCriticalSection( &csReply );
  397. // Check list to see if we're already on the list ( i.e. the response LINE_REPLY got here before us)
  398. pReply = find(id);
  399. if (pReply == NULL || !pReply->IsReply())
  400. {
  401. // No so we got here before the reply, create a new request entry on the list
  402. pReply = new CAsyncRequestReply(id, FALSE, 0);
  403. if (NULL == pReply)
  404. {
  405. LOG((TL_ERROR, "Could not alloc for CAsyncRequestReply"));
  406. }
  407. else if( pReply->getResult() == E_OUTOFMEMORY )
  408. {
  409. delete pReply;
  410. pReply = NULL;
  411. LOG((TL_ERROR, "addRequest - Create Semaphore failed"));
  412. }
  413. else
  414. {
  415. try
  416. {
  417. replyList.push_back(pReply);
  418. }
  419. catch(...)
  420. {
  421. delete pReply;
  422. pReply = NULL;
  423. LOG((TL_ERROR, "addRequest- failed - because of alloc failure"));
  424. }
  425. }
  426. }
  427. // Else, the reply comes before me, remove it from the list
  428. else
  429. {
  430. replyList.remove (pReply);
  431. }
  432. LeaveCriticalSection( &csReply );
  433. return pReply;
  434. }
  435. CAsyncRequestReply *addReply(DWORD id, HRESULT hr)
  436. {
  437. CAsyncRequestReply *pReply;
  438. EnterCriticalSection( &csReply );
  439. // Check list to see if we have a matching entry
  440. pReply = find(id);
  441. if (pReply == NULL || pReply->IsReply())
  442. {
  443. // No so we got here before the request returned, create a new entry on the list
  444. pReply = new CAsyncRequestReply(id, TRUE, hr);
  445. if (NULL == pReply)
  446. {
  447. LOG((TL_ERROR, "Could not alloc for CAsyncRequestReply"));
  448. }
  449. else if( pReply->getResult() == E_OUTOFMEMORY )
  450. {
  451. delete pReply;
  452. pReply = NULL;
  453. LOG((TL_ERROR, "addReply - Create Semaphore failed"));
  454. }
  455. else
  456. {
  457. try
  458. {
  459. replyList.push_back(pReply);
  460. }
  461. catch(...)
  462. {
  463. delete pReply;
  464. pReply = NULL;
  465. LOG((TL_ERROR, "addReply- failed - because of alloc failure"));
  466. }
  467. }
  468. }
  469. else
  470. {
  471. // Use the existing entry, set its return code & signal to the waiting request code
  472. pReply->setResult(hr);
  473. replyList.remove (pReply);
  474. }
  475. LeaveCriticalSection( &csReply );
  476. return pReply;
  477. }
  478. };
  479. ////////////////////////////////////////////////////////////////////
  480. //
  481. // Class CRetryQueue
  482. // Maintains queue of Async messages for retry.
  483. // Typically these relate to calls not yet entered in the call hash-
  484. // table, such that findCallObject failed. These are reprocessed
  485. // once the call is entered & the ghAsyncRetryQueueEvent event is
  486. // signalled.
  487. //
  488. // Added criticalsection - thread safe now
  489. //
  490. ////////////////////////////////////////////////////////////////////
  491. class CRetryQueue
  492. {
  493. typedef struct _tagRetryQueueEntry
  494. {
  495. DWORD dwRetryCount;
  496. PASYNCEVENTMSG pMessage;
  497. } RETRY_QUEUE_ENTRY, *PRETRY_QUEUE_ENTRY;
  498. typedef list<RETRY_QUEUE_ENTRY *> RetryQueueListType;
  499. #define MAX_REQUEUE_TRIES 3
  500. private:
  501. RetryQueueListType m_RetryQueueList;
  502. CRITICAL_SECTION m_cs;
  503. //
  504. // is the queue open for new entries?
  505. //
  506. BOOL m_bAcceptNewEntries;
  507. private:
  508. //
  509. // requeue the entry that failed processing. don't do this if the queue is
  510. // closed.
  511. //
  512. void RequeueEvent(PRETRY_QUEUE_ENTRY pQueueEntry);
  513. public:
  514. DECLARE_TRACELOG_CLASS(CRetryQueue)
  515. CRetryQueue()
  516. :m_bAcceptNewEntries(FALSE)
  517. {
  518. InitializeCriticalSection( &m_cs );
  519. }
  520. ~CRetryQueue();
  521. void Lock(){ EnterCriticalSection( &m_cs ); }
  522. void Unlock(){ LeaveCriticalSection( &m_cs ); }
  523. BOOL QueueEvent(PASYNCEVENTMSG pEvent);
  524. BOOL DequeueEvent(PRETRY_QUEUE_ENTRY * ppEvent);
  525. void ProcessQueue();
  526. void RemoveNewCallHub(DWORD);
  527. inline BOOL ItemsInQueue()
  528. {
  529. BOOL bReturn;
  530. Lock();
  531. bReturn = !m_RetryQueueList.empty();
  532. Unlock();
  533. return bReturn;
  534. }
  535. //
  536. // after this function returns, the queue will accept new entries
  537. //
  538. void OpenForNewEntries();
  539. //
  540. // new entries will be denied after this function returns
  541. //
  542. void CloseForNewEntries();
  543. };
  544. #define MAXCACHEENTRIES 5
  545. #define BUFFERTYPE_ADDRCAP 1
  546. #define BUFFERTYPE_LINEDEVCAP 2
  547. #define BUFFERTYPE_PHONECAP 3
  548. typedef struct
  549. {
  550. UINT_PTR pObject;
  551. LPVOID pBuffer;
  552. } CACHEENTRY;
  553. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  554. //
  555. // CStructCache
  556. //
  557. // A simple class to cache TAPI structures in tapi3.dll
  558. //
  559. // This implementation has an array of CACHEENTRY structures. Each
  560. // CACHEENTRY structure has 2 member:
  561. // pObject - the object that currently owns the buffer
  562. // pBuffer - the buffer
  563. //
  564. // The array is a fixed size, which is set when the class is initialized
  565. // The memory for the buffers is allocated during initialization as
  566. // well. It is possible that a buffer gets realloced (replaced)
  567. // at some time.
  568. //
  569. // This implementation assumes that the object that owns the buffer
  570. // uses it's critical sections correctly. That is, it is locked when
  571. // SetXxxBuffer is called, and it is locked when getting and using
  572. // a buffer If not, the buffer can disapper from the object at any time.
  573. //
  574. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  575. class CStructCache
  576. {
  577. private:
  578. CRITICAL_SECTION m_cs;
  579. DWORD m_dwType;
  580. DWORD m_dwMaxEntries;
  581. DWORD m_dwUsedEntries;
  582. CACHEENTRY m_aEntries[MAXCACHEENTRIES];
  583. public:
  584. DECLARE_TRACELOG_CLASS(CStructCache)
  585. CStructCache()
  586. {
  587. int iCount;
  588. InitializeCriticalSection( &m_cs );
  589. for( iCount=0; iCount<MAXCACHEENTRIES; iCount++)
  590. {
  591. m_aEntries[iCount].pObject = NULL;
  592. m_aEntries[iCount].pBuffer = NULL;
  593. }
  594. m_dwType = 0;
  595. m_dwMaxEntries = 0;
  596. m_dwUsedEntries = 0;
  597. }
  598. ~CStructCache()
  599. {
  600. DeleteCriticalSection( &m_cs );
  601. }
  602. void Lock()
  603. {
  604. EnterCriticalSection( &m_cs );
  605. }
  606. void Unlock()
  607. {
  608. LeaveCriticalSection( &m_cs );
  609. }
  610. HRESULT Initialize( DWORD dwMaxEntries, DWORD dwSize, DWORD dwType );
  611. HRESULT Shutdown();
  612. HRESULT GetBuffer( UINT_PTR pNewObject, LPVOID * ppReturnStruct );
  613. HRESULT SetBuffer( UINT_PTR pObject, LPVOID pNewStruct );
  614. HRESULT InvalidateBuffer( UINT_PTR pObject );
  615. };
  616. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  617. //
  618. // CArray - based on from CSimpleArray from atl
  619. //
  620. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  621. template <class T>
  622. class CTObjectArray
  623. {
  624. private:
  625. T * m_aT;
  626. int m_nSize;
  627. int m_nUsed;
  628. public:
  629. DECLARE_TRACELOG_CLASS(CTObjectArray)
  630. CTObjectArray() : m_aT(NULL), m_nSize(0), m_nUsed(0){}
  631. ~CTObjectArray()
  632. {}
  633. int GetSize() const
  634. {
  635. return m_nUsed;
  636. }
  637. BOOL Add(T& t)
  638. {
  639. if(m_nSize == m_nUsed)
  640. {
  641. T * aT;
  642. int nNewSize;
  643. nNewSize = (m_nSize == 0) ? 1 : (m_nSize * 2);
  644. aT = (T*) ClientAlloc (nNewSize * sizeof(T));
  645. if(aT == NULL)
  646. {
  647. return FALSE;
  648. }
  649. CopyMemory(
  650. aT,
  651. m_aT,
  652. m_nUsed * sizeof(T)
  653. );
  654. ClientFree( m_aT );
  655. m_aT = aT;
  656. m_nSize = nNewSize;
  657. }
  658. m_aT[m_nUsed] = t;
  659. t->AddRef();
  660. m_nUsed++;
  661. return TRUE;
  662. }
  663. BOOL Remove(T& t)
  664. {
  665. int nIndex = Find(t);
  666. if(nIndex == -1)
  667. return FALSE;
  668. return RemoveAt(nIndex);
  669. }
  670. BOOL RemoveAt(int nIndex)
  671. {
  672. m_aT[nIndex]->Release();
  673. if(nIndex != (m_nUsed - 1))
  674. {
  675. MoveMemory(
  676. (void*)&m_aT[nIndex],
  677. (void*)&m_aT[nIndex + 1],
  678. (m_nUsed - (nIndex + 1)) * sizeof(T)
  679. );
  680. }
  681. m_nUsed--;
  682. return TRUE;
  683. }
  684. void Shutdown()
  685. {
  686. if( NULL != m_aT )
  687. {
  688. int index;
  689. for (index = 0; index < m_nUsed; index++)
  690. {
  691. m_aT[index]->Release();
  692. }
  693. ClientFree(m_aT);
  694. m_aT = NULL;
  695. m_nUsed = 0;
  696. m_nSize = 0;
  697. }
  698. }
  699. T& operator[] (int nIndex) const
  700. {
  701. _ASSERTE(nIndex >= 0 && nIndex < m_nUsed);
  702. return m_aT[nIndex];
  703. }
  704. int Find(T& t) const
  705. {
  706. for(int i = 0; i < m_nUsed; i++)
  707. {
  708. if(m_aT[i] == t)
  709. return i;
  710. }
  711. return -1; // not found
  712. }
  713. };
  714. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  715. //
  716. // CArray - based on from CSimpleArray from atl
  717. //
  718. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  719. template <class T>
  720. class CTArray
  721. {
  722. private:
  723. T * m_aT;
  724. int m_nSize;
  725. int m_nUsed;
  726. public:
  727. DECLARE_TRACELOG_CLASS(CTArray)
  728. CTArray() : m_aT(NULL), m_nSize(0), m_nUsed(0){}
  729. ~CTArray()
  730. {}
  731. int GetSize() const
  732. {
  733. return m_nUsed;
  734. }
  735. BOOL Add(T& t)
  736. {
  737. if(m_nSize == m_nUsed)
  738. {
  739. T * aT;
  740. int nNewSize;
  741. nNewSize = (m_nSize == 0) ? 1 : (m_nSize * 2);
  742. aT = (T*) ClientAlloc (nNewSize * sizeof(T));
  743. if(aT == NULL)
  744. {
  745. return FALSE;
  746. }
  747. CopyMemory(
  748. aT,
  749. m_aT,
  750. m_nUsed * sizeof(T)
  751. );
  752. ClientFree( m_aT );
  753. m_aT = aT;
  754. m_nSize = nNewSize;
  755. }
  756. m_aT[m_nUsed] = t;
  757. m_nUsed++;
  758. return TRUE;
  759. }
  760. BOOL Remove(T& t)
  761. {
  762. int nIndex = Find(t);
  763. if(nIndex == -1)
  764. return FALSE;
  765. return RemoveAt(nIndex);
  766. }
  767. BOOL RemoveAt(int nIndex)
  768. {
  769. if(nIndex != (m_nUsed - 1))
  770. {
  771. MoveMemory(
  772. (void*)&m_aT[nIndex],
  773. (void*)&m_aT[nIndex + 1],
  774. (m_nUsed - (nIndex + 1)) * sizeof(T)
  775. );
  776. }
  777. m_nUsed--;
  778. return TRUE;
  779. }
  780. void Shutdown()
  781. {
  782. if( NULL != m_aT )
  783. {
  784. int index;
  785. ClientFree(m_aT);
  786. m_aT = NULL;
  787. m_nUsed = 0;
  788. m_nSize = 0;
  789. }
  790. }
  791. T& operator[] (int nIndex) const
  792. {
  793. _ASSERTE(nIndex >= 0 && nIndex < m_nUsed);
  794. return m_aT[nIndex];
  795. }
  796. int Find(T& t) const
  797. {
  798. for(int i = 0; i < m_nUsed; i++)
  799. {
  800. if(m_aT[i] == t)
  801. return i;
  802. }
  803. return -1; // not found
  804. }
  805. };
  806. #endif // __UTILS_H__