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.

407 lines
11 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 "fnd.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. #ifdef _WIN64
  168. #pragma pack(push,8)
  169. #endif // _WIN64
  170. typedef struct CommonInfoN {
  171. D(ULONG cin_dwSig;)
  172. ULONG cin_cRef;
  173. } CommonInfoN, CIN, *PCIN;
  174. typedef struct CommonInfoP {
  175. PREVTBL *cip_prevtbl;
  176. } CommonInfoP, CIP, *PCIP;
  177. typedef struct CommonInfoP2 {
  178. PREVTBL2 *cip2_prevtbl2;
  179. } CommonInfoP2, CIP2, *PCIP2;
  180. typedef union CommonInfo {
  181. CIN cin[1];
  182. CIP cip[1];
  183. CIP2 cip2[1];
  184. } CommonInfo, CI, *PCI;
  185. #define ci_dwSig cin[-1].cin_dwSig
  186. #define ci_cRef cin[-1].cin_cRef
  187. #define ci_rgfp cip[0].cip_prevtbl
  188. #define ci_riid cip[0].cip_prevtbl[-1].riid
  189. #define ci_Finalize cip[0].cip_prevtbl[-1].FinalizeProc
  190. #define ci_lib cip2[0].cip2_prevtbl2[-1].lib
  191. #define ci_Start ci_cRef
  192. #define ci_dwSignature 0x38162378 /* typed by my cat */
  193. /*****************************************************************************
  194. *
  195. * Common_QueryInterface (from IUnknown)
  196. *
  197. * Use this for objects that support only one interface.
  198. *
  199. *****************************************************************************/
  200. STDMETHODIMP
  201. Common_QueryInterface(PV pv, REFIID riid, PPV ppvObj)
  202. {
  203. PCI pci = pv;
  204. HRESULT hres;
  205. EnterProc(Common_QueryInterface, (_ "pG", pv, riid));
  206. AssertF(pci->ci_dwSig == ci_dwSignature);
  207. #ifdef _WIN64
  208. if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IShellExtInit) || IsEqualIID(riid, &IID_IContextMenu))
  209. #else
  210. if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, pci->ci_riid))
  211. #endif
  212. {
  213. *ppvObj = pv;
  214. Common_AddRef(pv);
  215. hres = NOERROR;
  216. }
  217. else
  218. {
  219. *ppvObj = NULL;
  220. hres = ResultFromScode(E_NOINTERFACE);
  221. }
  222. ExitOleProcPpv(ppvObj);
  223. return hres;
  224. }
  225. /*****************************************************************************
  226. *
  227. * Common_AddRef (from IUnknown)
  228. *
  229. * Increment the object refcount and the dll refcount.
  230. *
  231. *****************************************************************************/
  232. STDMETHODIMP_(ULONG)
  233. _Common_AddRef(PV pv)
  234. {
  235. PCI pci = pv;
  236. AssertF(pci->ci_dwSig == ci_dwSignature);
  237. InterlockedIncrement((LPLONG)&g_cRef);
  238. return ++pci->ci_cRef;
  239. }
  240. /*****************************************************************************
  241. *
  242. * Common_Finalize (from Common_Release)
  243. *
  244. * By default, no finalization is necessary.
  245. *
  246. *****************************************************************************/
  247. void EXTERNAL
  248. Common_Finalize(PV pv)
  249. {
  250. }
  251. /*****************************************************************************
  252. *
  253. * Common_Release (from IUnknown)
  254. *
  255. * Decrement the object refcount and the dll refcount.
  256. *
  257. * If the object refcount drops to zero, finalize the object
  258. * and free it.
  259. *
  260. * The finalization handler lives ahead of the object vtbl.
  261. *
  262. *****************************************************************************/
  263. STDMETHODIMP_(ULONG)
  264. _Common_Release(PV pv)
  265. {
  266. PCI pci = pv;
  267. ULONG ulRc;
  268. AssertF(pci->ci_dwSig == ci_dwSignature);
  269. InterlockedDecrement((LPLONG)&g_cRef);
  270. ulRc = --pci->ci_cRef;
  271. if (ulRc == 0)
  272. {
  273. #ifndef _WIN64
  274. pci->ci_Finalize(pv);
  275. #endif // WIN64
  276. FreePv(&pci->ci_Start);
  277. }
  278. return ulRc;
  279. }
  280. /*****************************************************************************
  281. *
  282. * Forward_QueryInterface (from IUnknown)
  283. *
  284. * Move to the main object and try again.
  285. *
  286. *****************************************************************************/
  287. STDMETHODIMP
  288. Forward_QueryInterface(PV pv, REFIID riid, PPV ppvObj)
  289. {
  290. PCI pci = pv;
  291. LPUNKNOWN punk = pvAddPvCb(pv, 0 - pci->ci_lib);
  292. return Common_QueryInterface(punk, riid, ppvObj);
  293. }
  294. /*****************************************************************************
  295. *
  296. * Forward_AddRef (from IUnknown)
  297. *
  298. * Move to the main object and try again.
  299. *
  300. *****************************************************************************/
  301. STDMETHODIMP_(ULONG)
  302. Forward_AddRef(PV pv)
  303. {
  304. PCI pci = pv;
  305. LPUNKNOWN punk = pvAddPvCb(pv, 0 - pci->ci_lib);
  306. return Common_AddRef(punk);
  307. }
  308. /*****************************************************************************
  309. *
  310. * Forward_Release (from IUnknown)
  311. *
  312. * Move to the main object and try again.
  313. *
  314. *****************************************************************************/
  315. STDMETHODIMP_(ULONG)
  316. Forward_Release(PV pv)
  317. {
  318. PCI pci = pv;
  319. LPUNKNOWN punk = pvAddPvCb(pv, 0 - pci->ci_lib);
  320. return Common_Release(punk);
  321. }
  322. /*****************************************************************************
  323. *
  324. * _Common_New
  325. *
  326. * Create a new object with refcount 1 and the specific vtbl.
  327. * All other fields are zero-initialized.
  328. *
  329. *****************************************************************************/
  330. STDMETHODIMP
  331. _Common_New(ULONG cb, PV vtbl, PPV ppvObj)
  332. {
  333. HRESULT hres;
  334. UNALIGNED PVOID * ppv;
  335. EnterProc(Common_New, (_ "u", cb));
  336. hres = AllocCbPpv(cb + sizeof(CIN), ppvObj);
  337. if (SUCCEEDED(hres))
  338. {
  339. PCI pci = pvAddPvCb(*ppvObj, sizeof(CIN));
  340. D(pci->ci_dwSig = ci_dwSignature);
  341. ppv = &(pci->cip[0].cip_prevtbl);
  342. *ppv = vtbl;
  343. *ppvObj = pci;
  344. Common_AddRef(pci);
  345. hres = NOERROR;
  346. }
  347. ExitOleProcPpv(ppvObj);
  348. return hres;
  349. }
  350. /*****************************************************************************
  351. *
  352. * Invoke_Release
  353. *
  354. * Release the object (if there is one) and wipe out the back-pointer.
  355. * Note that we wipe out the value before calling the release, in order
  356. * to ameliorate various weird callback conditions.
  357. *
  358. *****************************************************************************/
  359. void EXTERNAL
  360. Invoke_Release(PV pv)
  361. {
  362. LPUNKNOWN punk = pvExchangePpvPv(pv, 0);
  363. if (punk) {
  364. punk->lpVtbl->Release(punk);
  365. }
  366. }
  367. #ifdef _WIN64
  368. #pragma pack(pop)
  369. #endif //_WIN64