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.

388 lines
10 KiB

  1. /*****************************************************************************
  2. *
  3. * common.c - Shared stuff that operates on all classes
  4. *
  5. * WARNING! The Common services work only if you pass in the
  6. * "primary object". This is vacuous if you don't use multiple
  7. * inheritance, since there's only one object in the first place.
  8. *
  9. * If you use multiple inheritance, make sure you pass the pointer
  10. * to the object that you use as IUnknown.
  11. *
  12. * The exceptions are the Forward_* functions, which work on
  13. * pointers to non-primary interfaces. They forward the call to the
  14. * primary interface.
  15. *
  16. *****************************************************************************/
  17. #include "map.h"
  18. /*****************************************************************************
  19. *
  20. * The sqiffle for this file.
  21. *
  22. *****************************************************************************/
  23. #define sqfl sqflCommon
  24. /*****************************************************************************
  25. *
  26. * USAGE FOR OLE OBJECTS
  27. *
  28. * Suppose you want to implement an object called CObj that supports
  29. * the interfaces Foo, Bar, and Baz. Suppose that you opt for
  30. * Foo as the primary interface.
  31. *
  32. * >> NAMING CONVENTION <<
  33. *
  34. * COM objects begin with the letter "C".
  35. *
  36. * (1) Declare the primary and secondary vtbls.
  37. *
  38. * Primary_Interface(CObj, IFoo);
  39. * Secondary_Interface(CObj, IBar);
  40. * Secondary_Interface(CObj, IBaz);
  41. *
  42. * (3) Declare the object itself.
  43. *
  44. * typedef struct CObj {
  45. * IFoo foo; // Primary must come first
  46. * IBar bar;
  47. * IBaz baz;
  48. * ... other fields ...
  49. * } CObj;
  50. *
  51. * (4) Implement the methods.
  52. *
  53. * You may *not* reimplement the AddRef and Release methods!
  54. * although you can subclass them.
  55. *
  56. * (5) To allocate an object of the appropriate type, write
  57. *
  58. * hres = Common_New(CObj, ppvOut);
  59. *
  60. * or, if the object is variable-sized,
  61. *
  62. * hres = Common_NewCb(cb, CObj, ppvOut);
  63. *
  64. * If the object supports multiple interfaces, you also need to
  65. * initialize all the secondary interfaces.
  66. *
  67. * CObj *pco = *ppvOut;
  68. * pco->bar = Secondary_Vtbl(CObj, IBar);
  69. * pco->baz = Secondary_Vtbl(CObj, IBaz);
  70. *
  71. * (6) Define the vtbls.
  72. *
  73. * #pragma BEGIN_CONST_DATA
  74. *
  75. * // The macros will declare QueryInterface, AddRef and Release
  76. * // so don't list them again
  77. *
  78. * Primary_Interface_Begin(CObj, IFoo)
  79. * CObj_FooMethod1,
  80. * CObj_FooMethod2,
  81. * CObj_FooMethod3,
  82. * CObj_FooMethod4,
  83. * Primary_Interface_End(Obj, IFoo)
  84. *
  85. * Secondary_Interface_Begin(CObj, IBar, bar)
  86. * CObj_Bar_BarMethod1,
  87. * CObj_Bar_BarMethod2,
  88. * Secondary_Interface_Begin(CObj, IBar, bar)
  89. *
  90. * Secondary_Interface_Begin(CObj, IBaz, baz)
  91. * CObj_Baz_BazMethod1,
  92. * CObj_Baz_BazMethod2,
  93. * CObj_Baz_BazMethod3,
  94. * Secondary_Interface_Begin(CObj, IBaz, baz)
  95. *
  96. *****************************************************************************/
  97. /*****************************************************************************
  98. *
  99. * USAGE FOR NON-OLE OBJECTS
  100. *
  101. * All objects are COM objects, even if they are never given out.
  102. * In the simplest case, it just derives from IUnknown.
  103. *
  104. * Suppose you want to implement an object called Obj which is
  105. * used only internally.
  106. *
  107. * (1) Declare the vtbl.
  108. *
  109. * Simple_Interface(Obj);
  110. *
  111. * (3) Declare the object itself.
  112. *
  113. * typedef struct Obj {
  114. * IUnknown unk;
  115. * ... other fields ...
  116. * } Obj;
  117. *
  118. * (4) Implement the methods.
  119. *
  120. * You may *not* override the QueryInterface, AddRef or
  121. * Release methods!
  122. *
  123. * (5) Allocating an object of the appropriate type is the same
  124. * as with OLE objects.
  125. *
  126. * (6) Define the "vtbl".
  127. *
  128. * #pragma BEGIN_CONST_DATA
  129. *
  130. * Simple_Interface_Begin(Obj)
  131. * Simple_Interface_End(Obj)
  132. *
  133. * That's right, nothing goes between the Begin and the End.
  134. *
  135. *****************************************************************************/
  136. /*****************************************************************************
  137. *
  138. * CommonInfo
  139. *
  140. * Information tracked for all common objects.
  141. *
  142. * A common object looks like this:
  143. *
  144. * riid
  145. * cRef FinalizeProc
  146. * pFoo -> lpVtbl -> QueryInterface
  147. * data Common_AddRef
  148. * data Common_Release
  149. * ... ...
  150. *
  151. * Essentially, we use the otherwise-unused space above the
  152. * pointers to record our bookkeeping information.
  153. *
  154. * cRef = object reference count
  155. * riid = object iid
  156. * FinalizeProc = Finalization procedure
  157. *
  158. * For secondary interfaces, it looks like this:
  159. *
  160. * offset to primary interface
  161. * pFoo -> lpVtbl -> Forward_QueryInterface
  162. * Forward_AddRef
  163. * Forward_Release
  164. * ...
  165. *
  166. *****************************************************************************/
  167. typedef struct CommonInfoN {
  168. D(ULONG cin_dwSig;)
  169. ULONG cin_cRef;
  170. } CommonInfoN, CIN, *PCIN;
  171. typedef struct CommonInfoP {
  172. PREVTBL *cip_prevtbl;
  173. } CommonInfoP, CIP, *PCIP;
  174. typedef struct CommonInfoP2 {
  175. PREVTBL2 *cip2_prevtbl2;
  176. } CommonInfoP2, CIP2, *PCIP2;
  177. typedef union CommonInfo {
  178. CIN cin[1];
  179. CIP cip[1];
  180. CIP2 cip2[1];
  181. } CommonInfo, CI, *PCI;
  182. #define ci_dwSig cin[-1].cin_dwSig
  183. #define ci_cRef cin[-1].cin_cRef
  184. #define ci_rgfp cip[0].cip_prevtbl
  185. #define ci_riid cip[0].cip_prevtbl[-1].riid
  186. #define ci_Finalize cip[0].cip_prevtbl[-1].FinalizeProc
  187. #define ci_lib cip2[0].cip2_prevtbl2[-1].lib
  188. #ifdef DEBUG
  189. #define ci_Start ci_dwSig
  190. #else
  191. #define ci_Start ci_cRef
  192. #endif
  193. #define ci_dwSignature 0x38162378 /* typed by my cat */
  194. /*****************************************************************************
  195. *
  196. * Common_QueryInterface (from IUnknown)
  197. *
  198. * Use this for objects that support only one interface.
  199. *
  200. *****************************************************************************/
  201. STDMETHODIMP
  202. Common_QueryInterface(PV pv, REFIID riid, PPV ppvObj)
  203. {
  204. PCI pci = pv;
  205. HRESULT hres;
  206. EnterProc(Common_QueryInterface, (_ "pG", pv, riid));
  207. AssertF(pci->ci_dwSig == ci_dwSignature);
  208. if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, pci->ci_riid)) {
  209. *ppvObj = pv;
  210. Common_AddRef(pv);
  211. hres = S_OK;
  212. } else {
  213. *ppvObj = NULL;
  214. hres = E_NOINTERFACE;
  215. }
  216. ExitOleProcPpv(ppvObj);
  217. return hres;
  218. }
  219. /*****************************************************************************
  220. *
  221. * Common_AddRef (from IUnknown)
  222. *
  223. * Increment the object refcount and the dll refcount.
  224. *
  225. *****************************************************************************/
  226. STDMETHODIMP_(ULONG)
  227. _Common_AddRef(PV pv)
  228. {
  229. PCI pci = pv;
  230. AssertF(pci->ci_dwSig == ci_dwSignature);
  231. InterlockedIncrement((LPLONG)&g_cRef);
  232. return ++pci->ci_cRef;
  233. }
  234. /*****************************************************************************
  235. *
  236. * Common_Finalize (from Common_Release)
  237. *
  238. * By default, no finalization is necessary.
  239. *
  240. *****************************************************************************/
  241. void EXTERNAL
  242. Common_Finalize(PV pv)
  243. {
  244. SquirtSqflPtszV(sqfl, TEXT("Common_Finalize(%08x)"), pv);
  245. }
  246. /*****************************************************************************
  247. *
  248. * Common_Release (from IUnknown)
  249. *
  250. * Decrement the object refcount and the dll refcount.
  251. *
  252. * If the object refcount drops to zero, finalize the object
  253. * and free it.
  254. *
  255. * The finalization handler lives ahead of the object vtbl.
  256. *
  257. *****************************************************************************/
  258. STDMETHODIMP_(ULONG)
  259. _Common_Release(PV pv)
  260. {
  261. PCI pci = pv;
  262. ULONG ulRc;
  263. AssertF(pci->ci_dwSig == ci_dwSignature);
  264. AssertF(0 != g_cRef);
  265. InterlockedDecrement((LPLONG)&g_cRef);
  266. ulRc = --pci->ci_cRef;
  267. if (ulRc == 0) {
  268. pci->ci_Finalize(pv);
  269. FreePv(&pci->ci_Start);
  270. }
  271. return ulRc;
  272. }
  273. /*****************************************************************************
  274. *
  275. * Forward_QueryInterface (from IUnknown)
  276. *
  277. * Move to the main object and try again.
  278. *
  279. *****************************************************************************/
  280. STDMETHODIMP
  281. Forward_QueryInterface(PV pv, REFIID riid, PPV ppvObj)
  282. {
  283. PCI pci = pv;
  284. LPUNKNOWN punk = pvAddPvCb(pv, 0 - pci->ci_lib);
  285. return Common_QueryInterface(punk, riid, ppvObj);
  286. }
  287. /*****************************************************************************
  288. *
  289. * Forward_AddRef (from IUnknown)
  290. *
  291. * Move to the main object and try again.
  292. *
  293. *****************************************************************************/
  294. STDMETHODIMP_(ULONG)
  295. Forward_AddRef(PV pv)
  296. {
  297. PCI pci = pv;
  298. LPUNKNOWN punk = pvAddPvCb(pv, 0 - pci->ci_lib);
  299. return Common_AddRef(punk);
  300. }
  301. /*****************************************************************************
  302. *
  303. * Forward_Release (from IUnknown)
  304. *
  305. * Move to the main object and try again.
  306. *
  307. *****************************************************************************/
  308. STDMETHODIMP_(ULONG)
  309. Forward_Release(PV pv)
  310. {
  311. PCI pci = pv;
  312. LPUNKNOWN punk = pvAddPvCb(pv, 0 - pci->ci_lib);
  313. return Common_Release(punk);
  314. }
  315. /*****************************************************************************
  316. *
  317. * _Common_New
  318. *
  319. * Create a new object with refcount 1 and the specific vtbl.
  320. * All other fields are zero-initialized.
  321. *
  322. *****************************************************************************/
  323. STDMETHODIMP
  324. _Common_New(ULONG cb, PV vtbl, PPV ppvObj)
  325. {
  326. HRESULT hres;
  327. EnterProc(Common_New, (_ "u", cb));
  328. SquirtSqflPtszV(sqfl, TEXT("Common_New()"));
  329. hres = AllocCbPpv(cb + sizeof(CIN), ppvObj);
  330. if (SUCCEEDED(hres)) {
  331. PCI pci = pvAddPvCb(*ppvObj, sizeof(CIN));
  332. D(pci->ci_dwSig = ci_dwSignature);
  333. pci->ci_rgfp = (PV)vtbl;
  334. *ppvObj = pci;
  335. Common_AddRef(pci);
  336. hres = S_OK;
  337. }
  338. ExitOleProcPpv(ppvObj);
  339. return hres;
  340. }
  341. /*****************************************************************************
  342. *
  343. * Invoke_Release
  344. *
  345. * Release the object (if there is one) and wipe out the back-pointer.
  346. * Note that we wipe out the value before calling the release, in order
  347. * to ameliorate various weird callback conditions.
  348. *
  349. *****************************************************************************/
  350. void EXTERNAL
  351. Invoke_Release(PV pv)
  352. {
  353. LPUNKNOWN punk = pvExchangePpvPv(pv, 0);
  354. if (punk) {
  355. punk->lpVtbl->Release(punk);
  356. }
  357. }