Source code of Windows XP (NT5)
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.

766 lines
18 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999-2000
  5. //
  6. // File: minici.hxx
  7. //
  8. // Contents: The CI basics for exception handling and smart pointers
  9. //
  10. // History: 26-Jul-1999 dlee Created
  11. //
  12. //--------------------------------------------------------------------------
  13. #if DBG == 1
  14. inline void __AssertFailure( const char *pszFile,
  15. int iLine,
  16. char const *pszMsg )
  17. {
  18. char ac[200];
  19. sprintf( ac, "assert in %s at line %d: ",
  20. pszFile, iLine );
  21. OutputDebugStringA( ac );
  22. OutputDebugStringA( pszMsg );
  23. OutputDebugStringA( "\n" );
  24. //DebugBreak();
  25. }
  26. #define Win4Assert(x) (void)((x) || (__AssertFailure( __FILE__, __LINE__, #x ),0))
  27. #else
  28. #define Win4Assert(x)
  29. #endif
  30. #define srchDebugOut(x)
  31. class CException
  32. {
  33. public:
  34. CException(long lError) : _lError(lError), _dbgInfo(0) {}
  35. CException() :
  36. _dbgInfo( 0 ),
  37. _lError( HRESULT_FROM_WIN32( GetLastError() ) ) {}
  38. long GetErrorCode() { return _lError;}
  39. void SetInfo(unsigned dbgInfo) { _dbgInfo = dbgInfo; }
  40. unsigned long GetInfo(void) const { return _dbgInfo; }
  41. protected:
  42. long _lError;
  43. unsigned long _dbgInfo;
  44. };
  45. #if DBG == 1
  46. inline void __DoThrow( const char * pszFile,
  47. int iLine,
  48. CException & e,
  49. const char * pszMsg )
  50. {
  51. char ac[200];
  52. sprintf( ac, "throw %#x %s line %d of %s\n",
  53. e.GetErrorCode(), pszMsg, iLine, pszFile );
  54. OutputDebugStringA( ac );
  55. throw e;
  56. }
  57. #define THROW( e ) __DoThrow( __FILE__, __LINE__, e, "" )
  58. #define THROWMSG( e, msg ) __DoThrow( __FILE__, __LINE__, e, msg )
  59. #else
  60. #define THROW( e ) throw e
  61. #define THROWMSG( e, msg ) throw e
  62. #endif
  63. #define TRY try
  64. #define CATCH( class, e ) catch( class & e )
  65. #define END_CATCH
  66. inline void * __cdecl operator new( size_t st )
  67. {
  68. void *p = (void *) LocalAlloc( LMEM_FIXED, st );
  69. if ( 0 == p )
  70. THROWMSG( CException(), "out of memory" );
  71. return p;
  72. } //new
  73. inline void __cdecl operator delete( void *pv )
  74. {
  75. if ( 0 != pv )
  76. LocalFree( (HLOCAL) pv );
  77. } //delete
  78. inline void _cdecl SystemExceptionTranslator(
  79. unsigned int uiWhat,
  80. struct _EXCEPTION_POINTERS * pexcept )
  81. {
  82. THROWMSG( CException( uiWhat ), "translated system exception" );
  83. }
  84. #pragma warning(4:4535) // set_se_translator used w/o /EHa
  85. class CTranslateSystemExceptions
  86. {
  87. public:
  88. CTranslateSystemExceptions()
  89. {
  90. _tf = _set_se_translator( SystemExceptionTranslator );
  91. }
  92. ~CTranslateSystemExceptions()
  93. {
  94. _set_se_translator( _tf );
  95. }
  96. private:
  97. _se_translator_function _tf;
  98. };
  99. //+-------------------------------------------------------------------------
  100. //
  101. // Template: XPtr
  102. //
  103. // Synopsis: Template for managing ownership of memory
  104. //
  105. //--------------------------------------------------------------------------
  106. template<class T> class XPtr
  107. {
  108. public:
  109. XPtr( T * p = 0 ) : _p( p ) {}
  110. ~XPtr() { Free(); }
  111. void SetSize( unsigned c ) { Free(); _p = new T [ c ]; }
  112. void Set ( T * p ) { Win4Assert( 0 == _p ); _p = p; }
  113. T * Get() const { return _p ; }
  114. void Free() { delete Acquire(); }
  115. T & operator[]( unsigned i ) { return _p[i]; }
  116. T const & operator[]( unsigned i ) const { return _p[i]; }
  117. T * Acquire() { T * p = _p; _p = 0; return p; }
  118. BOOL IsNull() const { return ( 0 == _p ); }
  119. T* operator->() { return _p; }
  120. T const * operator->() const { return _p; }
  121. private:
  122. T * _p;
  123. };
  124. //+-------------------------------------------------------------------------
  125. //
  126. // Template: XInterface
  127. //
  128. // Synopsis: Template for managing ownership of interfaces
  129. //
  130. //--------------------------------------------------------------------------
  131. template<class T> class XInterface
  132. {
  133. public:
  134. XInterface( T * p = 0 ) : _p( p ) {}
  135. ~XInterface() { if ( 0 != _p ) _p->Release(); }
  136. T * operator->() { return _p; }
  137. T * GetPointer() const { return _p; }
  138. IUnknown ** GetIUPointer() { return (IUnknown **) &_p; }
  139. T ** GetPPointer() { return &_p; }
  140. T & GetReference() { return *_p; }
  141. void ** GetQIPointer() { return (void **) &_p; }
  142. T * Acquire() { T * p = _p; _p = 0; return p; }
  143. BOOL IsNull() { return ( 0 == _p ); }
  144. void Free() { T * p = Acquire(); if ( 0 != p ) p->Release(); }
  145. void Set( T * p ) { Free(); _p = p; }
  146. private:
  147. T * _p;
  148. };
  149. //+-------------------------------------------------------------------------
  150. //
  151. // Class: XBStr
  152. //
  153. // Synopsis: Class for managing ownership of BSTRings
  154. //
  155. //--------------------------------------------------------------------------
  156. class XBStr
  157. {
  158. public:
  159. XBStr( BSTR p = 0 ) : _p( p ) {}
  160. XBStr( XBStr & x ): _p( x.Acquire() ) {}
  161. ~XBStr() { Free(); }
  162. BOOL IsNull() const { return (0 == _p); }
  163. BSTR SetText( WCHAR const * pStr )
  164. {
  165. Win4Assert( 0 == _p );
  166. _p = SysAllocString( pStr );
  167. if ( 0 == _p )
  168. THROWMSG( CException( E_OUTOFMEMORY ), "can't allocate bstr" );
  169. return _p;
  170. }
  171. void Set( BSTR pOleStr ) { _p = pOleStr; }
  172. BSTR Acquire() { BSTR p = _p; _p = 0; return p; }
  173. BSTR GetPointer() const { return _p; }
  174. void Free() { SysFreeString(Acquire()); }
  175. private:
  176. BSTR _p;
  177. };
  178. inline ULONG CiPtrToUlong( ULONG_PTR p )
  179. {
  180. Win4Assert( p <= ULONG_MAX );
  181. return PtrToUlong( (PVOID)p );
  182. }
  183. #define CiPtrToUint( p ) CiPtrToUlong( p )
  184. //+---------------------------------------------------------------------------
  185. // Class: CDynArrayInPlace
  186. //
  187. // Purpose: Identical to CDynArray except array objects are stored in place,
  188. // instead of storing an array of pointers.
  189. //
  190. // History: 19-Aug-98 KLam Added this header
  191. //
  192. // Note: This reduces memory allocations, but does not work for objects
  193. // with destructors.
  194. //
  195. //+---------------------------------------------------------------------------
  196. template<class CItem> class CDynArrayInPlace
  197. {
  198. public:
  199. CDynArrayInPlace(unsigned size);
  200. CDynArrayInPlace();
  201. CDynArrayInPlace( CDynArrayInPlace const & src );
  202. CDynArrayInPlace( CDynArrayInPlace const & src, unsigned size );
  203. ~CDynArrayInPlace();
  204. void Add( const CItem &newItem, unsigned position);
  205. void Insert(const CItem& newItem, unsigned position);
  206. void Remove (unsigned position);
  207. unsigned Size () const {return _size;}
  208. CItem& Get (unsigned position) const;
  209. CItem * Get() { return _aItem; }
  210. void Clear();
  211. unsigned Count() const { return _count; }
  212. void SetSize(unsigned position)
  213. {
  214. if (position >= _size)
  215. _GrowToSize(position);
  216. };
  217. void Shrink()
  218. {
  219. // make size == count, to save memory
  220. if ( 0 == _count )
  221. {
  222. Clear();
  223. }
  224. else if ( _count != _size )
  225. {
  226. CItem * p = new CItem [_count];
  227. _size = _count;
  228. RtlCopyMemory( p, _aItem, _count * sizeof CItem );
  229. delete (BYTE *) _aItem;
  230. _aItem = p;
  231. }
  232. }
  233. CItem* Acquire ()
  234. {
  235. CItem *temp = _aItem;
  236. _aItem = 0;
  237. _count = 0;
  238. _size = 0;
  239. return temp;
  240. }
  241. void Duplicate( CDynArrayInPlace<CItem> & aFrom )
  242. {
  243. Clear();
  244. if ( 0 != aFrom.Count() )
  245. {
  246. _size = _count = aFrom.Count();
  247. _aItem = new CItem [_size];
  248. memcpy( _aItem, aFrom._aItem, _size * sizeof( CItem ) );
  249. }
  250. }
  251. CItem & operator[]( unsigned position )
  252. {
  253. if ( position >= _count )
  254. {
  255. if ( position >= _size )
  256. _GrowToSize( position );
  257. _count = position + 1;
  258. }
  259. return _aItem[position];
  260. }
  261. CItem & operator[]( unsigned position ) const
  262. {
  263. Win4Assert( position < _count );
  264. return _aItem[position];
  265. }
  266. CItem const * GetPointer() { return _aItem; }
  267. unsigned SizeOfInUse() const { return sizeof CItem * Count(); }
  268. protected:
  269. void _GrowToSize( unsigned position );
  270. CItem * _aItem;
  271. unsigned _size;
  272. unsigned _count;
  273. };
  274. #define DECL_DYNARRAY_INPLACE( CMyDynArrayInPlace, CItem )\
  275. typedef CDynArrayInPlace<CItem> CMyDynArrayInPlace;
  276. #define IMPL_DYNARRAY_INPLACE( CMyDynArrayInPlace, CItem )
  277. template<class CItem> CDynArrayInPlace<CItem>::CDynArrayInPlace(unsigned size)
  278. : _size(size), _count(0), _aItem( 0 )
  279. {
  280. if ( 0 != size )
  281. {
  282. _aItem = new CItem [_size];
  283. RtlZeroMemory( _aItem, _size * sizeof(CItem) );
  284. }
  285. }
  286. template<class CItem> CDynArrayInPlace<CItem>::CDynArrayInPlace()
  287. : _size(0), _count(0), _aItem(0)
  288. {
  289. }
  290. template<class CItem> CDynArrayInPlace<CItem>::CDynArrayInPlace( CDynArrayInPlace const & src )
  291. : _size( src._size ),
  292. _count( src._count )
  293. {
  294. _aItem = new CItem [_size];
  295. RtlCopyMemory( _aItem, src._aItem, _size * sizeof(_aItem[0]) );
  296. }
  297. template<class CItem> CDynArrayInPlace<CItem>::CDynArrayInPlace(
  298. CDynArrayInPlace const & src,
  299. unsigned size )
  300. : _size( size ),
  301. _count( src._count )
  302. {
  303. // this constructor is useful if the size should be larger than the
  304. // # of items in the source array
  305. Win4Assert( _size >= _count );
  306. _aItem = new CItem [_size];
  307. RtlCopyMemory( _aItem, src._aItem, _count * sizeof CItem );
  308. }
  309. template<class CItem> CDynArrayInPlace<CItem>::~CDynArrayInPlace()
  310. {
  311. delete [] _aItem;
  312. }
  313. template<class CItem> void CDynArrayInPlace<CItem>::Clear()
  314. {
  315. delete [] _aItem;
  316. _aItem = 0;
  317. _size = 0;
  318. _count = 0;
  319. }
  320. #define arraySize 16
  321. template<class CItem> void CDynArrayInPlace<CItem>::_GrowToSize( unsigned position )
  322. {
  323. Win4Assert( position >= _size );
  324. unsigned newsize = _size * 2;
  325. if ( newsize == 0 )
  326. newsize = arraySize;
  327. for( ; position >= newsize; newsize *= 2)
  328. continue;
  329. CItem *aNew = new CItem [newsize];
  330. if (_size > 0)
  331. {
  332. memcpy( aNew,
  333. _aItem,
  334. _size * sizeof( CItem ) );
  335. }
  336. RtlZeroMemory( aNew + _size,
  337. (newsize-_size) * sizeof(CItem) );
  338. delete (BYTE*) _aItem;
  339. _aItem = aNew;
  340. _size = newsize;
  341. }
  342. template<class CItem> void CDynArrayInPlace<CItem>::Add(const CItem &newItem,
  343. unsigned position)
  344. {
  345. if (position >= _count)
  346. {
  347. if (position >= _size)
  348. _GrowToSize( position );
  349. _count = position + 1;
  350. }
  351. _aItem[position] = newItem;
  352. }
  353. template<class CItem> CItem& CDynArrayInPlace<CItem>::Get(unsigned position) const
  354. {
  355. Win4Assert( position < _count );
  356. return _aItem[position];
  357. }
  358. template<class CItem> void CDynArrayInPlace<CItem>::Insert(const CItem& newItem, unsigned pos)
  359. {
  360. Win4Assert(pos <= _count);
  361. Win4Assert(_count <= _size);
  362. if (_count == _size)
  363. {
  364. unsigned newsize;
  365. if ( _size == 0 )
  366. newsize = arraySize;
  367. else
  368. newsize = _size * 2;
  369. CItem *aNew = new CItem [newsize];
  370. memcpy( aNew,
  371. _aItem,
  372. pos * sizeof( CItem ) );
  373. memcpy( aNew + pos + 1,
  374. _aItem + pos,
  375. (_count - pos) * sizeof(CItem));
  376. delete (BYTE *) _aItem;
  377. _aItem = aNew;
  378. _size = newsize;
  379. }
  380. else
  381. {
  382. memmove ( _aItem + pos + 1,
  383. _aItem + pos,
  384. (_count - pos) * sizeof(CItem));
  385. }
  386. _aItem[pos] = newItem;
  387. _count++;
  388. }
  389. template<class CItem> void CDynArrayInPlace<CItem>::Remove(unsigned pos)
  390. {
  391. Win4Assert(pos < _count);
  392. Win4Assert(_count <= _size);
  393. if (pos < _count - 1)
  394. {
  395. memmove ( _aItem + pos,
  396. _aItem + pos + 1,
  397. (_count - pos - 1) * sizeof(CItem));
  398. }
  399. RtlZeroMemory( _aItem + _count - 1, sizeof(CItem) );
  400. _count--;
  401. if (_count == 0)
  402. {
  403. delete (BYTE*) _aItem;
  404. _aItem = 0;
  405. _size = 0;
  406. }
  407. }
  408. template <class T, unsigned C = MAX_PATH> class XGrowable
  409. {
  410. public:
  411. XGrowable( unsigned cInit = C ) :
  412. _pT( _aT ),
  413. _cT( C )
  414. {
  415. Win4Assert( 0 != _cT );
  416. SetSize( cInit );
  417. }
  418. XGrowable( XGrowable<T,C> const & src ) :
  419. _pT( _aT ),
  420. _cT( C )
  421. {
  422. Win4Assert( 0 != _cT );
  423. *this = src;
  424. }
  425. ~XGrowable() { Free(); }
  426. XGrowable<T,C> & operator =( XGrowable<T,C> const & src )
  427. {
  428. Win4Assert( 0 != _cT );
  429. Copy ( src.Get(), src.Count() );
  430. return *this;
  431. }
  432. T * Copy ( T const * pItem, unsigned cItems, unsigned iStart = 0 )
  433. {
  434. // Copies cItems of pItem starting at position iStart
  435. Win4Assert ( 0 != pItem );
  436. SetSize ( cItems + iStart );
  437. RtlCopyMemory ( _pT + iStart, pItem, cItems * sizeof(T) );
  438. return _pT;
  439. }
  440. void Free()
  441. {
  442. if ( _pT != _aT )
  443. {
  444. delete [] _pT;
  445. _pT = _aT;
  446. _cT = C;
  447. Win4Assert( 0 != _cT );
  448. }
  449. }
  450. T & operator[](unsigned iElem)
  451. {
  452. Win4Assert( iElem < _cT );
  453. return _pT[iElem];
  454. }
  455. T const & operator[](unsigned iElem) const
  456. {
  457. Win4Assert( iElem < _cT );
  458. return _pT[iElem];
  459. }
  460. T * SetSize( unsigned c )
  461. {
  462. Win4Assert( 0 != c );
  463. if ( c > _cT )
  464. {
  465. unsigned cOld = _cT;
  466. Win4Assert( 0 != _cT );
  467. do
  468. {
  469. _cT *= 2;
  470. }
  471. while ( _cT < c );
  472. T *pTmp = new T [ _cT ];
  473. RtlCopyMemory( pTmp, _pT, cOld * sizeof T );
  474. if ( _pT != _aT )
  475. delete [] _pT;
  476. _pT = pTmp;
  477. }
  478. return _pT;
  479. }
  480. void SetSizeInBytes( unsigned cb )
  481. {
  482. // round up to the next element size
  483. SetSize( (cb + sizeof T - 1 ) / sizeof T );
  484. }
  485. T * Get() { return _pT; }
  486. T const * Get() const { return _pT; }
  487. unsigned Count() const { return _cT; }
  488. unsigned SizeOf() const { return sizeof T * _cT; }
  489. void SetBuf( const T* p, unsigned cc )
  490. {
  491. Win4Assert( p );
  492. SetSize( cc );
  493. RtlCopyMemory( _pT,
  494. p,
  495. cc * sizeof( T ) );
  496. }
  497. private:
  498. unsigned _cT;
  499. T * _pT;
  500. T _aT[ C ];
  501. };
  502. template <class T> class XArray
  503. {
  504. public:
  505. XArray() : _cElems( 0 ), _pElems( 0 )
  506. {
  507. }
  508. XArray( unsigned cElems ) : _cElems( cElems )
  509. {
  510. _pElems = new T[cElems];
  511. }
  512. XArray( XArray<T> & src )
  513. {
  514. // don't do this in initializers -- _pElems is declared first
  515. // so the old array is acquired before the count is copied
  516. _cElems = src._cElems;
  517. _pElems = src.Acquire();
  518. }
  519. ~XArray(void) { delete [] _pElems; }
  520. void Init( unsigned cElems )
  521. {
  522. Win4Assert( _pElems == 0 );
  523. _cElems = cElems;
  524. _pElems = new T[cElems];
  525. }
  526. void Init( XArray<T> const & src )
  527. {
  528. Win4Assert( _pElems == 0 );
  529. _cElems = src._cElems;
  530. _pElems = new T[_cElems];
  531. RtlCopyMemory( _pElems, src._pElems, _cElems * sizeof T );
  532. }
  533. void Set( unsigned cElems, T * pElems )
  534. {
  535. Win4Assert( _pElems == 0 );
  536. _cElems = cElems;
  537. _pElems = pElems;
  538. }
  539. T * Get() const { return _pElems; }
  540. T * GetPointer() const { return _pElems; }
  541. T * Acquire() { T * p = _pElems; _pElems = 0; _cElems = 0; return p; }
  542. BOOL IsNull() const { return ( 0 == _pElems); }
  543. T & operator[](ULONG_PTR iElem) { return _pElems[iElem]; }
  544. T const & operator[](ULONG_PTR iElem) const { return _pElems[iElem]; }
  545. unsigned Count() const { return _cElems; }
  546. unsigned SizeOf() const { return _cElems * sizeof T; }
  547. void Free() { delete [] Acquire(); }
  548. void ReSize( unsigned cElems )
  549. {
  550. T * pNew = new T[cElems];
  551. RtlCopyMemory( pNew, _pElems, sizeof T * __min( cElems, _cElems ) );
  552. delete [] _pElems;
  553. _pElems = pNew;
  554. _cElems = cElems;
  555. }
  556. private:
  557. T * _pElems;
  558. unsigned _cElems;
  559. };
  560. template<class T> class XCoMem
  561. {
  562. public:
  563. XCoMem(T* p = 0) : _p(p)
  564. {
  565. }
  566. XCoMem(unsigned Ts) : _p(0)
  567. {
  568. Init( Ts );
  569. }
  570. ~XCoMem() { if ( 0 != _p ) CoTaskMemFree( _p ); }
  571. BOOL IsNull() const { return (0 == _p); }
  572. T & operator[]( unsigned i ) { return _p[i]; }
  573. void Set ( T* p )
  574. {
  575. _p = p;
  576. }
  577. T * Acquire()
  578. {
  579. T * pTemp = _p;
  580. _p = 0;
  581. return pTemp;
  582. }
  583. T & GetReference() const
  584. {
  585. return *_p;
  586. }
  587. T * GetPointer()
  588. {
  589. return _p;
  590. }
  591. void Init( unsigned Ts )
  592. {
  593. _p = (T *) CoTaskMemAlloc( Ts * sizeof T );
  594. if ( 0 == _p )
  595. THROW ( CException( E_OUTOFMEMORY ) );
  596. }
  597. void InitNoThrow( unsigned Ts )
  598. {
  599. _p = (T *) CoTaskMemAlloc( Ts * sizeof T );
  600. }
  601. void Free( void )
  602. {
  603. if ( 0 != _p ) {
  604. CoTaskMemFree( _p );
  605. _p = 0;
  606. }
  607. }
  608. protected:
  609. T * _p;
  610. private:
  611. XCoMem (const XCoMem<T> & x);
  612. XCoMem<T> & operator=( const XCoMem<T> & x);
  613. };
  614. class XIHandle
  615. {
  616. public:
  617. XIHandle( HANDLE h = 0 ) : _h(h) {}
  618. ~XIHandle() { Free(); }
  619. HANDLE Get() { return _h; }
  620. BOOL IsNull() { return 0 == _h; }
  621. void Free()
  622. {
  623. if ( 0 != _h )
  624. {
  625. InternetCloseHandle( _h );
  626. _h = 0;
  627. }
  628. }
  629. private:
  630. HANDLE _h;
  631. };