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.

392 lines
11 KiB

  1. #include "priv.h"
  2. #pragma hdrstop
  3. const GUID CLSID_CDocProp = {0x3EA48300L, 0x8CF6, 0x101B, 0x84, 0xFB, 0x66, 0x6C, 0xCB, 0x9B, 0xCD, 0x32};
  4. HRESULT CDocProp_CreateInstance(IUnknown *punkOuter, REFIID riid, void **);
  5. // Global variables
  6. UINT g_cRefDll = 0; // Reference count of this DLL.
  7. HANDLE g_hmodThisDll = NULL; // Handle to this DLL itself.
  8. STDAPI_(BOOL) DllEntry(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
  9. {
  10. switch(dwReason)
  11. {
  12. case DLL_PROCESS_ATTACH:
  13. g_hmodThisDll = hDll;
  14. DisableThreadLibraryCalls(hDll);
  15. SHFusionInitializeFromModule(hDll);
  16. break;
  17. case DLL_PROCESS_DETACH:
  18. SHFusionUninitialize();
  19. break;
  20. }
  21. return TRUE;
  22. }
  23. typedef struct {
  24. const IClassFactoryVtbl *cf;
  25. const CLSID *pclsid;
  26. HRESULT (*pfnCreate)(IUnknown *, REFIID, void **);
  27. } OBJ_ENTRY;
  28. extern const IClassFactoryVtbl c_CFVtbl; // forward
  29. //
  30. // we always do a linear search here so put your most often used things first
  31. //
  32. const OBJ_ENTRY c_clsmap[] = {
  33. { &c_CFVtbl, &CLSID_CDocProp, CDocProp_CreateInstance},
  34. // add more entries here
  35. { NULL, NULL, NULL}
  36. };
  37. // static class factory (no allocs!)
  38. STDMETHODIMP CClassFactory_QueryInterface(IClassFactory *pcf, REFIID riid, void **ppvObj)
  39. {
  40. if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown))
  41. {
  42. *ppvObj = (void *)pcf;
  43. }
  44. else
  45. {
  46. *ppvObj = NULL;
  47. return E_NOINTERFACE;
  48. }
  49. DllAddRef();
  50. return NOERROR;
  51. }
  52. STDMETHODIMP_(ULONG) CClassFactory_AddRef(IClassFactory *pcf)
  53. {
  54. DllAddRef();
  55. return 2;
  56. }
  57. STDMETHODIMP_(ULONG) CClassFactory_Release(IClassFactory *pcf)
  58. {
  59. DllRelease();
  60. return 1;
  61. }
  62. STDMETHODIMP CClassFactory_CreateInstance(IClassFactory *pcf, IUnknown *punkOuter, REFIID riid, void **ppvObject)
  63. {
  64. OBJ_ENTRY *this = IToClass(OBJ_ENTRY, cf, pcf);
  65. return this->pfnCreate(punkOuter, riid, ppvObject);
  66. }
  67. STDMETHODIMP CClassFactory_LockServer(IClassFactory *pcf, BOOL fLock)
  68. {
  69. if (fLock)
  70. DllAddRef();
  71. else
  72. DllRelease();
  73. return S_OK;
  74. }
  75. const IClassFactoryVtbl c_CFVtbl = {
  76. CClassFactory_QueryInterface, CClassFactory_AddRef, CClassFactory_Release,
  77. CClassFactory_CreateInstance,
  78. CClassFactory_LockServer
  79. };
  80. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
  81. {
  82. if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown))
  83. {
  84. const OBJ_ENTRY *pcls;
  85. for (pcls = c_clsmap; pcls->pclsid; pcls++)
  86. {
  87. if (IsEqualIID(rclsid, pcls->pclsid))
  88. {
  89. *ppv = (void *)&(pcls->cf);
  90. DllAddRef(); // Class Factory keeps dll in memory
  91. return NOERROR;
  92. }
  93. }
  94. }
  95. // failure
  96. *ppv = NULL;
  97. return CLASS_E_CLASSNOTAVAILABLE;;
  98. }
  99. STDAPI_(void) DllAddRef()
  100. {
  101. InterlockedIncrement(&g_cRefDll);
  102. }
  103. STDAPI_(void) DllRelease()
  104. {
  105. Assert( 0 != g_cRefDll );
  106. InterlockedDecrement(&g_cRefDll);
  107. }
  108. STDAPI DllCanUnloadNow(void)
  109. {
  110. return g_cRefDll == 0 ? S_OK : S_FALSE;
  111. }
  112. typedef struct
  113. {
  114. IShellExtInit _ei;
  115. IShellPropSheetExt _pse;
  116. int _cRef; // reference count
  117. IDataObject * _pdtobj; // data object
  118. TCHAR _szFile[MAX_PATH];
  119. } CDocProp;
  120. STDMETHODIMP_(UINT) CDocProp_PSE_AddRef(IShellPropSheetExt *pei)
  121. {
  122. CDocProp *this = IToClass(CDocProp, _pse, pei);
  123. return ++this->_cRef;
  124. }
  125. STDMETHODIMP_(UINT) CDocProp_PSE_Release(IShellPropSheetExt *pei)
  126. {
  127. CDocProp *this = IToClass(CDocProp, _pse, pei);
  128. if (--this->_cRef)
  129. return this->_cRef;
  130. if (this->_pdtobj)
  131. this->_pdtobj->lpVtbl->Release(this->_pdtobj);
  132. LocalFree((HLOCAL)this);
  133. DllRelease();
  134. return 0;
  135. }
  136. STDMETHODIMP CDocProp_PSE_QueryInterface(IShellPropSheetExt *pei, REFIID riid, void **ppvOut)
  137. {
  138. CDocProp *this = IToClass(CDocProp, _pse, pei);
  139. if (IsEqualIID(riid, &IID_IShellPropSheetExt) ||
  140. IsEqualIID(riid, &IID_IUnknown))
  141. {
  142. *ppvOut = (void *)pei;
  143. }
  144. else if (IsEqualIID(riid, &IID_IShellExtInit))
  145. {
  146. *ppvOut = (void *)&this->_ei;
  147. }
  148. else
  149. {
  150. *ppvOut = NULL;
  151. return E_NOINTERFACE;
  152. }
  153. this->_cRef++;
  154. return NOERROR;
  155. }
  156. #define NUM_PAGES 1
  157. UINT CALLBACK PSPCallback(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE psp)
  158. {
  159. switch (uMsg) {
  160. case PSPCB_RELEASE:
  161. if (psp && psp->lParam)
  162. {
  163. LPALLOBJS lpallobjs = (LPALLOBJS)psp->lParam;
  164. if (0 == --lpallobjs->uPageRef)
  165. {
  166. if (lpallobjs->fOleInit)
  167. CoUninitialize();
  168. // Free our structure so hope we don't get it again!
  169. FOfficeDestroyObjects(&lpallobjs->lpSIObj, &lpallobjs->lpDSIObj, &lpallobjs->lpUDObj);
  170. GlobalFree(lpallobjs);
  171. }
  172. }
  173. DllRelease();
  174. break;
  175. }
  176. return 1;
  177. }
  178. STDMETHODIMP CDocProp_PSE_AddPages(IShellPropSheetExt *ppse, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
  179. {
  180. CDocProp *this = IToClass(CDocProp, _pse, ppse);
  181. STGMEDIUM medium;
  182. FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  183. HRESULT hres = this->_pdtobj->lpVtbl->GetData(this->_pdtobj, &fmte, &medium);
  184. if (hres == S_OK && (DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, NULL, 0) == 1))
  185. {
  186. WCHAR szPath[MAX_PATH];
  187. DWORD grfStgMode;
  188. IStorage *pstg = NULL;
  189. DragQueryFile((HDROP)medium.hGlobal, 0, szPath, ARRAYSIZE(szPath));
  190. // Load the properties for this file
  191. grfStgMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
  192. if( GetFileAttributes( szPath ) & FILE_ATTRIBUTE_OFFLINE )
  193. {
  194. ReleaseStgMedium(&medium);
  195. return HRESULT_FROM_WIN32(ERROR_FILE_OFFLINE);
  196. }
  197. hres = StgOpenStorageEx(szPath, grfStgMode, STGFMT_STORAGE, 0, NULL, NULL, &IID_IStorage, (void**)&pstg);
  198. if (FAILED(hres))
  199. {
  200. // if we failed to open the file, try w/READ ONLY access
  201. grfStgMode = STGM_SHARE_EXCLUSIVE | STGM_READ;
  202. hres = StgOpenStorageEx(szPath, grfStgMode, STGFMT_STORAGE, 0, NULL, NULL, &IID_IStorage, (void**)&pstg);
  203. }
  204. if (SUCCEEDED(hres))
  205. {
  206. int i;
  207. // Allocate our main structure and make sure it is zero filled!
  208. LPALLOBJS lpallobjs = (LPALLOBJS)GlobalAlloc(GPTR, sizeof(ALLOBJS));
  209. if (lpallobjs)
  210. {
  211. PROPSHEETPAGE psp[NUM_PAGES];
  212. Assert( ARRAYSIZE(lpallobjs->szPath) == ARRAYSIZE(szPath) );
  213. StringCchCopy(lpallobjs->szPath, ARRAYSIZE(lpallobjs->szPath), szPath);
  214. // Initialize Office property code
  215. FOfficeCreateAndInitObjects( NULL, NULL, &lpallobjs->lpUDObj);
  216. lpallobjs->lpfnDwQueryLinkData = NULL;
  217. lpallobjs->dwMask = 0;
  218. // Fill in some stuff for the Office code
  219. lpallobjs->fFiledataInit = FALSE;
  220. // Initialize OLE
  221. lpallobjs->fOleInit = SUCCEEDED(CoInitialize(0));
  222. // Initialize the PropertySheets we're going to add
  223. FOfficeInitPropInfo(psp, PSP_USECALLBACK, (LPARAM)lpallobjs, PSPCallback);
  224. FLoadTextStrings();
  225. DwOfficeLoadProperties(pstg, NULL, NULL, lpallobjs->lpUDObj, 0, grfStgMode);
  226. // Try to add our new property pages
  227. for (i = 0; i < NUM_PAGES; i++)
  228. {
  229. HPROPSHEETPAGE hpage = CreatePropertySheetPage(&psp[i]);
  230. if (hpage)
  231. {
  232. DllAddRef(); // matched in PSPCB_RELEASE
  233. if (lpfnAddPage(hpage, lParam))
  234. {
  235. FAttach( lpallobjs, psp + i, hpage );
  236. lpallobjs->uPageRef++;
  237. }
  238. else
  239. DestroyPropertySheetPage(hpage);
  240. }
  241. }
  242. if (lpallobjs->uPageRef == 0)
  243. {
  244. if (lpallobjs->fOleInit)
  245. CoUninitialize();
  246. // Free our structures
  247. FOfficeDestroyObjects(&lpallobjs->lpSIObj, &lpallobjs->lpDSIObj, &lpallobjs->lpUDObj);
  248. GlobalFree(lpallobjs);
  249. }
  250. } // if (lpallobjs)
  251. } // StgOpenStorage ... if (SUCCEEDED(hres))
  252. if (NULL != pstg )
  253. {
  254. pstg->lpVtbl->Release(pstg);
  255. pstg = NULL;
  256. }
  257. ReleaseStgMedium(&medium);
  258. }
  259. return S_OK;
  260. }
  261. STDMETHODIMP CDocProp_SEI_Initialize(IShellExtInit *pei, LPCITEMIDLIST pidlFolder, LPDATAOBJECT pdtobj, HKEY hkeyProgID)
  262. {
  263. CDocProp *this = IToClass(CDocProp, _ei, pei);
  264. // Initialize can be called more than once.
  265. if (this->_pdtobj)
  266. this->_pdtobj->lpVtbl->Release(this->_pdtobj);
  267. // Duplicate the pdtobj pointer
  268. if (pdtobj)
  269. {
  270. this->_pdtobj = pdtobj;
  271. pdtobj->lpVtbl->AddRef(pdtobj);
  272. }
  273. return NOERROR;
  274. }
  275. STDMETHODIMP_(UINT) CDocProp_SEI_AddRef(IShellExtInit *pei)
  276. {
  277. CDocProp *this = IToClass(CDocProp, _ei, pei);
  278. return CDocProp_PSE_AddRef(&this->_pse);
  279. }
  280. STDMETHODIMP_(UINT) CDocProp_SEI_Release(IShellExtInit *pei)
  281. {
  282. CDocProp *this = IToClass(CDocProp, _ei, pei);
  283. return CDocProp_PSE_Release(&this->_pse);
  284. }
  285. STDMETHODIMP CDocProp_SEI_QueryInterface(IShellExtInit *pei, REFIID riid, void **ppv)
  286. {
  287. CDocProp *this = IToClass(CDocProp, _ei, pei);
  288. return CDocProp_PSE_QueryInterface(&this->_pse, riid, ppv);
  289. }
  290. extern IShellExtInitVtbl c_CDocProp_SXIVtbl;
  291. extern IShellPropSheetExtVtbl c_CDocProp_SPXVtbl;
  292. HRESULT CDocProp_CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppvOut)
  293. {
  294. CDocProp *pdp;
  295. if (punkOuter)
  296. return CLASS_E_NOAGGREGATION;
  297. pdp = LocalAlloc(LPTR, sizeof(CDocProp));
  298. if (pdp)
  299. {
  300. HRESULT hres;
  301. DllAddRef();
  302. pdp->_ei.lpVtbl = &c_CDocProp_SXIVtbl;
  303. pdp->_pse.lpVtbl = &c_CDocProp_SPXVtbl;
  304. pdp->_cRef = 1;
  305. hres = CDocProp_PSE_QueryInterface(&pdp->_pse, riid, ppvOut);
  306. CDocProp_PSE_Release(&pdp->_pse);
  307. return hres; // S_OK or E_NOINTERFACE
  308. }
  309. return E_OUTOFMEMORY;
  310. }
  311. IShellPropSheetExtVtbl c_CDocProp_SPXVtbl = {
  312. CDocProp_PSE_QueryInterface, CDocProp_PSE_AddRef, CDocProp_PSE_Release,
  313. CDocProp_PSE_AddPages
  314. };
  315. IShellExtInitVtbl c_CDocProp_SXIVtbl = {
  316. CDocProp_SEI_QueryInterface, CDocProp_SEI_AddRef, CDocProp_SEI_Release,
  317. CDocProp_SEI_Initialize
  318. };