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.

528 lines
16 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: ole2.cpp
  7. //
  8. // Contents: LibMain and initialization routines
  9. //
  10. // Classes:
  11. //
  12. // Functions: LibMain
  13. // OleInitialize
  14. // OleInitializeWOW
  15. // OleInitializeEx
  16. // OleUnitialize
  17. // OleBuildVersion - !WIN32
  18. //
  19. //
  20. // History: dd-mmm-yy Author Comment
  21. // 16-Feb-94 AlexT alias OleBuildVersion, remove OleGetMalloc
  22. // remove DisableThreadLibaryCalls
  23. // 11-Jan-94 alexgo added VDATEHEAP macros to every function
  24. // 10-Dec-93 alexgo added support for LEDebugOut
  25. // 06-Dec-93 ChrisWe remove declaration of ClipboardInitialize()
  26. // and ClipboardUninitialize(), which are declared in
  27. // clipbrd.h; include that instead
  28. // 15-Mar-94 KevinRo Added OleInitializeWOW();
  29. //
  30. //--------------------------------------------------------------------------
  31. #include <le2int.h>
  32. #include <clipbrd.h>
  33. #include <dragopt.h>
  34. #include <drag.h>
  35. #pragma SEG(ole)
  36. #include <olerem.h>
  37. #include <ole2ver.h>
  38. #include <thunkapi.hxx>
  39. #include <olesem.hxx>
  40. #include <verify.hxx>
  41. //
  42. // DECLARE_INFOLEVEL is a macro used with cairo-style debugging output.
  43. // it creates a global variable LEInfoLevel which contains bits flags
  44. // of the various debugging output that should be sent to the debugger.
  45. //
  46. // Note that info level may be set within the debugger once ole232.dll
  47. // has loaded.
  48. //
  49. // Currently LEInfoLevel defaults to DEB_WARN | DEB_ERROR
  50. //
  51. DECLARE_INFOLEVEL(LE);
  52. DECLARE_INFOLEVEL(Ref);
  53. DECLARE_INFOLEVEL(DD);
  54. DECLARE_INFOLEVEL(VDATE);
  55. NAME_SEG(Ole2Main)
  56. // these are globals
  57. HMODULE g_hmodOLE2 = NULL;
  58. HINSTANCE g_hinst = NULL;
  59. ULONG g_cOleProcessInits = 0;
  60. CLIPFORMAT g_cfObjectLink = NULL;
  61. CLIPFORMAT g_cfOwnerLink = NULL;
  62. CLIPFORMAT g_cfNative = NULL;
  63. CLIPFORMAT g_cfLink = NULL;
  64. CLIPFORMAT g_cfBinary = NULL;
  65. CLIPFORMAT g_cfFileName = NULL;
  66. CLIPFORMAT g_cfFileNameW = NULL;
  67. CLIPFORMAT g_cfNetworkName = NULL;
  68. CLIPFORMAT g_cfDataObject = NULL;
  69. CLIPFORMAT g_cfEmbeddedObject = NULL;
  70. CLIPFORMAT g_cfEmbedSource = NULL;
  71. CLIPFORMAT g_cfCustomLinkSource = NULL;
  72. CLIPFORMAT g_cfLinkSource = NULL;
  73. CLIPFORMAT g_cfLinkSrcDescriptor = NULL;
  74. CLIPFORMAT g_cfObjectDescriptor = NULL;
  75. CLIPFORMAT g_cfOleDraw = NULL;
  76. CLIPFORMAT g_cfPBrush = NULL;
  77. CLIPFORMAT g_cfMSDraw = NULL;
  78. CLIPFORMAT g_cfOlePrivateData = NULL;
  79. CLIPFORMAT g_cfScreenPicture = NULL;
  80. CLIPFORMAT g_cfOleClipboardPersistOnFlush= NULL;
  81. CLIPFORMAT g_cfMoreOlePrivateData = NULL;
  82. ATOM g_aDropTarget = NULL;
  83. ATOM g_aDropTargetMarshalHwnd = NULL;
  84. ASSERTDATA
  85. ASSERTOUTDATA
  86. // more globals
  87. extern UINT uOmPostWmCommand;
  88. extern UINT uOleMessage;
  89. extern COleStaticMutexSem g_mxsSingleThreadOle;
  90. // this dummy function is used to avoid a copy of the environment variables.
  91. // NOTE: the moniker and dde code still use the windows heap.
  92. extern "C" void _setenvp(void) {
  93. VDATEHEAP();
  94. }
  95. //+---------------------------------------------------------------------------
  96. //
  97. // Function: OleInitializeWOW
  98. // Synopsis: Entry point to initialize the 16-bit WOW thunk layer.
  99. //
  100. // Effects: This routine is called when OLE32 is loaded by a VDM.
  101. // It serves two functions: It lets OLE know that it is
  102. // running in a VDM, and it passes in the address to a set
  103. // of functions that are called by the thunk layer. This
  104. // allows normal 32-bit processes to avoid loading the WOW
  105. // DLL since the thunk layer references it.
  106. //
  107. // Arguments: [vlpmalloc] -- 16:16 pointer to the 16 bit allocator.
  108. // [lpthk] -- Flat pointer to the OleThunkWOW virtual
  109. // interface. This is NOT an OLE/IUnknown style
  110. // interface.
  111. // Requires:
  112. //
  113. // Returns:
  114. //
  115. // Signals:
  116. //
  117. // Modifies:
  118. //
  119. // Algorithm:
  120. //
  121. // History: 3-15-94 kevinro Created
  122. //
  123. // Notes:
  124. //
  125. //----------------------------------------------------------------------------
  126. STDAPI OleInitializeWOW( LPMALLOC vlpmalloc, LPOLETHUNKWOW lpthk )
  127. {
  128. OLETRACEIN((API_OleInitializeWOW, PARAMFMT("vlpmalloc= %x, lpthk= %p"),
  129. vlpmalloc, lpthk));
  130. SetOleThunkWowPtr(lpthk);
  131. HRESULT hr;
  132. hr = OleInitializeEx( NULL, COINIT_APARTMENTTHREADED );
  133. OLETRACEOUT((API_OleInitializeWOW, hr));
  134. return hr;
  135. }
  136. //+-------------------------------------------------------------------------
  137. //
  138. // Function: OleInitialize
  139. //
  140. // Synopsis: Initializes OLE in single threaded mode
  141. //
  142. // Effects:
  143. //
  144. // Arguments: [pMalloc] -- the memory allocator to use
  145. //
  146. // Requires:
  147. //
  148. // Returns: HRESULT
  149. //
  150. // Signals:
  151. //
  152. // Modifies:
  153. //
  154. // Algorithm:
  155. //
  156. // History: dd-mmm-yy Author Comment
  157. // 06-Dec-93 alexgo 32bit port
  158. //
  159. // Notes:
  160. //
  161. //--------------------------------------------------------------------------
  162. STDAPI OleInitialize(void * pMalloc)
  163. {
  164. OLETRACEIN((API_OleInitialize, PARAMFMT("pMalloc= %p"), pMalloc));
  165. VDATEHEAP();
  166. HRESULT hr;
  167. hr = OleInitializeEx( pMalloc, COINIT_APARTMENTTHREADED );
  168. OLETRACEOUT((API_OleInitialize, hr));
  169. return hr;
  170. }
  171. //+-------------------------------------------------------------------------
  172. //
  173. // Function: OleInitializeEx
  174. //
  175. // Synopsis: Initializes ole
  176. //
  177. // Effects:
  178. //
  179. // Arguments: [pMalloc] -- the task memory allocator to use
  180. // [flags] -- single or multi-threaded
  181. //
  182. // Requires:
  183. //
  184. // Returns: HRESULT
  185. //
  186. // Signals:
  187. //
  188. // Modifies:
  189. //
  190. // Algorithm:
  191. //
  192. // History: dd-mmm-yy Author Comment
  193. // 06-Dec-93 alexgo 32bit port
  194. // 24-May-94 AlexT Propagate CoInitializeEx's return code
  195. // 21-Jul-94 AlexT Allow nested OleInit/Uninit calls
  196. // 24-Aug-94 AlexT Return S_OK for first success and S_FALSE
  197. // thereafter (unless an allocator was
  198. // passed in)
  199. // 14-Aug-96 SatishT Changed the test for notification of Explorer
  200. // to only use the gfShellInitialized flag
  201. //
  202. // Notes: This routine may be called multiple times per apartment
  203. //
  204. //--------------------------------------------------------------------------
  205. #pragma SEG(OleInitialize)
  206. STDAPI OleInitializeEx(LPVOID pMalloc, ULONG ulFlags)
  207. {
  208. OLETRACEIN((API_OleInitialize, PARAMFMT("pMalloc= %p, ulFlags= %x"), pMalloc, ulFlags));
  209. VDATEHEAP();
  210. HRESULT hr;
  211. #if DBG==1
  212. HRESULT hrCoInit = S_OK;
  213. #endif
  214. DWORD cThreadOleInits;
  215. hr = CoInitializeEx(pMalloc, ulFlags);
  216. if (SUCCEEDED(hr))
  217. {
  218. Assert (g_hmodOLE2);
  219. #if DBG==1
  220. hrCoInit = hr;
  221. #endif
  222. COleTls tls;
  223. cThreadOleInits = ++ tls->cOleInits;
  224. do
  225. {
  226. // We only want to do the below initialization once per apartment
  227. if (cThreadOleInits > 1)
  228. {
  229. // We've already been this way before, just return
  230. Assert(SUCCEEDED(hr) && "Bad OleInitializeEx logic");
  231. break;
  232. }
  233. // single thread registration of DDE and clipboard formats.
  234. // Only do this once per process.
  235. COleStaticLock lck(g_mxsSingleThreadOle);
  236. if (++g_cOleProcessInits != 1)
  237. {
  238. // already done the per-process initialization
  239. break;
  240. }
  241. // initialized DDE only if any server objects have
  242. // already been registered.
  243. hr = CheckInitDde(FALSE);
  244. if (FAILED(hr))
  245. {
  246. Assert (!"DDELibMain failed()");
  247. break;
  248. }
  249. // Only need to do the initialization once so check the global
  250. // that gets assigned last.
  251. if( !g_aDropTarget )
  252. {
  253. // on NT3.51, clipboard formats are pre-registered for us by user32.
  254. // (This is done in file \ntuser\kernel\server.c.)
  255. // We know they are going to be sequential. This gives us a
  256. // good performance improvement (since the clipboard formats never
  257. // change.
  258. g_cfObjectLink = (CLIPFORMAT) RegisterClipboardFormat(OLESTR("ObjectLink"));
  259. g_cfOwnerLink = g_cfObjectLink + 1;
  260. Assert(g_cfOwnerLink == RegisterClipboardFormat(OLESTR("OwnerLink")));
  261. g_cfNative = g_cfObjectLink + 2;
  262. Assert(g_cfNative == RegisterClipboardFormat(OLESTR("Native")));
  263. g_cfBinary = g_cfObjectLink + 3;
  264. Assert(g_cfBinary == RegisterClipboardFormat(OLESTR("Binary")));
  265. g_cfFileName = g_cfObjectLink + 4;
  266. Assert(g_cfFileName == RegisterClipboardFormat(OLESTR("FileName")));
  267. g_cfFileNameW = g_cfObjectLink + 5;
  268. Assert(g_cfFileNameW ==
  269. RegisterClipboardFormat(OLESTR("FileNameW")));
  270. g_cfNetworkName = g_cfObjectLink + 6;
  271. Assert(g_cfNetworkName ==
  272. RegisterClipboardFormat(OLESTR("NetworkName")));
  273. g_cfDataObject = g_cfObjectLink + 7;
  274. Assert(g_cfDataObject ==
  275. RegisterClipboardFormat(OLESTR("DataObject")));
  276. g_cfEmbeddedObject = g_cfObjectLink + 8;
  277. Assert(g_cfEmbeddedObject ==
  278. RegisterClipboardFormat(OLESTR("Embedded Object")));
  279. g_cfEmbedSource = g_cfObjectLink + 9;
  280. Assert(g_cfEmbedSource ==
  281. RegisterClipboardFormat(OLESTR("Embed Source")));
  282. g_cfCustomLinkSource = g_cfObjectLink + 10;
  283. Assert(g_cfCustomLinkSource ==
  284. RegisterClipboardFormat(OLESTR("Custom Link Source")));
  285. g_cfLinkSource = g_cfObjectLink + 11;
  286. Assert(g_cfLinkSource ==
  287. RegisterClipboardFormat(OLESTR("Link Source")));
  288. g_cfObjectDescriptor = g_cfObjectLink + 12;
  289. Assert(g_cfObjectDescriptor ==
  290. RegisterClipboardFormat(OLESTR("Object Descriptor")));
  291. g_cfLinkSrcDescriptor = g_cfObjectLink + 13;
  292. Assert(g_cfLinkSrcDescriptor ==
  293. RegisterClipboardFormat(OLESTR("Link Source Descriptor")));
  294. g_cfOleDraw = g_cfObjectLink + 14;
  295. Assert(g_cfOleDraw == RegisterClipboardFormat(OLESTR("OleDraw")));
  296. g_cfPBrush = g_cfObjectLink + 15;
  297. Assert(g_cfPBrush == RegisterClipboardFormat(OLESTR("PBrush")));
  298. g_cfMSDraw = g_cfObjectLink + 16;
  299. Assert(g_cfMSDraw == RegisterClipboardFormat(OLESTR("MSDraw")));
  300. g_cfOlePrivateData = g_cfObjectLink + 17;
  301. Assert(g_cfOlePrivateData ==
  302. RegisterClipboardFormat(OLESTR("Ole Private Data")));
  303. g_cfScreenPicture = g_cfObjectLink + 18;
  304. Assert(g_cfScreenPicture ==
  305. RegisterClipboardFormat(OLESTR("Screen Picture")));
  306. g_cfOleClipboardPersistOnFlush = g_cfObjectLink + 19;
  307. /* turned off till NtUser group checks in for 335613
  308. Assert(g_cfOleClipboardPersistOnFlush ==
  309. RegisterClipboardFormat(OLESTR("OleClipboardPersistOnFlush")));
  310. */
  311. g_cfMoreOlePrivateData = g_cfObjectLink + 20;
  312. /* turned off till NtUser group checks in for 335613
  313. Assert(g_cfMoreOlePrivateData ==
  314. RegisterClipboardFormat(OLESTR("MoreOlePrivateData")));
  315. */
  316. g_aDropTarget = GlobalAddAtom(OLE_DROP_TARGET_PROP);
  317. AssertSz(g_aDropTarget, "Couldn't add drop target atom\n");
  318. g_aDropTargetMarshalHwnd = GlobalAddAtom(OLE_DROP_TARGET_MARSHALHWND);
  319. AssertSz(g_aDropTargetMarshalHwnd, "Couldn't add drop target hwnd atom\n");
  320. }
  321. // Used in Inplace editing
  322. uOmPostWmCommand = RegisterWindowMessage(OLESTR("OM_POST_WM_COMMAND"));
  323. uOleMessage = RegisterWindowMessage(OLESTR("OLE_MESSAHE"));
  324. } while (FALSE); // end of do
  325. if (FAILED(hr))
  326. {
  327. // clean up and break out
  328. CheckUninitDde(FALSE);
  329. tls->cOleInits--;
  330. CoUninitialize();
  331. }
  332. else
  333. {
  334. Assert(SUCCEEDED(hr) && "Bad OleInitializeEx logic");
  335. // If we're overriding the allocator, we return whatever
  336. // CoInitializeEx returned
  337. if (NULL != pMalloc)
  338. {
  339. Assert(hr == hrCoInit && "Bad OleInit logic");
  340. }
  341. else if (1 == cThreadOleInits)
  342. {
  343. // First successful call to OleInitializeEx - S_OK
  344. hr = S_OK;
  345. }
  346. else
  347. {
  348. // Second or greater succesful call to OleInitializeEx - S_FALSE
  349. hr = S_FALSE;
  350. }
  351. // Notify the COM verifier about the oleinit, for tracking purposes.
  352. CoVrfNotifyOleInit();
  353. }
  354. }
  355. OLETRACEOUT((API_OleInitialize, hr));
  356. return hr;
  357. }
  358. //+-------------------------------------------------------------------------
  359. //
  360. // Function: OleUnitialize
  361. //
  362. // Synopsis: Unitializes OLE, releasing any grabbed resources
  363. //
  364. // Effects:
  365. //
  366. // Arguments: void
  367. //
  368. // Requires:
  369. //
  370. // Returns: void
  371. //
  372. // Signals:
  373. //
  374. // Modifies:
  375. //
  376. // Algorithm:
  377. //
  378. // History: dd-mmm-yy Author Comment
  379. // 06-Dec-93 alexgo 32bit port
  380. // 21-Jul-94 AlexT Allow nested OleInit/Uninit calls
  381. //
  382. // Notes:
  383. //
  384. //--------------------------------------------------------------------------
  385. #pragma SEG(OleUninitialize)
  386. STDAPI_(void) OleUninitialize(void)
  387. {
  388. OLETRACEIN((API_OleUninitialize, NOPARAM));
  389. VDATEHEAP();
  390. COleTls tls(TRUE);
  391. if (tls.IsNULL() || 0 == tls->cOleInits)
  392. {
  393. CoVrfNotifyExtraOleUninit();
  394. LEDebugOut((DEB_ERROR,
  395. "(0 == thread inits) Unbalanced call to OleUninitialize\n"));
  396. goto errRtn;
  397. }
  398. if (0 == -- tls->cOleInits)
  399. {
  400. // This thread has called OleUninitialize for the last time. Check if
  401. // we need to do per process uninit now.
  402. ClipboardUninitialize(); // Must be first thing
  403. CheckUninitDde(FALSE);
  404. COleStaticLock lck(g_mxsSingleThreadOle);
  405. if (--g_cOleProcessInits == 0)
  406. {
  407. DragDropProcessUninitialize();
  408. // after this point, the uninit should not fail (because we don't
  409. // have code to redo the init).
  410. CheckUninitDde(TRUE);
  411. #if DBG==1
  412. // check for unreleased globals
  413. UtGlobalFlushTracking();
  414. #endif
  415. }
  416. }
  417. // Notify the COM verifier about the oleuninit, for tracking purposes.
  418. CoVrfNotifyOleUninit();
  419. // We call CoInitialize each time we call OleInitialize, so here we
  420. // balance that call
  421. CoUninitialize();
  422. errRtn:
  423. OLETRACEOUTEX((API_OleUninitialize, NORETURN));
  424. return;
  425. }