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.

389 lines
12 KiB

  1. /* File: D:\wacker\ext\pageext.c (Created: 01-Mar-1994)
  2. *
  3. * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 3 $
  7. * $Date: 3/25/02 3:52p $
  8. */
  9. #define _INC_OLE // WIN32, get ole2 from windows.h
  10. #define CONST_VTABLE
  11. #define INITGUID
  12. #include <windows.h>
  13. #pragma hdrstop
  14. //
  15. // Initialize GUIDs (should be done only and at-least once per DLL/EXE)
  16. //
  17. #pragma data_seg(".text")
  18. #include <objbase.h>
  19. #include <initguid.h>
  20. //#include <coguid.h>
  21. //#include <oleguid.h>
  22. #include <shlguid.h>
  23. #include <shlobj.h>
  24. #include "pageext.hh"
  25. #pragma data_seg()
  26. //
  27. // Function prototypes
  28. //
  29. HRESULT CALLBACK PageExt_CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR*);
  30. //
  31. // Global variables
  32. //
  33. UINT g_cRefThisDll = 0; // Reference count of this DLL.
  34. //---------------------------------------------------------------------------
  35. // DllCanUnloadNow
  36. //---------------------------------------------------------------------------
  37. STDAPI DllCanUnloadNow(void)
  38. {
  39. return ResultFromScode((g_cRefThisDll==0) ? S_OK : S_FALSE);
  40. }
  41. //---------------------------------------------------------------------------
  42. //
  43. // DllGetClassObject
  44. //
  45. // This is the entry of this DLL, which all the In-Proc server DLLs should
  46. // export. See the description of "DllGetClassObject" of OLE 2.0 reference
  47. // manual for detail.
  48. //
  49. //---------------------------------------------------------------------------
  50. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID FAR* ppvOut)
  51. {
  52. //
  53. // This DLL has only one class (CLSID_SamplePageExt). If a DLL supports
  54. // multiple classes, it should have either multiple if-statements or
  55. // efficient table lookup code.
  56. //
  57. // We need to put the icon handler in a separate DLL so when CAB32.EXE
  58. // calls it we don't implicitly link to TAPI and other system DLL's.
  59. // This is mostly for speed and to work around a bug in the Chicago
  60. // beta 1. Of course, we want to keep one source. So the main DLL
  61. // will link to the icon DLL to get icons, and the SHCreateDefClassObject(),
  62. // etc. Sorry for the complexity but its in the interest of system
  63. // performance. - mrw
  64. if (IsEqualIID(rclsid, &CLSID_SamplePageExt))
  65. {
  66. //
  67. // We are supposed return the class object for this class. Instead
  68. // of fully implementing it in this DLL, we just call a helper
  69. // function in the shell DLL which creates a default class factory
  70. // object for us. When its CreateInstance member is called, it
  71. // will call back our create instance function (PageExt_CreateInstance).
  72. //
  73. return SHCreateDefClassObject(
  74. riid,
  75. ppvOut,
  76. PageExt_CreateInstance, // callback function
  77. &g_cRefThisDll, // reference count of this DLL
  78. &IID_IShellExtInit // init interface
  79. );
  80. }
  81. return ResultFromScode(CLASS_E_CLASSNOTAVAILABLE);
  82. }
  83. //---------------------------------------------------------------------------
  84. //
  85. // CSamplePageExt class
  86. //
  87. // In C++:
  88. // class CSamplePageExt : protected IShellPropSheetExt, protected IShellExtInit
  89. // {
  90. // protected:
  91. // UINT _cRef;
  92. // LPDATAOBJECT _pdtobj;
  93. // HKEY _hkeyProgID;
  94. // public:
  95. // CSamplePageExt() _cRef(1), _pdtobj(NULL), _hkeyProgID(NULL) {};
  96. // ...
  97. // };
  98. //
  99. //---------------------------------------------------------------------------
  100. typedef struct _CSamplePageExt // smx
  101. {
  102. IShellPropSheetExt _spx; // 1st base class
  103. IShellExtInit _sxi; // 2nd base class
  104. UINT _cRef; // reference count
  105. LPDATAOBJECT _pdtobj; // data object
  106. HKEY _hkeyProgID; // reg. database key to ProgID
  107. } CSamplePageExt, * PSAMPLEPAGEEXT;
  108. //
  109. // Useful macros, which casts interface pointers to class pointers.
  110. //
  111. #define SMX_OFFSETOF(x) ((UINT_PTR)(&((PSAMPLEPAGEEXT)0)->x))
  112. #define PVOID2PSMX(pv,offset) ((PSAMPLEPAGEEXT)(((LPBYTE)pv)-offset))
  113. #define PSPX2PSMX(pspx) PVOID2PSMX(pspx, SMX_OFFSETOF(_spx))
  114. #define PSXI2PSMX(psxi) PVOID2PSMX(psxi, SMX_OFFSETOF(_sxi))
  115. //
  116. // Vtable prototype
  117. //
  118. extern IShellPropSheetExtVtbl c_SamplePageExt_SPXVtbl;
  119. extern IShellExtInitVtbl c_SamplePageExt_SXIVtbl;
  120. //---------------------------------------------------------------------------
  121. //
  122. // PageExt_CreateInstance
  123. //
  124. // This function is called back from within IClassFactory::CreateInstance()
  125. // of the default class factory object, which is created by Shell_CreateClassObject.
  126. //
  127. //---------------------------------------------------------------------------
  128. HRESULT CALLBACK PageExt_CreateInstance(LPUNKNOWN punkOuter,
  129. REFIID riid, LPVOID FAR* ppvOut)
  130. {
  131. HRESULT hres;
  132. PSAMPLEPAGEEXT psmx;
  133. //
  134. // Shell extentions typically does not support aggregation.
  135. //
  136. if (punkOuter)
  137. return ResultFromScode(CLASS_E_NOAGGREGATION);
  138. //
  139. // in C++:
  140. // psmx = new CSamplePageExt();
  141. //
  142. psmx = LocalAlloc(LPTR, sizeof(CSamplePageExt));
  143. if (!psmx)
  144. return ResultFromScode(E_OUTOFMEMORY);
  145. psmx->_spx.lpVtbl = &c_SamplePageExt_SPXVtbl;
  146. psmx->_sxi.lpVtbl = &c_SamplePageExt_SXIVtbl;
  147. psmx->_cRef = 1;
  148. psmx->_pdtobj = NULL;
  149. psmx->_hkeyProgID = NULL;
  150. g_cRefThisDll++;
  151. //
  152. // in C++:
  153. // hres = psmx->QueryInterface(riid, ppvOut);
  154. // psmx->Release();
  155. //
  156. // Note that the Release member will free the object, if QueryInterface
  157. // failed.
  158. //
  159. hres = c_SamplePageExt_SPXVtbl.QueryInterface(&psmx->_spx, riid, ppvOut);
  160. c_SamplePageExt_SPXVtbl.Release(&psmx->_spx);
  161. return hres; // S_OK or E_NOINTERFACE
  162. }
  163. //---------------------------------------------------------------------------
  164. // CSamplePageExt::Initialize (IShellExtInit override)
  165. //
  166. // The shell always calls this member function to initialize this object
  167. // immediately after creating it (by calling CoCreateInstance).
  168. //
  169. // Arguments:
  170. // pdtobj -- Specifies one or more objects for which the shell is about to
  171. // open the property sheet. Typically, they are selected objects
  172. // in the explorer. If they are file system objects, it supports
  173. // CF_FILELIST; if they are network resource objects, it supports
  174. // "Net Resource" clipboard format.
  175. // hkeyProgID -- Specifies the program ID of the primary object (typically
  176. // the object which has the focus in the explorer's content pane).
  177. //
  178. // Comments:
  179. // The extension should "duplicate" the parameters if it needs them later.
  180. // Call AddRef() member function for the pdtobj and RegOpenKeyEx() API for the
  181. // hkeyProgID.
  182. //---------------------------------------------------------------------------
  183. STDMETHODIMP PageExt_Initialize(LPSHELLEXTINIT psxi,
  184. LPCITEMIDLIST pidlFolder,
  185. LPDATAOBJECT pdtobj, HKEY hkeyProgID)
  186. {
  187. PSAMPLEPAGEEXT this = PSXI2PSMX(psxi);
  188. //
  189. // Initialize can be called more than once.
  190. //
  191. if (this->_pdtobj)
  192. {
  193. this->_pdtobj->lpVtbl->Release(this->_pdtobj);
  194. this->_pdtobj = NULL;
  195. }
  196. if (this->_hkeyProgID)
  197. {
  198. RegCloseKey(this->_hkeyProgID);
  199. this->_hkeyProgID = NULL;
  200. }
  201. //
  202. // Duplicate the pdtobj pointer
  203. //
  204. if (pdtobj)
  205. {
  206. this->_pdtobj = pdtobj;
  207. pdtobj->lpVtbl->AddRef(pdtobj);
  208. }
  209. //
  210. // Duplicate the handle (althogh we don't use it in this sample)
  211. //
  212. if (hkeyProgID)
  213. RegOpenKeyEx(hkeyProgID, 0, 0, KEY_READ, &this->_hkeyProgID);
  214. return NOERROR;
  215. }
  216. //---------------------------------------------------------------------------
  217. // CSamplePageExt::AddPages (IShellPropSheetExt override)
  218. //---------------------------------------------------------------------------
  219. STDMETHODIMP PageExt_AddPages(LPSHELLPROPSHEETEXT pspx,
  220. LPFNADDPROPSHEETPAGE lpfnAddPage,
  221. LPARAM lParam)
  222. {
  223. PSAMPLEPAGEEXT this = PSPX2PSMX(pspx);
  224. //
  225. // This is the place where this extension may add pages to the property
  226. // sheet the shell is about to create. In this example, we add the
  227. // "FSPage" if the selected objects are file system objects and add
  228. // the "NETPage" if the selected objects are file system objects.
  229. //
  230. // Typically, a shell extension is registered either file system object
  231. // class or network resource classe, and does not need to deal with two
  232. // different kinds of objects.
  233. //
  234. FSPage_AddPages(this->_pdtobj, lpfnAddPage, lParam);
  235. //NETPage_AddPages(this->_pdtobj, lpfnAddPage, lParam);
  236. return NOERROR;
  237. }
  238. //---------------------------------------------------------------------------
  239. // CSamplePageExt::AddRef (IShellPropSheetExt override)
  240. //---------------------------------------------------------------------------
  241. STDMETHODIMP_(UINT) PageExt_SPX_AddRef(LPSHELLPROPSHEETEXT pspx)
  242. {
  243. PSAMPLEPAGEEXT this = PSPX2PSMX(pspx);
  244. return ++this->_cRef;
  245. }
  246. //---------------------------------------------------------------------------
  247. // CSamplePageExt::AddRef (IShellExtInit override)
  248. //---------------------------------------------------------------------------
  249. STDMETHODIMP_(UINT) PageExt_SXI_AddRef(LPSHELLEXTINIT psxi)
  250. {
  251. PSAMPLEPAGEEXT this = PSXI2PSMX(psxi);
  252. return ++this->_cRef;
  253. }
  254. //---------------------------------------------------------------------------
  255. // CSamplePageExt::Release (IShellPropSheetExt override)
  256. //---------------------------------------------------------------------------
  257. STDMETHODIMP_(UINT) PageExt_SPX_Release(LPSHELLPROPSHEETEXT pspx)
  258. {
  259. PSAMPLEPAGEEXT this = PSPX2PSMX(pspx);
  260. if (--this->_cRef)
  261. return this->_cRef;
  262. if (this->_pdtobj)
  263. this->_pdtobj->lpVtbl->Release(this->_pdtobj);
  264. if (this->_hkeyProgID)
  265. RegCloseKey(this->_hkeyProgID);
  266. LocalFree((HLOCAL)this);
  267. g_cRefThisDll--;
  268. return 0;
  269. }
  270. //---------------------------------------------------------------------------
  271. // CSamplePageExt::Release (IShellExtInit thunk)
  272. //---------------------------------------------------------------------------
  273. STDMETHODIMP_(UINT) PageExt_SXI_Release(LPSHELLEXTINIT psxi)
  274. {
  275. PSAMPLEPAGEEXT this = PSXI2PSMX(psxi);
  276. return PageExt_SPX_Release(&this->_spx);
  277. }
  278. //---------------------------------------------------------------------------
  279. // CSamplePageExt::QueryInterface (IShellPropSheetExt override)
  280. //---------------------------------------------------------------------------
  281. STDMETHODIMP PageExt_SPX_QueryInterface(LPSHELLPROPSHEETEXT pspx, REFIID riid, LPVOID FAR* ppvOut)
  282. {
  283. PSAMPLEPAGEEXT this = PSPX2PSMX(pspx);
  284. if (IsEqualIID(riid, &IID_IShellPropSheetExt) ||
  285. IsEqualIID(riid, &IID_IUnknown))
  286. {
  287. (LPSHELLPROPSHEETEXT)*ppvOut=pspx;
  288. this->_cRef++;
  289. return NOERROR;
  290. }
  291. if (IsEqualIID(riid, &IID_IShellExtInit))
  292. {
  293. (LPSHELLEXTINIT)*ppvOut=&this->_sxi;
  294. this->_cRef++;
  295. return NOERROR;
  296. }
  297. *ppvOut=NULL;
  298. return ResultFromScode(E_NOINTERFACE);
  299. }
  300. //---------------------------------------------------------------------------
  301. // CSamplePageExt::QueryInterface (IShellExtInit thunk)
  302. //---------------------------------------------------------------------------
  303. STDMETHODIMP PageExt_SXI_QueryInterface(LPSHELLEXTINIT psxi, REFIID riid, LPVOID FAR* ppv)
  304. {
  305. PSAMPLEPAGEEXT this = PSXI2PSMX(psxi);
  306. return PageExt_SPX_QueryInterface(&this->_spx, riid, ppv);
  307. }
  308. //---------------------------------------------------------------------------
  309. // CSamplePageExt class : Vtables
  310. //
  311. // VTables should be placed in the read only section unless we need to alter
  312. // them at runtime.
  313. //---------------------------------------------------------------------------
  314. #pragma data_seg(".text")
  315. IShellPropSheetExtVtbl c_SamplePageExt_SPXVtbl =
  316. {
  317. PageExt_SPX_QueryInterface,
  318. PageExt_SPX_AddRef,
  319. PageExt_SPX_Release,
  320. PageExt_AddPages
  321. };
  322. IShellExtInitVtbl c_SamplePageExt_SXIVtbl =
  323. {
  324. PageExt_SXI_QueryInterface,
  325. PageExt_SXI_AddRef,
  326. PageExt_SXI_Release,
  327. PageExt_Initialize
  328. };
  329. #pragma data_seg()