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.

601 lines
19 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 <perfmnce.hxx>
  40. #include <olesem.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. #ifdef _CHICAGO_
  96. // Private Chicago Defines
  97. //
  98. // The Chicago Shell will dynamically load the OLE32.DLL to improve
  99. // bootup start time. When an application calls CoInitialize, post
  100. // a message to the shell to inform it to load OLE32.DLL if it hasn't
  101. // already. The Shell will never unload OLE32.DLL.
  102. //
  103. // We are using an undocumented Shell interface.
  104. //
  105. BOOL gfShellInitialized = FALSE;
  106. #define WM_SHELLNOTIFY 0x0034
  107. #define SHELLNOTIFY_OLELOADED 0x0002
  108. extern "C" HWND WINAPI GetShellWindow(void);
  109. #endif // _CHICAGO_
  110. //+---------------------------------------------------------------------------
  111. //
  112. // Function: OleInitializeWOW
  113. // Synopsis: Entry point to initialize the 16-bit WOW thunk layer.
  114. //
  115. // Effects: This routine is called when OLE32 is loaded by a VDM.
  116. // It serves two functions: It lets OLE know that it is
  117. // running in a VDM, and it passes in the address to a set
  118. // of functions that are called by the thunk layer. This
  119. // allows normal 32-bit processes to avoid loading the WOW
  120. // DLL since the thunk layer references it.
  121. //
  122. // Arguments: [vlpmalloc] -- 16:16 pointer to the 16 bit allocator.
  123. // [lpthk] -- Flat pointer to the OleThunkWOW virtual
  124. // interface. This is NOT an OLE/IUnknown style
  125. // interface.
  126. // Requires:
  127. //
  128. // Returns:
  129. //
  130. // Signals:
  131. //
  132. // Modifies:
  133. //
  134. // Algorithm:
  135. //
  136. // History: 3-15-94 kevinro Created
  137. //
  138. // Notes:
  139. //
  140. //----------------------------------------------------------------------------
  141. STDAPI OleInitializeWOW( LPMALLOC vlpmalloc, LPOLETHUNKWOW lpthk )
  142. {
  143. OLETRACEIN((API_OleInitializeWOW, PARAMFMT("vlpmalloc= %x, lpthk= %p"),
  144. vlpmalloc, lpthk));
  145. SetOleThunkWowPtr(lpthk);
  146. HRESULT hr;
  147. hr = OleInitializeEx( NULL, COINIT_APARTMENTTHREADED );
  148. OLETRACEOUT((API_OleInitializeWOW, hr));
  149. return hr;
  150. }
  151. //+-------------------------------------------------------------------------
  152. //
  153. // Function: OleInitialize
  154. //
  155. // Synopsis: Initializes OLE in single threaded mode
  156. //
  157. // Effects:
  158. //
  159. // Arguments: [pMalloc] -- the memory allocator to use
  160. //
  161. // Requires:
  162. //
  163. // Returns: HRESULT
  164. //
  165. // Signals:
  166. //
  167. // Modifies:
  168. //
  169. // Algorithm:
  170. //
  171. // History: dd-mmm-yy Author Comment
  172. // 06-Dec-93 alexgo 32bit port
  173. //
  174. // Notes:
  175. //
  176. //--------------------------------------------------------------------------
  177. STDAPI OleInitialize(void * pMalloc)
  178. {
  179. OLETRACEIN((API_OleInitialize, PARAMFMT("pMalloc= %p"), pMalloc));
  180. VDATEHEAP();
  181. HRESULT hr;
  182. hr = OleInitializeEx( pMalloc, COINIT_APARTMENTTHREADED );
  183. OLETRACEOUT((API_OleInitialize, hr));
  184. return hr;
  185. }
  186. //+-------------------------------------------------------------------------
  187. //
  188. // Function: OleInitializeEx
  189. //
  190. // Synopsis: Initializes ole
  191. //
  192. // Effects:
  193. //
  194. // Arguments: [pMalloc] -- the task memory allocator to use
  195. // [flags] -- single or multi-threaded
  196. //
  197. // Requires:
  198. //
  199. // Returns: HRESULT
  200. //
  201. // Signals:
  202. //
  203. // Modifies:
  204. //
  205. // Algorithm:
  206. //
  207. // History: dd-mmm-yy Author Comment
  208. // 06-Dec-93 alexgo 32bit port
  209. // 24-May-94 AlexT Propagate CoInitializeEx's return code
  210. // 21-Jul-94 AlexT Allow nested OleInit/Uninit calls
  211. // 24-Aug-94 AlexT Return S_OK for first success and S_FALSE
  212. // thereafter (unless an allocator was
  213. // passed in)
  214. // 14-Aug-96 SatishT Changed the test for notification of Explorer
  215. // to only use the gfShellInitialized flag
  216. //
  217. // Notes: This routine may be called multiple times per apartment
  218. //
  219. //--------------------------------------------------------------------------
  220. #pragma SEG(OleInitialize)
  221. STDAPI OleInitializeEx(LPVOID pMalloc, ULONG ulFlags)
  222. {
  223. OLETRACEIN((API_OleInitialize, PARAMFMT("pMalloc= %p, ulFlags= %x"), pMalloc, ulFlags));
  224. VDATEHEAP();
  225. HRESULT hr;
  226. #if DBG==1
  227. HRESULT hrCoInit = S_OK;
  228. #endif
  229. DWORD cThreadOleInits;
  230. StartPerfCounter(CoInitialize);
  231. hr = CoInitializeEx(pMalloc, ulFlags);
  232. EndPerfCounter(CoInitialize);
  233. if (SUCCEEDED(hr))
  234. {
  235. Assert (g_hmodOLE2);
  236. #if DBG==1
  237. hrCoInit = hr;
  238. #endif
  239. COleTls tls;
  240. cThreadOleInits = ++ tls->cOleInits;
  241. do
  242. {
  243. // We only want to do the below initialization once per apartment
  244. if (cThreadOleInits > 1)
  245. {
  246. // We've already been this way before, just return
  247. Assert(SUCCEEDED(hr) && "Bad OleInitializeEx logic");
  248. break;
  249. }
  250. // single thread registration of DDE and clipboard formats.
  251. // Only do this once per process.
  252. COleStaticLock lck(g_mxsSingleThreadOle);
  253. if (++g_cOleProcessInits != 1)
  254. {
  255. // already done the per-process initialization
  256. break;
  257. }
  258. // initialized DDE only if any server objects have
  259. // already been registered.
  260. hr = CheckInitDde(FALSE);
  261. if (FAILED(hr))
  262. {
  263. Assert (!"DDELibMain failed()");
  264. break;
  265. }
  266. // Only need to do the initialization once so check the global
  267. // that gets assigned last.
  268. if( !g_aDropTarget )
  269. {
  270. #ifndef _CHICAGO_
  271. // on NT3.51, clipboard formats are pre-registered for us by user32.
  272. // (This is done in file \ntuser\kernel\server.c.)
  273. // We know they are going to be sequential. This gives us a
  274. // good performance improvement (since the clipboard formats never
  275. // change.
  276. g_cfObjectLink = (CLIPFORMAT) RegisterClipboardFormat(OLESTR("ObjectLink"));
  277. g_cfOwnerLink = g_cfObjectLink + 1;
  278. Assert(g_cfOwnerLink == RegisterClipboardFormat(OLESTR("OwnerLink")));
  279. g_cfNative = g_cfObjectLink + 2;
  280. Assert(g_cfNative == RegisterClipboardFormat(OLESTR("Native")));
  281. g_cfBinary = g_cfObjectLink + 3;
  282. Assert(g_cfBinary == RegisterClipboardFormat(OLESTR("Binary")));
  283. g_cfFileName = g_cfObjectLink + 4;
  284. Assert(g_cfFileName == RegisterClipboardFormat(OLESTR("FileName")));
  285. g_cfFileNameW = g_cfObjectLink + 5;
  286. Assert(g_cfFileNameW ==
  287. RegisterClipboardFormat(OLESTR("FileNameW")));
  288. g_cfNetworkName = g_cfObjectLink + 6;
  289. Assert(g_cfNetworkName ==
  290. RegisterClipboardFormat(OLESTR("NetworkName")));
  291. g_cfDataObject = g_cfObjectLink + 7;
  292. Assert(g_cfDataObject ==
  293. RegisterClipboardFormat(OLESTR("DataObject")));
  294. g_cfEmbeddedObject = g_cfObjectLink + 8;
  295. Assert(g_cfEmbeddedObject ==
  296. RegisterClipboardFormat(OLESTR("Embedded Object")));
  297. g_cfEmbedSource = g_cfObjectLink + 9;
  298. Assert(g_cfEmbedSource ==
  299. RegisterClipboardFormat(OLESTR("Embed Source")));
  300. g_cfCustomLinkSource = g_cfObjectLink + 10;
  301. Assert(g_cfCustomLinkSource ==
  302. RegisterClipboardFormat(OLESTR("Custom Link Source")));
  303. g_cfLinkSource = g_cfObjectLink + 11;
  304. Assert(g_cfLinkSource ==
  305. RegisterClipboardFormat(OLESTR("Link Source")));
  306. g_cfObjectDescriptor = g_cfObjectLink + 12;
  307. Assert(g_cfObjectDescriptor ==
  308. RegisterClipboardFormat(OLESTR("Object Descriptor")));
  309. g_cfLinkSrcDescriptor = g_cfObjectLink + 13;
  310. Assert(g_cfLinkSrcDescriptor ==
  311. RegisterClipboardFormat(OLESTR("Link Source Descriptor")));
  312. g_cfOleDraw = g_cfObjectLink + 14;
  313. Assert(g_cfOleDraw == RegisterClipboardFormat(OLESTR("OleDraw")));
  314. g_cfPBrush = g_cfObjectLink + 15;
  315. Assert(g_cfPBrush == RegisterClipboardFormat(OLESTR("PBrush")));
  316. g_cfMSDraw = g_cfObjectLink + 16;
  317. Assert(g_cfMSDraw == RegisterClipboardFormat(OLESTR("MSDraw")));
  318. g_cfOlePrivateData = g_cfObjectLink + 17;
  319. Assert(g_cfOlePrivateData ==
  320. RegisterClipboardFormat(OLESTR("Ole Private Data")));
  321. g_cfScreenPicture = g_cfObjectLink + 18;
  322. Assert(g_cfScreenPicture ==
  323. RegisterClipboardFormat(OLESTR("Screen Picture")));
  324. g_cfOleClipboardPersistOnFlush = g_cfObjectLink + 19;
  325. /* turned off till NtUser group checks in for 335613
  326. Assert(g_cfOleClipboardPersistOnFlush ==
  327. RegisterClipboardFormat(OLESTR("OleClipboardPersistOnFlush")));
  328. */
  329. g_cfMoreOlePrivateData = g_cfObjectLink + 20;
  330. /* turned off till NtUser group checks in for 335613
  331. Assert(g_cfMoreOlePrivateData ==
  332. RegisterClipboardFormat(OLESTR("MoreOlePrivateData")));
  333. */
  334. g_aDropTarget = GlobalAddAtom(OLE_DROP_TARGET_PROP);
  335. AssertSz(g_aDropTarget, "Couldn't add drop target atom\n");
  336. g_aDropTargetMarshalHwnd = GlobalAddAtom(OLE_DROP_TARGET_MARSHALHWND);
  337. AssertSz(g_aDropTargetMarshalHwnd, "Couldn't add drop target hwnd atom\n");
  338. }
  339. // Used in Inplace editing
  340. uOmPostWmCommand = RegisterWindowMessage(OLESTR("OM_POST_WM_COMMAND"));
  341. uOleMessage = RegisterWindowMessage(OLESTR("OLE_MESSAHE"));
  342. #else // !_CHICAGO_
  343. g_cfObjectLink = SSRegisterClipboardFormatA("ObjectLink");
  344. g_cfOwnerLink = SSRegisterClipboardFormatA("OwnerLink");
  345. g_cfNative = SSRegisterClipboardFormatA("Native");
  346. g_cfBinary = SSRegisterClipboardFormatA("Binary");
  347. g_cfFileName = SSRegisterClipboardFormatA("FileName");
  348. g_cfFileNameW = SSRegisterClipboardFormatA("FileNameW");
  349. g_cfNetworkName = SSRegisterClipboardFormatA("NetworkName");
  350. g_cfDataObject = SSRegisterClipboardFormatA("DataObject");
  351. g_cfEmbeddedObject = SSRegisterClipboardFormatA("Embedded Object");
  352. g_cfEmbedSource = SSRegisterClipboardFormatA("Embed Source");
  353. g_cfCustomLinkSource = SSRegisterClipboardFormatA("Custom Link Source");
  354. g_cfLinkSource = SSRegisterClipboardFormatA("Link Source");
  355. g_cfObjectDescriptor = SSRegisterClipboardFormatA("Object Descriptor");
  356. g_cfLinkSrcDescriptor = SSRegisterClipboardFormatA("Link Source Descriptor");
  357. g_cfOleDraw = SSRegisterClipboardFormatA("OleDraw");
  358. g_cfPBrush = SSRegisterClipboardFormatA("PBrush");
  359. g_cfMSDraw = SSRegisterClipboardFormatA("MSDraw");
  360. g_cfOlePrivateData = SSRegisterClipboardFormatA("Ole Private Data");
  361. g_cfScreenPicture = SSRegisterClipboardFormatA("Screen Picture");
  362. g_aDropTarget = GlobalAddAtomA(OLE_DROP_TARGET_PROPA);
  363. AssertSz(g_aDropTarget, "Couldn't add drop target atom\n");
  364. g_aDropTargetMarshalHwnd = GlobalAddAtomA(OLE_DROP_TARGET_MARSHALHWNDA);
  365. AssertSz(g_aDropTargetMarshalHwnd, "Couldn't add drop target Marshal atom\n");
  366. }
  367. // Used in Inplace editing
  368. uOmPostWmCommand = RegisterWindowMessageA("OM_POST_WM_COMMAND");
  369. uOleMessage = RegisterWindowMessageA("OLE_MESSAHE");
  370. #endif // !_CHICAGO_
  371. } while (FALSE); // end of do
  372. if (FAILED(hr))
  373. {
  374. // clean up and break out
  375. CheckUninitDde(FALSE);
  376. tls->cOleInits--;
  377. CoUninitialize();
  378. }
  379. else
  380. {
  381. #if defined(_CHICAGO_)
  382. if (!gfShellInitialized)
  383. {
  384. // The Chicago Shell will dynamically load the OLE32.DLL to improve
  385. // bootup start time. When an application calls CoInitialize, post
  386. // a message to the shell to inform it to load OLE32.DLL if it hasn't
  387. // already. The Shell will never unload OLE32.DLL.
  388. //
  389. // We are using an undocumented Shell interface.
  390. //
  391. // We do this last so that we dont take a task switch while in
  392. // CoInitialize.
  393. #if DBG==1
  394. if (RegQueryValueEx(HKEY_CURRENT_USER,
  395. L"Software\\Microsoft\\OLE2\\NoShellNotify",
  396. NULL, // reserved
  397. NULL, // lpdwType
  398. NULL, // lpbData
  399. NULL) != ERROR_SUCCESS) // lpcbData
  400. #endif
  401. {
  402. HWND hwndShell = GetShellWindow();
  403. if (hwndShell)
  404. {
  405. PostMessage(hwndShell,WM_SHELLNOTIFY,
  406. SHELLNOTIFY_OLELOADED,0L);
  407. }
  408. }
  409. }
  410. gfShellInitialized = TRUE;
  411. #endif // _CHICAGO_
  412. Assert(SUCCEEDED(hr) && "Bad OleInitializeEx logic");
  413. // If we're overriding the allocator, we return whatever
  414. // CoInitializeEx returned
  415. if (NULL != pMalloc)
  416. {
  417. Assert(hr == hrCoInit && "Bad OleInit logic");
  418. }
  419. else if (1 == cThreadOleInits)
  420. {
  421. // First successful call to OleInitializeEx - S_OK
  422. hr = S_OK;
  423. }
  424. else
  425. {
  426. // Second or greater succesful call to OleInitializeEx - S_FALSE
  427. hr = S_FALSE;
  428. }
  429. }
  430. }
  431. OLETRACEOUT((API_OleInitialize, hr));
  432. return hr;
  433. }
  434. //+-------------------------------------------------------------------------
  435. //
  436. // Function: OleUnitialize
  437. //
  438. // Synopsis: Unitializes OLE, releasing any grabbed resources
  439. //
  440. // Effects:
  441. //
  442. // Arguments: void
  443. //
  444. // Requires:
  445. //
  446. // Returns: void
  447. //
  448. // Signals:
  449. //
  450. // Modifies:
  451. //
  452. // Algorithm:
  453. //
  454. // History: dd-mmm-yy Author Comment
  455. // 06-Dec-93 alexgo 32bit port
  456. // 21-Jul-94 AlexT Allow nested OleInit/Uninit calls
  457. //
  458. // Notes:
  459. //
  460. //--------------------------------------------------------------------------
  461. #pragma SEG(OleUninitialize)
  462. STDAPI_(void) OleUninitialize(void)
  463. {
  464. OLETRACEIN((API_OleUninitialize, NOPARAM));
  465. VDATEHEAP();
  466. COleTls tls(TRUE);
  467. if (tls.IsNULL() || 0 == tls->cOleInits)
  468. {
  469. LEDebugOut((DEB_ERROR,
  470. "(0 == thread inits) Unbalanced call to OleUninitialize\n"));
  471. goto errRtn;
  472. }
  473. if (0 == -- tls->cOleInits)
  474. {
  475. // This thread has called OleUninitialize for the last time. Check if
  476. // we need to do per process uninit now.
  477. ClipboardUninitialize(); // Must be first thing
  478. CheckUninitDde(FALSE);
  479. COleStaticLock lck(g_mxsSingleThreadOle);
  480. if (--g_cOleProcessInits == 0)
  481. {
  482. DragDropProcessUninitialize();
  483. // after this point, the uninit should not fail (because we don't
  484. // have code to redo the init).
  485. CheckUninitDde(TRUE);
  486. #if DBG==1
  487. // check for unreleased globals
  488. UtGlobalFlushTracking();
  489. #endif
  490. }
  491. }
  492. // We call CoInitialize each time we call OleInitialize, so here we
  493. // balance that call
  494. CoUninitialize();
  495. errRtn:
  496. OLETRACEOUTEX((API_OleUninitialize, NORETURN));
  497. return;
  498. }