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.

587 lines
14 KiB

  1. /************************************************************************
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name :
  4. smartptr.h
  5. Abstract :
  6. This file contains a class for implementing smart ref counted pointers.
  7. Author :
  8. Mike Zoran mzoran Feb 2002.
  9. Revision History :
  10. ***********************************************************************/
  11. #if !defined( _BITS_SMARTPTR_H )
  12. #include <strsafe.h>
  13. #define ARRAY_ELEMENTS( array ) ( sizeof( array ) / sizeof( *(array) ) )
  14. class ComError
  15. {
  16. public:
  17. HRESULT m_Hr;
  18. ComError( const ComError & Other ) :
  19. m_Hr( Other.m_Hr )
  20. {
  21. }
  22. ComError( HRESULT Hr ) :
  23. m_Hr( Hr )
  24. {
  25. }
  26. };
  27. inline void THROW_COMERROR( HRESULT Hr )
  28. {
  29. if ( FAILED( Hr ) )
  30. throw ComError( Hr );
  31. }
  32. inline void THROW_OUTOFMEMORY_IFNULL( void *p )
  33. {
  34. if (p == NULL)
  35. throw ComError( E_OUTOFMEMORY );
  36. }
  37. template<class T> class SmartRefPointer
  38. {
  39. private:
  40. T * m_Interface;
  41. void ReleaseIt()
  42. {
  43. if ( m_Interface )
  44. m_Interface->Release();
  45. m_Interface = NULL;
  46. }
  47. void RefIt()
  48. {
  49. if ( m_Interface )
  50. m_Interface->AddRef();
  51. }
  52. public:
  53. SmartRefPointer()
  54. {
  55. m_Interface = NULL;
  56. }
  57. SmartRefPointer( T * RawInterface )
  58. {
  59. m_Interface = RawInterface;
  60. RefIt();
  61. }
  62. SmartRefPointer( SmartRefPointer & Other )
  63. {
  64. m_Interface = Other.m_Interface;
  65. RefIt();
  66. }
  67. ~SmartRefPointer()
  68. {
  69. ReleaseIt();
  70. }
  71. T * Get() const
  72. {
  73. return m_Interface;
  74. }
  75. T * Release()
  76. {
  77. T * temp = m_Interface;
  78. m_Interface = NULL;
  79. return temp;
  80. }
  81. void Clear()
  82. {
  83. ReleaseIt();
  84. }
  85. T** GetRecvPointer()
  86. {
  87. ReleaseIt();
  88. return &m_Interface;
  89. }
  90. SmartRefPointer & operator=( SmartRefPointer & Other )
  91. {
  92. ReleaseIt();
  93. m_Interface = Other.m_Interface;
  94. RefIt();
  95. return *this;
  96. }
  97. T* operator->() const
  98. {
  99. return m_Interface;
  100. }
  101. operator const T*() const
  102. {
  103. return m_Interface;
  104. }
  105. const GUID & GetUUID() const
  106. {
  107. return __uuidof( T );
  108. }
  109. };
  110. typedef SmartRefPointer<IUnknown> SmartIUnknownPointer;
  111. typedef SmartRefPointer<IDispatch> SmartIDispatchPointer;
  112. class SmartVariant : public VARIANT
  113. {
  114. public:
  115. SmartVariant()
  116. {
  117. VariantInit( this );
  118. }
  119. ~SmartVariant()
  120. {
  121. VariantClear( this );
  122. }
  123. };
  124. class SafeArrayLocker
  125. {
  126. SAFEARRAY* m_Array;
  127. bool m_Locked;
  128. public:
  129. SafeArrayLocker(
  130. SAFEARRAY* Array,
  131. bool Locked = false ) :
  132. m_Array( Array ),
  133. m_Locked( Locked )
  134. {
  135. }
  136. ~SafeArrayLocker()
  137. {
  138. Unlock();
  139. }
  140. void Lock()
  141. {
  142. if ( m_Array && !m_Locked )
  143. {
  144. THROW_COMERROR( SafeArrayLock( m_Array ) );
  145. m_Locked = true;
  146. }
  147. }
  148. void Unlock()
  149. {
  150. if ( m_Array && m_Locked )
  151. {
  152. THROW_COMERROR( SafeArrayUnlock( m_Array ) );
  153. m_Locked = false;
  154. }
  155. }
  156. };
  157. template<class T>
  158. class MemoryArrayCleaner
  159. {
  160. T *& m_Pointer;
  161. public:
  162. MemoryArrayCleaner( T *& Pointer ) :
  163. m_Pointer( Pointer )
  164. {
  165. }
  166. ~MemoryArrayCleaner()
  167. {
  168. delete[] m_Pointer;
  169. m_Pointer = NULL;
  170. }
  171. };
  172. class CharStringRoutines
  173. {
  174. public:
  175. static int strcmp( const char *str1, const char *str2 )
  176. {
  177. return ::strcmp( str1, str2 );
  178. }
  179. static HRESULT StringCchCopy( char *str1, size_t cchDest, const char *str2 )
  180. {
  181. return ::StringCchCopyA( str1, cchDest, str2 );
  182. }
  183. static size_t strlen( const char *str )
  184. {
  185. return ::strlen( str );
  186. }
  187. static void* ConvertToInternal( SIZE_T Pad, const char *String, SIZE_T & Size )
  188. {
  189. Size = ::strlen( String );
  190. char *Ret = new char[ Pad + Size + 1 ];
  191. ::StringCchCopyA( Ret + Pad, Size + 1, String );
  192. return (void*)Ret;
  193. }
  194. static void* ConvertToInternal( SIZE_T Pad, const WCHAR *String, SIZE_T & Size )
  195. {
  196. int Alloc =
  197. WideCharToMultiByte(
  198. CP_THREAD_ACP, // code page
  199. 0, // performance and mapping flags
  200. String, // wide-character string
  201. -1, // number of chars in string
  202. NULL, // buffer for new string
  203. 0, // size of buffer
  204. NULL, // default for unmappable chars
  205. NULL // set when default char used
  206. );
  207. if ( !Alloc )
  208. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  209. char *Ret = new char[ Pad + Alloc ];
  210. int Actual =
  211. WideCharToMultiByte(
  212. CP_THREAD_ACP, // code page
  213. 0, // performance and mapping flags
  214. String, // wide-character string
  215. -1, // number of chars in string
  216. Ret + Pad, // buffer for new string
  217. Alloc, // size of buffer
  218. NULL, // default for unmappable chars
  219. NULL // set when default char used
  220. );
  221. if ( !Actual )
  222. {
  223. HRESULT Hr = HRESULT_FROM_WIN32( GetLastError() );
  224. delete[] Ret;
  225. throw ComError( Hr );
  226. }
  227. Size = Actual - 1;
  228. return Ret;
  229. }
  230. };
  231. class WCHARStringRoutines
  232. {
  233. public:
  234. static int strcmp( const WCHAR *str1, const WCHAR *str2 )
  235. {
  236. return ::wcscmp( str1, str2 );
  237. }
  238. static HRESULT StringCchCopy( WCHAR *str1, size_t cchDest, const WCHAR *str2 )
  239. {
  240. return ::StringCchCopyW( str1, cchDest, str2 );
  241. }
  242. static size_t strlen( const wchar_t *str )
  243. {
  244. return ::wcslen( str );
  245. }
  246. static void* ConvertToInternal( SIZE_T Pad, const WCHAR *String, SIZE_T & Size )
  247. {
  248. Size = ::wcslen( String );
  249. char *Ret = new char[ Pad + ( ( Size + 1 ) * sizeof(WCHAR) ) ];
  250. ::StringCchCopyW( (WCHAR*)(Ret + Pad), Size + 1, String );
  251. return (void*)Ret;
  252. }
  253. static void* ConvertToInternal( SIZE_T Pad, const char *String, SIZE_T & Size )
  254. {
  255. int Alloc =
  256. MultiByteToWideChar(
  257. CP_THREAD_ACP, // code page
  258. 0, // character-type options
  259. String, // string to map
  260. -1, // number of bytes in string
  261. NULL, // wide-character buffer
  262. 0 // size of buffer
  263. );
  264. if ( !Alloc )
  265. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  266. char *Ret = new char[ Pad + ( Alloc * sizeof(WCHAR) ) ];
  267. int Actual =
  268. MultiByteToWideChar(
  269. CP_THREAD_ACP, // code page
  270. 0, // character-type options
  271. String, // string to map
  272. -1, // number of bytes in string
  273. (WCHAR*)( Ret + Pad ), // wide-character buffer
  274. Alloc // size of buffer
  275. );
  276. if ( !Actual )
  277. {
  278. HRESULT Hr = HRESULT_FROM_WIN32( GetLastError() );
  279. delete[] Ret;
  280. throw ComError( Hr );
  281. }
  282. Size = Actual - 1;
  283. return Ret;
  284. }
  285. };
  286. template<class T, class CONV>
  287. class StringHandleTemplate : private CONV
  288. {
  289. struct StringData
  290. {
  291. SIZE_T m_Count;
  292. long m_Refs;
  293. };
  294. struct EmptyStringData
  295. {
  296. StringData m_StringData;
  297. T m_Data;
  298. };
  299. static EmptyStringData s_EmptyString;
  300. StringData *m_Value;
  301. void NewString( const char *String, bool ReplaceExisting = false );
  302. void NewString( const WCHAR *String, bool ReplaceExisting = false );
  303. StringData * RefIt() const
  304. {
  305. InterlockedIncrement( &m_Value->m_Refs );
  306. return m_Value;
  307. }
  308. void FreeIt()
  309. {
  310. if ( m_Value->m_Refs && InterlockedDecrement( &m_Value->m_Refs ) == 0 )
  311. {
  312. delete [] m_Value;
  313. m_Value = NULL;
  314. }
  315. }
  316. // Create String by concating 2 strings
  317. StringHandleTemplate( const StringData *LeftValue, const T *RightValue, SIZE_T RightSize );
  318. public:
  319. StringHandleTemplate()
  320. {
  321. NewString( (T*)NULL );
  322. }
  323. StringHandleTemplate( const char *String )
  324. {
  325. NewString( String );
  326. }
  327. StringHandleTemplate( const WCHAR *String )
  328. {
  329. NewString( String );
  330. }
  331. StringHandleTemplate( const StringHandleTemplate & Other ) :
  332. m_Value( Other.RefIt() )
  333. {
  334. }
  335. ~StringHandleTemplate()
  336. {
  337. FreeIt();
  338. }
  339. void SetStringSize()
  340. {
  341. m_Value->m_Count = strlen( (T*)(m_Value + 1) );
  342. }
  343. T *AllocBuffer( SIZE_T Size );
  344. StringHandleTemplate & operator=( const StringHandleTemplate & r )
  345. {
  346. FreeIt();
  347. m_Value = r.RefIt();
  348. return *this;
  349. }
  350. StringHandleTemplate & operator=( const T * r )
  351. {
  352. NewString( r, true );
  353. return *this;
  354. }
  355. SIZE_T Size() const
  356. {
  357. return m_Value->m_Count;
  358. }
  359. operator const T*() const
  360. {
  361. return (const T*)(m_Value + 1);
  362. }
  363. bool operator <( const StringHandleTemplate & r ) const
  364. {
  365. if ( m_Value == r.m_Value)
  366. return false;
  367. return (strcmp( (const T*)*this, (const T*)r ) < 0);
  368. }
  369. StringHandleTemplate operator+( const StringHandleTemplate & r ) const
  370. {
  371. return StringHandleTemplate( m_Value, (T*)(r.m_Value+1), r.m_Value->m_Count );
  372. }
  373. StringHandleTemplate operator+( const T * p ) const
  374. {
  375. static const T EmptyChar = '\0';
  376. if ( !p )
  377. return StringHandleTemplate( m_Value, &EmptyChar, 0 );
  378. return StringHandleTemplate( m_Value, p, strlen(p) );
  379. }
  380. StringHandleTemplate & operator+=( const StringHandleTemplate & r )
  381. {
  382. return (*this = (*this + r ) );
  383. }
  384. StringHandleTemplate & operator+=( const T * p )
  385. {
  386. return (*this = (*this + p ) );
  387. }
  388. };
  389. template<class T,class CONV>
  390. void
  391. StringHandleTemplate<T,CONV>::NewString( const char *String, bool ReplaceExisting )
  392. {
  393. if ( !String )
  394. {
  395. InterlockedIncrement( &s_EmptyString.m_StringData.m_Refs );
  396. StringData* Value = (StringData*)&s_EmptyString;
  397. if ( ReplaceExisting )
  398. FreeIt();
  399. m_Value = Value;
  400. return;
  401. }
  402. SIZE_T Size;
  403. StringData* Value = (StringData*)ConvertToInternal( sizeof(StringData), String, Size );
  404. Value->m_Count = Size;
  405. Value->m_Refs = 1;
  406. if ( ReplaceExisting )
  407. FreeIt();
  408. m_Value = Value;
  409. }
  410. template<class T,class CONV>
  411. void
  412. StringHandleTemplate<T,CONV>::NewString( const WCHAR *String, bool ReplaceExisting )
  413. {
  414. if ( !String )
  415. {
  416. InterlockedIncrement( &s_EmptyString.m_StringData.m_Refs );
  417. StringData* Value = (StringData*)&s_EmptyString;
  418. if ( ReplaceExisting )
  419. FreeIt();
  420. m_Value = Value;
  421. return;
  422. }
  423. SIZE_T Size;
  424. StringData* Value = (StringData*)ConvertToInternal( sizeof(StringData), String, Size );
  425. Value->m_Count = Size;
  426. Value->m_Refs = 1;
  427. if ( ReplaceExisting )
  428. FreeIt();
  429. m_Value = Value;
  430. }
  431. // Create String by concating 2 strings
  432. template<class T,class CONV>
  433. StringHandleTemplate<T,CONV>::StringHandleTemplate( const StringData *LeftValue, const T *RightValue, SIZE_T RightSize )
  434. {
  435. SIZE_T Size = LeftValue->m_Count + RightSize;
  436. m_Value = (StringData*)new char[ sizeof(StringData) + (Size*sizeof(T)) + sizeof(T) ];
  437. m_Value->m_Count = Size;
  438. m_Value->m_Refs = 1;
  439. T *DestData = (T*)( m_Value + 1 );
  440. memcpy( DestData, (T*)(LeftValue + 1), sizeof(T) * LeftValue->m_Count );
  441. memcpy( DestData + LeftValue->m_Count, RightValue, sizeof( T ) * RightSize );
  442. DestData[ Size ] = 0;
  443. }
  444. template<class T,class CONV>
  445. T *
  446. StringHandleTemplate<T,CONV>::AllocBuffer( SIZE_T Size )
  447. {
  448. StringData *Data = (StringData*)new T[sizeof(StringData)+(Size*sizeof(T))+sizeof(T)];
  449. Data->m_Count = 0;
  450. Data->m_Refs = 1;
  451. T *String = (T*)(Data + 1);
  452. String[0] = '\0';
  453. FreeIt(); // Free old string
  454. m_Value = Data;
  455. // Whoever fills in the string needs to call SetStringSize
  456. return String;
  457. }
  458. template<class T,class CONV>
  459. typename StringHandleTemplate<T,CONV>::EmptyStringData StringHandleTemplate<T,CONV>::s_EmptyString =
  460. {
  461. 0, 1, L'\0' // Initialize with 1 ref so it is never deleted
  462. };
  463. typedef StringHandleTemplate<char, CharStringRoutines> StringHandleA;
  464. typedef StringHandleTemplate<WCHAR, WCHARStringRoutines> StringHandleW;
  465. #define _BITS_SMARTPTR_H
  466. #endif //_BITS_SMARTPTR_H