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.

469 lines
12 KiB

  1. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2. //
  3. // dll.cpp
  4. //
  5. // Exported Dll functions.
  6. //
  7. // History:
  8. //
  9. // 3/16/97 edwardp Created.
  10. //
  11. ////////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Includes
  14. //
  15. #include "stdinc.h"
  16. #include "dll.h"
  17. #include "clsfact.h"
  18. #include "cdfidl.h"
  19. #include "xmlutil.h"
  20. #include "chanapi.h"
  21. #include "persist.h"
  22. #include "cdfview.h"
  23. #include "iconhand.h"
  24. #include "chanmgrp.h"
  25. #include "chanmgri.h"
  26. #include "chanmenu.h"
  27. #include "proppgs.h"
  28. #include <advpub.h> // Self registration helper.
  29. #include <olectl.h> // SELFREG_E_CLASS definition.
  30. #include <comcat.h> // Catagory registration.
  31. #define MLUI_INIT
  32. #include <mluisupp.h>
  33. BOOL g_bRunningOnNT = FALSE;
  34. void DLL_ForcePreloadDlls(DWORD dwFlags)
  35. {
  36. //
  37. // CoLoadLibrary is getting called here to add an extra reference count
  38. // to a COM dll so that it doesn't get unloaded by COM before we are through
  39. // with it. This problem occurs since our object gets created on
  40. // one thread and then passed along to another where we instantiate an
  41. // COM object. The secondary thread isn't guaranteed to have called
  42. // CoInitialize so we call it, then call CoCreateInstance then call
  43. // CoUnitialize to clean up. The side effect of all this is that dlls
  44. // are being unloaded while we still have references to them.
  45. //
  46. if ((dwFlags & PRELOAD_MSXML) && !g_msxmlInst)
  47. {
  48. g_msxmlInst = CoLoadLibrary(L"msxml.dll", FALSE); // Not much we can if
  49. // this fails
  50. }
  51. #ifndef UNIX
  52. /* Unix does not use webcheck */
  53. if ((dwFlags & PRELOAD_WEBCHECK) && !g_webcheckInst)
  54. {
  55. g_webcheckInst = CoLoadLibrary(L"webcheck.dll", FALSE);
  56. }
  57. #endif /* UNIX */
  58. }
  59. //
  60. // Exported Functions.
  61. //
  62. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  63. //
  64. // *** DllMain ***
  65. //
  66. // Dll entry point.
  67. //
  68. ////////////////////////////////////////////////////////////////////////////////
  69. EXTERN_C
  70. BOOL
  71. WINAPI DllMain(
  72. HANDLE hInst,
  73. DWORD dwReason,
  74. LPVOID pReserved
  75. )
  76. {
  77. if (DLL_PROCESS_ATTACH == dwReason)
  78. {
  79. //
  80. // This is a hack to fix an oleaut32.dll bug. If the oleaut32.dll is
  81. // loaded, then unloaded, then reloaded in the same process its heap
  82. // can become corrupt. This Loadlibrary will ensure that oleaut32
  83. // stays loaded once cdfview is ever loaded.
  84. //
  85. LoadLibrary(TEXT("oleaut32.dll"));
  86. DisableThreadLibraryCalls((HINSTANCE)hInst);
  87. g_hinst = (HINSTANCE)hInst;
  88. GetModuleFileName(g_hinst, g_szModuleName, ARRAYSIZE(g_szModuleName));
  89. MLLoadResources(g_hinst, TEXT("cdfvwlc.dll"));
  90. Cache_Initialize();
  91. //
  92. // Read the debug flags defined in ShellExt.ini. The filename, section
  93. // to read, and flag variables are defined in debug.cpp.
  94. //
  95. #ifdef DEBUG
  96. #ifndef UNIX
  97. CcshellGetDebugFlags();
  98. #endif /* UNIX */
  99. #endif
  100. g_bRunningOnNT = IsOS(OS_NT);
  101. }
  102. else if (DLL_PROCESS_DETACH == dwReason)
  103. {
  104. MLFreeResources(g_hinst);
  105. //
  106. // REVIEW: Clearing the cache on DLL unload.
  107. //
  108. Cache_Deinitialize();
  109. if (g_msxmlInst)
  110. CoFreeLibrary(g_msxmlInst);
  111. TraceMsg(TF_OBJECTS, "cdfview.dll unloaded!");
  112. }
  113. return TRUE;
  114. }
  115. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  116. //
  117. // *** DllCanUnloadNow ***
  118. //
  119. // Determines whether this DLL is in use. If not, the caller can safely
  120. // unload the DLL from memory.
  121. //
  122. ////////////////////////////////////////////////////////////////////////////////
  123. EXTERN_C
  124. STDAPI DllCanUnloadNow(
  125. void
  126. )
  127. {
  128. HRESULT hr;
  129. if (0 == g_cDllRef)
  130. {
  131. Cache_FreeAll();
  132. hr = S_OK;
  133. }
  134. else
  135. {
  136. hr = S_FALSE;
  137. }
  138. TraceMsg(TF_OBJECTS, "DllCanUnloadNow returned %s",
  139. hr == S_OK ? TEXT("TRUE") : TEXT("FALSE"));
  140. return g_cDllRef ? S_FALSE : S_OK;
  141. }
  142. //
  143. // Create functions used by the class factory.
  144. //
  145. #define DEFINE_CREATEINSTANCE(cls, iface) \
  146. HRESULT cls##_Create(IUnknown **ppIUnknown) \
  147. { \
  148. ASSERT(NULL != ppIUnknown); \
  149. *ppIUnknown = (iface *)new cls; \
  150. return (NULL != *ppIUnknown) ? S_OK : E_OUTOFMEMORY; \
  151. }
  152. DEFINE_CREATEINSTANCE(CCdfView, IShellFolder);
  153. DEFINE_CREATEINSTANCE(CChannelMgr, IChannelMgr);
  154. DEFINE_CREATEINSTANCE(CIconHandler, IExtractIcon);
  155. DEFINE_CREATEINSTANCE(CChannelMenu, IContextMenu);
  156. DEFINE_CREATEINSTANCE(CPropertyPages, IShellPropSheetExt);
  157. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  158. //
  159. // *** DllGetClassObject ***
  160. //
  161. // Retrieves the class factory object for the cdf viewer.
  162. //
  163. ////////////////////////////////////////////////////////////////////////////////
  164. EXTERN_C
  165. STDAPI DllGetClassObject(
  166. REFCLSID rclsid,
  167. REFIID riid,
  168. void** ppvObj
  169. )
  170. {
  171. //
  172. // Table used to pass the correct create function to the class factory.
  173. //
  174. static const struct _tagCLASSFACT {
  175. GUID const* pguid;
  176. CREATEPROC pfn;
  177. } aClassFact[] = { {&CLSID_CDFVIEW, CCdfView_Create},
  178. {&CLSID_CDFINI, CCdfView_Create},
  179. {&CLSID_ChannelMgr, CChannelMgr_Create},
  180. {&CLSID_CDFICONHANDLER, CIconHandler_Create},
  181. {&CLSID_CDFMENUHANDLER, CChannelMenu_Create},
  182. {&CLSID_CDFPROPPAGES, CPropertyPages_Create} };
  183. HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
  184. ASSERT(ppvObj);
  185. *ppvObj = NULL;
  186. for (int i = 0; i < ARRAYSIZE(aClassFact); i++)
  187. {
  188. if (rclsid == *aClassFact[i].pguid)
  189. {
  190. CCdfClassFactory *pCdfClassFactory =
  191. new CCdfClassFactory(aClassFact[i].pfn);
  192. if (pCdfClassFactory)
  193. {
  194. hr = pCdfClassFactory->QueryInterface(riid, ppvObj);
  195. //
  196. // The 'new' created a class factory with a ref count of one. The
  197. // above QueryInterface incremented the ref count by one or failed.
  198. // In either case the ClassFactory ref count should be decremented.
  199. //
  200. pCdfClassFactory->Release();
  201. }
  202. else
  203. {
  204. hr = E_OUTOFMEMORY;
  205. }
  206. break;
  207. }
  208. }
  209. ASSERT((SUCCEEDED(hr) && *ppvObj) || (FAILED(hr) && NULL == *ppvObj));
  210. return hr;
  211. }
  212. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  213. //
  214. // *** DllRegisterServer ***
  215. //
  216. // Self register the cdf viewer.
  217. //
  218. ////////////////////////////////////////////////////////////////////////////////
  219. EXTERN_C
  220. STDAPI DllRegisterServer(
  221. void
  222. )
  223. {
  224. HRESULT hr;
  225. //
  226. // Unregister previous versions of this control.
  227. //
  228. DllUnregisterServer();
  229. //
  230. // REVIEW this should be called at install time
  231. //
  232. DllInstall(TRUE, NULL);
  233. //
  234. // RegisterServerHelper uses advpack.dll to add registry entries using
  235. // entries found in the .rc.
  236. //
  237. //
  238. // REVIEW : Use #defines for "Reg" and "Unreg"
  239. //
  240. hr = RegisterServerHelper("Reg");
  241. if (SUCCEEDED(hr))
  242. {
  243. //
  244. // Register as a browseable shell extension. This will allow a user
  245. // to type the path of a cdf in the address bar and browse to the cdf
  246. // in place. This call adds an entry to the HKCR\CLSID\CLSID_CDFVIEW
  247. // \Implemented Catagories key.
  248. //
  249. ICatRegister *pICatRegister;
  250. HRESULT hr2 = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
  251. NULL, CLSCTX_INPROC_SERVER,
  252. IID_ICatRegister,
  253. (void**)&pICatRegister);
  254. if (SUCCEEDED(hr2))
  255. {
  256. ASSERT(pICatRegister);
  257. CATID acatid[1];
  258. acatid[0] = CATID_BrowsableShellExt;
  259. pICatRegister->RegisterClassImplCategories(CLSID_CDFVIEW, 1,
  260. acatid);
  261. pICatRegister->Release();
  262. }
  263. }
  264. return hr;
  265. }
  266. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  267. //
  268. // *** DllUnregisterServer ***
  269. //
  270. // Self unregister the cdf viewer.
  271. //
  272. ////////////////////////////////////////////////////////////////////////////////
  273. EXTERN_C
  274. STDAPI DllUnregisterServer(
  275. void
  276. )
  277. {
  278. //
  279. // Note: The catagories registration in DllRegisterServer simply places a
  280. // value in CLSID\CLSID_CDFVIEW. This unreg removes the whole key (see
  281. // "selfreg.inx"). So no special handeling of the removal of the catagory
  282. // is required.
  283. //
  284. return RegisterServerHelper("Unreg");
  285. }
  286. EXTERN_C
  287. STDAPI DllInstall(BOOL fInstall, LPCWSTR pszCmdLine)
  288. {
  289. if (fInstall)
  290. {
  291. //
  292. // IE5 no longer creates special channel folders. Channels go into the
  293. // favorites folder.
  294. //
  295. /*
  296. Channel_CreateChannelFolder(DOC_CHANNEL);
  297. Channel_CreateChannelFolder(DOC_SOFTWAREUPDATE);
  298. */
  299. }
  300. else
  301. {
  302. //
  303. // REVIEW delete channels folder on uninstall?
  304. //
  305. ;
  306. }
  307. return S_OK;
  308. }
  309. //
  310. // Internal Functions.
  311. //
  312. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  313. //
  314. // *** RegisterServerHelper ***
  315. //
  316. //
  317. // Description:
  318. // Helper function used to register and unregister the cdf viewer.
  319. //
  320. // Parameters:
  321. // [IN] szCmd - String passed to advpack.RegInstall. Values use: "Reg" or
  322. // "Unreg".
  323. //
  324. // Return:
  325. // SELFREG_E_CLASS if advpack.dll isn't accessed. Otherwise the reuslt
  326. // from advpack.RegInstall is returned.
  327. //
  328. // Comments:
  329. // This helper is called by DllRegisterServer and DllUnregisterServer.
  330. //
  331. // This function uses an exported function from advpack.dll to update the
  332. // registry. Advpack uses the REGINST resource item to populate the
  333. // registry.
  334. //
  335. ////////////////////////////////////////////////////////////////////////////////
  336. HRESULT
  337. RegisterServerHelper(
  338. LPSTR szCmd
  339. )
  340. {
  341. ASSERT(szCmd);
  342. HRESULT hr = SELFREG_E_CLASS;
  343. HINSTANCE hinstLib = LoadLibrary(TEXT("advpack.dll"));
  344. if (hinstLib)
  345. {
  346. REGINSTALL RegInstall = (REGINSTALL)GetProcAddress(hinstLib,
  347. achREGINSTALL);
  348. if (RegInstall)
  349. hr = RegInstall(g_hinst, szCmd, NULL);
  350. else
  351. TraceMsg(TF_ERROR, "DLLREG RegisterServerHelper() GetProcAddress Failed");
  352. FreeLibrary(hinstLib);
  353. }
  354. else
  355. TraceMsg(TF_ERROR, "DLLREG RegisterServerHelper() Failed to load Advpack.dll");
  356. return hr;
  357. }
  358. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  359. //
  360. // *** DllAddref ***
  361. //
  362. // Increment the Dll ref counts.
  363. //
  364. ////////////////////////////////////////////////////////////////////////////////
  365. void
  366. DllAddRef(
  367. void
  368. )
  369. {
  370. ASSERT (g_cDllRef < (ULONG)-1);
  371. InterlockedIncrement((PLONG)&g_cDllRef);
  372. TraceMsg(TF_OBJECTS, "%d Dll ref count", g_cDllRef);
  373. return;
  374. }
  375. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  376. //
  377. // *** DllRelease ***
  378. //
  379. // Decrements the Dll ref counts.
  380. //
  381. ////////////////////////////////////////////////////////////////////////////////
  382. void
  383. DllRelease(
  384. void
  385. )
  386. {
  387. ASSERT( 0 != g_cDllRef );
  388. LONG cRef = InterlockedDecrement((PLONG)&g_cDllRef);
  389. TraceMsg(TF_OBJECTS, "%d Dll ref count", cRef);
  390. return;
  391. }