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.

285 lines
7.1 KiB

  1. /*
  2. * S A F E O B J . H
  3. *
  4. * Implementation of safe object classes
  5. *
  6. * Copyright 1986-1997 Microsoft Corporation, All Rights Reserved
  7. */
  8. #ifndef _SAFEOBJ_H_
  9. #define _SAFEOBJ_H_
  10. #include <except.h>
  11. // safe_xxx classes ----------------------------------------------------------
  12. //
  13. class safe_bstr
  14. {
  15. BSTR bstr;
  16. // NOT IMPLEMENTED
  17. //
  18. safe_bstr(const safe_bstr& b);
  19. safe_bstr& operator=(const safe_bstr& b);
  20. public:
  21. // CONSTRUCTORS
  22. //
  23. explicit safe_bstr(BSTR b=0) : bstr(b) {}
  24. ~safe_bstr()
  25. {
  26. SysFreeString (bstr);
  27. }
  28. // MANIPULATORS
  29. //
  30. safe_bstr& operator=(BSTR b)
  31. {
  32. Assert(!bstr); // Scream on overwrite of good data.
  33. bstr = b;
  34. return *this;
  35. }
  36. // ACCESSORS
  37. //
  38. BSTR* operator&() { Assert(NULL==bstr); return &bstr; }
  39. BSTR get() const { return bstr; }
  40. BSTR relinquish() { BSTR b = bstr; bstr = 0; return b; }
  41. BSTR* load() { Assert(NULL==bstr); return &bstr; }
  42. };
  43. class safe_propvariant
  44. {
  45. PROPVARIANT var;
  46. // NOT IMPLEMENTED
  47. //
  48. safe_propvariant(const safe_propvariant& b);
  49. safe_propvariant& operator=(const safe_propvariant& b);
  50. public:
  51. // CONSTRUCTORS
  52. //
  53. explicit safe_propvariant()
  54. {
  55. // Note! we cannot simply set vt to VT_EMPTY, as when this
  56. // structure go across process, it will cause marshalling
  57. // problem if not property initialized.
  58. //
  59. ZeroMemory (&var, sizeof(PROPVARIANT) );
  60. }
  61. ~safe_propvariant()
  62. {
  63. PropVariantClear (&var);
  64. }
  65. // MANIPULATORS
  66. //
  67. safe_propvariant& operator=(PROPVARIANT v)
  68. {
  69. Assert(var.vt == VT_EMPTY); // Scream on overwrite of good data.
  70. var = v;
  71. return *this;
  72. }
  73. // ACCESSORS
  74. //
  75. PROPVARIANT* operator&() { Assert(var.vt == VT_EMPTY); return &var; }
  76. // get() accessor
  77. // NOTE that I am returning a const reference here. The reference is to
  78. // avoid creating a copy of our member var on return. The const is
  79. // because this method is a const accessor method.
  80. const PROPVARIANT& get() const { return var; }
  81. // relinquish() accessor
  82. // NOTE that I am NOT returning a reference here. The return for this
  83. // method comes off the STACK (PROPVARIANT v), so a reference would point
  84. // to that stack space, and our caller would be accessing OLD STACK frames.
  85. PROPVARIANT relinquish() { PROPVARIANT v = var; var.vt = VT_EMPTY; return v; }
  86. PROPVARIANT* addressof() { return &var; }
  87. };
  88. class safe_variant
  89. {
  90. // IMPORTANT: Do not add any other members to this class
  91. // other than the VARIANT that is to be protected. You will
  92. // break code all over the place if you do. There are places
  93. // where an array of these things are treated as an array of
  94. // VARIANT structures.
  95. //
  96. VARIANT var;
  97. // NOT IMPLEMENTED
  98. //
  99. safe_variant(const safe_variant& b);
  100. safe_variant& operator=(const safe_variant& b);
  101. public:
  102. // CONSTRUCTORS
  103. //
  104. explicit safe_variant()
  105. {
  106. // Note! we cannot simply set vt to VT_EMPTY, as when this
  107. // structure go across process, it will cause marshalling
  108. // problem if not property initialized.
  109. //
  110. ZeroMemory (&var, sizeof(VARIANT) );
  111. }
  112. ~safe_variant()
  113. {
  114. VariantClear (&var);
  115. }
  116. // MANIPULATORS
  117. //
  118. safe_variant& operator=(VARIANT v)
  119. {
  120. Assert(var.vt == VT_EMPTY); // Scream on overwrite of good data.
  121. var = v;
  122. return *this;
  123. }
  124. // ACCESSORS
  125. //
  126. VARIANT* operator&() { Assert(var.vt == VT_EMPTY); return &var; }
  127. // get() accessor
  128. // NOTE that I am returning a const reference here. The reference is to
  129. // avoid creating a copy of our member var on return. The const is
  130. // because this method is a const accessor method.
  131. const VARIANT& get() const { return var; }
  132. // relinquish() accessor
  133. // NOTE that I am NOT returning a reference here. The return for this
  134. // method comes off the STACK (PROPVARIANT v), so a reference would point
  135. // to that stack space, and our caller would be accessing OLD STACK frames.
  136. VARIANT relinquish() { VARIANT v = var; var.vt = VT_EMPTY; return v; }
  137. };
  138. // Safe impersonation --------------------------------------------------------
  139. //
  140. class safe_impersonation
  141. {
  142. BOOL m_fImpersonated;
  143. // NOT IMPLEMENTED
  144. //
  145. safe_impersonation(const safe_impersonation& b);
  146. safe_impersonation& operator=(const safe_impersonation& b);
  147. public:
  148. // CONSTRUCTORS
  149. //
  150. explicit safe_impersonation(HANDLE h = 0) : m_fImpersonated(0)
  151. {
  152. if (h != 0)
  153. m_fImpersonated = ImpersonateLoggedOnUser (h);
  154. }
  155. ~safe_impersonation()
  156. {
  157. if (m_fImpersonated)
  158. RevertToSelf();
  159. }
  160. BOOL FImpersonated() const { return m_fImpersonated; }
  161. };
  162. // ------------------------------------------------------------------------
  163. //
  164. // class safe_revert
  165. //
  166. // Turns impersonation OFF for the duration of the object's lifespan.
  167. // Unconditionally reimpersonates on exit, based on the provided handle.
  168. //
  169. // NOTE: UNCONDITIONALLY reimpersonates on exit.
  170. // (Just wanted to make that clear.)
  171. //
  172. // WARNING: the safe_revert class should only be used in very selective
  173. // situations. It is not a "quick way to get around" impersonation. If
  174. // you do need to do something like this, please see Becky -- she will then
  175. // wack you up'side the head.
  176. //
  177. class safe_revert
  178. {
  179. HANDLE m_h;
  180. safe_revert( const safe_revert& );
  181. safe_revert& operator=( const safe_revert& );
  182. public:
  183. explicit safe_revert( HANDLE h ) : m_h(h)
  184. {
  185. RevertToSelf();
  186. }
  187. ~safe_revert()
  188. {
  189. if (!ImpersonateLoggedOnUser( m_h ))
  190. {
  191. // There's not much we can do in this dtor. throw
  192. //
  193. throw CLastErrorException();
  194. }
  195. }
  196. };
  197. // -------------------------------------------------------------------------
  198. //
  199. // class safe_revert_self
  200. //
  201. // This is class is essentially the same as safe_revert except it uses
  202. // the thread handle instead of an external handle
  203. //
  204. class safe_revert_self
  205. {
  206. // Handle to hold on to the thread token
  207. // that we will want to use when we go back
  208. // to impersonating.
  209. //
  210. HANDLE m_hThreadHandle;
  211. public:
  212. // constructor will revert to self if there is
  213. // a valid thread token it can get for the current thread
  214. //
  215. safe_revert_self() :
  216. m_hThreadHandle (INVALID_HANDLE_VALUE)
  217. {
  218. if (OpenThreadToken( GetCurrentThread(),
  219. TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
  220. TRUE, // fOpenAsSelf
  221. &m_hThreadHandle ))
  222. {
  223. if (!RevertToSelf())
  224. DebugTrace ("Failed to revert to self \r\n");
  225. }
  226. else
  227. DebugTrace ("Failed to open thread token, last error = %d\n",
  228. GetLastError());
  229. }
  230. // destructor will impersonate again if we did a RevertToSelf above.
  231. //
  232. ~safe_revert_self()
  233. {
  234. if (m_hThreadHandle != INVALID_HANDLE_VALUE)
  235. {
  236. if (!ImpersonateLoggedOnUser(m_hThreadHandle))
  237. {
  238. DebugTrace("Failed to get back to correct user \r\n");
  239. // There's not much we can do in this dtor. throw
  240. //
  241. CloseHandle (m_hThreadHandle);
  242. throw CLastErrorException();
  243. }
  244. }
  245. }
  246. };
  247. #endif // _SAFEOBJ_H_