Source code of Windows XP (NT5)
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.

417 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. InterlockedDecrement(&g_cRefDll);
  106. }
  107. STDAPI DllCanUnloadNow(void)
  108. {
  109. return g_cRefDll == 0 ? S_OK : S_FALSE;
  110. }
  111. typedef struct
  112. {
  113. IShellExtInit _ei;
  114. IShellPropSheetExt _pse;
  115. int _cRef; // reference count
  116. IDataObject * _pdtobj; // data object
  117. TCHAR _szFile[MAX_PATH];
  118. } CDocProp;
  119. STDMETHODIMP_(UINT) CDocProp_PSE_AddRef(IShellPropSheetExt *pei)
  120. {
  121. CDocProp *this = IToClass(CDocProp, _pse, pei);
  122. return ++this->_cRef;
  123. }
  124. STDMETHODIMP_(UINT) CDocProp_PSE_Release(IShellPropSheetExt *pei)
  125. {
  126. CDocProp *this = IToClass(CDocProp, _pse, pei);
  127. if (--this->_cRef)
  128. return this->_cRef;
  129. if (this->_pdtobj)
  130. this->_pdtobj->lpVtbl->Release(this->_pdtobj);
  131. LocalFree((HLOCAL)this);
  132. DllRelease();
  133. return 0;
  134. }
  135. STDMETHODIMP CDocProp_PSE_QueryInterface(IShellPropSheetExt *pei, REFIID riid, void **ppvOut)
  136. {
  137. CDocProp *this = IToClass(CDocProp, _pse, pei);
  138. if (IsEqualIID(riid, &IID_IShellPropSheetExt) ||
  139. IsEqualIID(riid, &IID_IUnknown))
  140. {
  141. *ppvOut = (void *)pei;
  142. }
  143. else if (IsEqualIID(riid, &IID_IShellExtInit))
  144. {
  145. *ppvOut = (void *)&this->_ei;
  146. }
  147. else
  148. {
  149. *ppvOut = NULL;
  150. return E_NOINTERFACE;
  151. }
  152. this->_cRef++;
  153. return NOERROR;
  154. }
  155. #ifdef _ABBREVIATED_DOCPROP_
  156. #define NUM_PAGES 1
  157. #else //_ABBREVIATED_DOCPROP_
  158. #define NUM_PAGES 4
  159. #endif //_ABBREVIATED_DOCPROP_
  160. UINT CALLBACK PSPCallback(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE psp)
  161. {
  162. switch (uMsg) {
  163. case PSPCB_RELEASE:
  164. if (psp && psp->lParam)
  165. {
  166. LPALLOBJS lpallobjs = (LPALLOBJS)psp->lParam;
  167. if (0 == --lpallobjs->uPageRef)
  168. {
  169. if (lpallobjs->fOleInit)
  170. CoUninitialize();
  171. // Free our structure so hope we don't get it again!
  172. FOfficeDestroyObjects(&lpallobjs->lpSIObj, &lpallobjs->lpDSIObj, &lpallobjs->lpUDObj);
  173. GlobalFree(lpallobjs);
  174. }
  175. }
  176. DllRelease();
  177. break;
  178. }
  179. return 1;
  180. }
  181. STDMETHODIMP CDocProp_PSE_AddPages(IShellPropSheetExt *ppse, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
  182. {
  183. CDocProp *this = IToClass(CDocProp, _pse, ppse);
  184. STGMEDIUM medium;
  185. FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  186. HRESULT hres = this->_pdtobj->lpVtbl->GetData(this->_pdtobj, &fmte, &medium);
  187. if (hres == S_OK && (DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, NULL, 0) == 1))
  188. {
  189. WCHAR wszPath[MAX_PATH];
  190. TCHAR szPath[MAX_PATH];
  191. DWORD grfStgMode;
  192. IStorage *pstg = NULL;
  193. DragQueryFile((HDROP)medium.hGlobal, 0, szPath, ARRAYSIZE(szPath));
  194. #ifdef UNICODE
  195. lstrcpyn(wszPath, szPath, MAX_PATH);
  196. #else
  197. MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, ARRAYSIZE(wszPath));
  198. #endif
  199. // Load the properties for this file
  200. grfStgMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
  201. #ifdef WINNT
  202. if( GetFileAttributes( szPath ) & FILE_ATTRIBUTE_OFFLINE )
  203. {
  204. ReleaseStgMedium(&medium);
  205. return HRESULT_FROM_WIN32(ERROR_FILE_OFFLINE);
  206. }
  207. hres = StgOpenStorageEx(wszPath, grfStgMode, STGFMT_STORAGE, 0, NULL, NULL, &IID_IStorage, (void**)&pstg);
  208. #else
  209. hres = StgOpenStorage( wszPath, NULL, grfStgMode, NULL, 0L, &pstg ) ;
  210. #endif
  211. if (FAILED(hres))
  212. {
  213. // if we failed to open the file, try w/READ ONLY access
  214. grfStgMode = STGM_SHARE_EXCLUSIVE | STGM_READ;
  215. #ifdef WINNT
  216. hres = StgOpenStorageEx(wszPath, grfStgMode, STGFMT_STORAGE, 0, NULL, NULL, &IID_IStorage, (void**)&pstg);
  217. #else
  218. hres = StgOpenStorage( wszPath, NULL, grfStgMode, NULL, 0L, &pstg ) ;
  219. #endif
  220. }
  221. if (SUCCEEDED(hres))
  222. {
  223. int i;
  224. // Allocate our main structure and make sure it is zero filled!
  225. LPALLOBJS lpallobjs = (LPALLOBJS)GlobalAlloc(GPTR, sizeof(ALLOBJS));
  226. if (lpallobjs)
  227. {
  228. PROPSHEETPAGE psp[NUM_PAGES];
  229. lstrcpyn(lpallobjs->szPath, szPath, ARRAYSIZE(lpallobjs->szPath));
  230. // Initialize Office property code
  231. #ifdef _ABBREVIATED_DOCPROP_
  232. FOfficeCreateAndInitObjects( NULL, NULL, &lpallobjs->lpUDObj);
  233. #else _ABBREVIATED_DOCPROP_
  234. FOfficeCreateAndInitObjects(&lpallobjs->lpSIObj, &lpallobjs->lpDSIObj, &lpallobjs->lpUDObj);
  235. #endif _ABBREVIATED_DOCPROP_
  236. lpallobjs->lpfnDwQueryLinkData = NULL;
  237. lpallobjs->dwMask = 0;
  238. // Fill in some stuff for the Office code
  239. lpallobjs->fFiledataInit = FALSE;
  240. // Initialize OLE
  241. lpallobjs->fOleInit = SUCCEEDED(CoInitialize(0));
  242. // Initialize the PropertySheets we're going to add
  243. FOfficeInitPropInfo(psp, PSP_USECALLBACK, (LPARAM)lpallobjs, PSPCallback);
  244. FLoadTextStrings();
  245. #ifdef _ABBREVIATED_DOCPROP_
  246. DwOfficeLoadProperties(pstg, NULL, NULL, lpallobjs->lpUDObj, 0, grfStgMode);
  247. #else _ABBREVIATED_DOCPROP_
  248. DwOfficeLoadProperties(pstg, lpallobjs->lpSIObj, lpallobjs->lpDSIObj, lpallobjs->lpUDObj, 0, grfStgMode);
  249. #endif _ABBREVIATED_DOCPROP_
  250. // Try to add our new property pages
  251. for (i = 0; i < NUM_PAGES; i++)
  252. {
  253. HPROPSHEETPAGE hpage = CreatePropertySheetPage(&psp[i]);
  254. if (hpage)
  255. {
  256. DllAddRef(); // matched in PSPCB_RELEASE
  257. if (lpfnAddPage(hpage, lParam))
  258. {
  259. FAttach( lpallobjs, psp + i, hpage );
  260. lpallobjs->uPageRef++;
  261. }
  262. else
  263. DestroyPropertySheetPage(hpage);
  264. }
  265. }
  266. if (lpallobjs->uPageRef == 0)
  267. {
  268. if (lpallobjs->fOleInit)
  269. CoUninitialize();
  270. // Free our structures
  271. FOfficeDestroyObjects(&lpallobjs->lpSIObj, &lpallobjs->lpDSIObj, &lpallobjs->lpUDObj);
  272. GlobalFree(lpallobjs);
  273. }
  274. } // if (lpallobjs)
  275. } // StgOpenStorage ... if (SUCCEEDED(hres))
  276. if (NULL != pstg )
  277. {
  278. pstg->lpVtbl->Release(pstg);
  279. pstg = NULL;
  280. }
  281. ReleaseStgMedium(&medium);
  282. }
  283. return S_OK;
  284. }
  285. STDMETHODIMP CDocProp_SEI_Initialize(IShellExtInit *pei, LPCITEMIDLIST pidlFolder, LPDATAOBJECT pdtobj, HKEY hkeyProgID)
  286. {
  287. CDocProp *this = IToClass(CDocProp, _ei, pei);
  288. // Initialize can be called more than once.
  289. if (this->_pdtobj)
  290. this->_pdtobj->lpVtbl->Release(this->_pdtobj);
  291. // Duplicate the pdtobj pointer
  292. if (pdtobj)
  293. {
  294. this->_pdtobj = pdtobj;
  295. pdtobj->lpVtbl->AddRef(pdtobj);
  296. }
  297. return NOERROR;
  298. }
  299. STDMETHODIMP_(UINT) CDocProp_SEI_AddRef(IShellExtInit *pei)
  300. {
  301. CDocProp *this = IToClass(CDocProp, _ei, pei);
  302. return CDocProp_PSE_AddRef(&this->_pse);
  303. }
  304. STDMETHODIMP_(UINT) CDocProp_SEI_Release(IShellExtInit *pei)
  305. {
  306. CDocProp *this = IToClass(CDocProp, _ei, pei);
  307. return CDocProp_PSE_Release(&this->_pse);
  308. }
  309. STDMETHODIMP CDocProp_SEI_QueryInterface(IShellExtInit *pei, REFIID riid, void **ppv)
  310. {
  311. CDocProp *this = IToClass(CDocProp, _ei, pei);
  312. return CDocProp_PSE_QueryInterface(&this->_pse, riid, ppv);
  313. }
  314. extern IShellExtInitVtbl c_CDocProp_SXIVtbl;
  315. extern IShellPropSheetExtVtbl c_CDocProp_SPXVtbl;
  316. HRESULT CDocProp_CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppvOut)
  317. {
  318. CDocProp *pdp;
  319. if (punkOuter)
  320. return CLASS_E_NOAGGREGATION;
  321. pdp = LocalAlloc(LPTR, sizeof(CDocProp));
  322. if (pdp)
  323. {
  324. HRESULT hres;
  325. DllAddRef();
  326. pdp->_ei.lpVtbl = &c_CDocProp_SXIVtbl;
  327. pdp->_pse.lpVtbl = &c_CDocProp_SPXVtbl;
  328. pdp->_cRef = 1;
  329. hres = CDocProp_PSE_QueryInterface(&pdp->_pse, riid, ppvOut);
  330. CDocProp_PSE_Release(&pdp->_pse);
  331. return hres; // S_OK or E_NOINTERFACE
  332. }
  333. return E_OUTOFMEMORY;
  334. }
  335. IShellPropSheetExtVtbl c_CDocProp_SPXVtbl = {
  336. CDocProp_PSE_QueryInterface, CDocProp_PSE_AddRef, CDocProp_PSE_Release,
  337. CDocProp_PSE_AddPages
  338. };
  339. IShellExtInitVtbl c_CDocProp_SXIVtbl = {
  340. CDocProp_SEI_QueryInterface, CDocProp_SEI_AddRef, CDocProp_SEI_Release,
  341. CDocProp_SEI_Initialize
  342. };