|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: ole2.cpp
//
// Contents: LibMain and initialization routines
//
// Classes:
//
// Functions: LibMain
// OleInitialize
// OleInitializeWOW
// OleInitializeEx
// OleUnitialize
// OleBuildVersion - !WIN32
//
//
// History: dd-mmm-yy Author Comment
// 16-Feb-94 AlexT alias OleBuildVersion, remove OleGetMalloc
// remove DisableThreadLibaryCalls
// 11-Jan-94 alexgo added VDATEHEAP macros to every function
// 10-Dec-93 alexgo added support for LEDebugOut
// 06-Dec-93 ChrisWe remove declaration of ClipboardInitialize()
// and ClipboardUninitialize(), which are declared in
// clipbrd.h; include that instead
// 15-Mar-94 KevinRo Added OleInitializeWOW();
//
//--------------------------------------------------------------------------
#include <le2int.h>
#include <clipbrd.h>
#include <dragopt.h>
#include <drag.h>
#pragma SEG(ole)
#include <olerem.h>
#include <ole2ver.h>
#include <thunkapi.hxx>
#include <olesem.hxx>
#include <verify.hxx>
//
// DECLARE_INFOLEVEL is a macro used with cairo-style debugging output.
// it creates a global variable LEInfoLevel which contains bits flags
// of the various debugging output that should be sent to the debugger.
//
// Note that info level may be set within the debugger once ole232.dll
// has loaded.
//
// Currently LEInfoLevel defaults to DEB_WARN | DEB_ERROR
//
DECLARE_INFOLEVEL(LE); DECLARE_INFOLEVEL(Ref); DECLARE_INFOLEVEL(DD); DECLARE_INFOLEVEL(VDATE);
NAME_SEG(Ole2Main) // these are globals
HMODULE g_hmodOLE2 = NULL; HINSTANCE g_hinst = NULL; ULONG g_cOleProcessInits = 0;
CLIPFORMAT g_cfObjectLink = NULL; CLIPFORMAT g_cfOwnerLink = NULL; CLIPFORMAT g_cfNative = NULL; CLIPFORMAT g_cfLink = NULL; CLIPFORMAT g_cfBinary = NULL; CLIPFORMAT g_cfFileName = NULL; CLIPFORMAT g_cfFileNameW = NULL; CLIPFORMAT g_cfNetworkName = NULL; CLIPFORMAT g_cfDataObject = NULL; CLIPFORMAT g_cfEmbeddedObject = NULL; CLIPFORMAT g_cfEmbedSource = NULL; CLIPFORMAT g_cfCustomLinkSource = NULL; CLIPFORMAT g_cfLinkSource = NULL; CLIPFORMAT g_cfLinkSrcDescriptor = NULL; CLIPFORMAT g_cfObjectDescriptor = NULL; CLIPFORMAT g_cfOleDraw = NULL; CLIPFORMAT g_cfPBrush = NULL; CLIPFORMAT g_cfMSDraw = NULL; CLIPFORMAT g_cfOlePrivateData = NULL; CLIPFORMAT g_cfScreenPicture = NULL; CLIPFORMAT g_cfOleClipboardPersistOnFlush= NULL; CLIPFORMAT g_cfMoreOlePrivateData = NULL;
ATOM g_aDropTarget = NULL; ATOM g_aDropTargetMarshalHwnd = NULL;
ASSERTDATA
ASSERTOUTDATA
// more globals
extern UINT uOmPostWmCommand; extern UINT uOleMessage; extern COleStaticMutexSem g_mxsSingleThreadOle;
// this dummy function is used to avoid a copy of the environment variables.
// NOTE: the moniker and dde code still use the windows heap.
extern "C" void _setenvp(void) { VDATEHEAP(); }
//+---------------------------------------------------------------------------
//
// Function: OleInitializeWOW
// Synopsis: Entry point to initialize the 16-bit WOW thunk layer.
//
// Effects: This routine is called when OLE32 is loaded by a VDM.
// It serves two functions: It lets OLE know that it is
// running in a VDM, and it passes in the address to a set
// of functions that are called by the thunk layer. This
// allows normal 32-bit processes to avoid loading the WOW
// DLL since the thunk layer references it.
//
// Arguments: [vlpmalloc] -- 16:16 pointer to the 16 bit allocator.
// [lpthk] -- Flat pointer to the OleThunkWOW virtual
// interface. This is NOT an OLE/IUnknown style
// interface.
// Requires:
//
// Returns:
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: 3-15-94 kevinro Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI OleInitializeWOW( LPMALLOC vlpmalloc, LPOLETHUNKWOW lpthk ) { OLETRACEIN((API_OleInitializeWOW, PARAMFMT("vlpmalloc= %x, lpthk= %p"), vlpmalloc, lpthk));
SetOleThunkWowPtr(lpthk);
HRESULT hr;
hr = OleInitializeEx( NULL, COINIT_APARTMENTTHREADED );
OLETRACEOUT((API_OleInitializeWOW, hr));
return hr; }
//+-------------------------------------------------------------------------
//
// Function: OleInitialize
//
// Synopsis: Initializes OLE in single threaded mode
//
// Effects:
//
// Arguments: [pMalloc] -- the memory allocator to use
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 06-Dec-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDAPI OleInitialize(void * pMalloc) { OLETRACEIN((API_OleInitialize, PARAMFMT("pMalloc= %p"), pMalloc));
VDATEHEAP();
HRESULT hr;
hr = OleInitializeEx( pMalloc, COINIT_APARTMENTTHREADED );
OLETRACEOUT((API_OleInitialize, hr));
return hr; }
//+-------------------------------------------------------------------------
//
// Function: OleInitializeEx
//
// Synopsis: Initializes ole
//
// Effects:
//
// Arguments: [pMalloc] -- the task memory allocator to use
// [flags] -- single or multi-threaded
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 06-Dec-93 alexgo 32bit port
// 24-May-94 AlexT Propagate CoInitializeEx's return code
// 21-Jul-94 AlexT Allow nested OleInit/Uninit calls
// 24-Aug-94 AlexT Return S_OK for first success and S_FALSE
// thereafter (unless an allocator was
// passed in)
// 14-Aug-96 SatishT Changed the test for notification of Explorer
// to only use the gfShellInitialized flag
//
// Notes: This routine may be called multiple times per apartment
//
//--------------------------------------------------------------------------
#pragma SEG(OleInitialize)
STDAPI OleInitializeEx(LPVOID pMalloc, ULONG ulFlags) { OLETRACEIN((API_OleInitialize, PARAMFMT("pMalloc= %p, ulFlags= %x"), pMalloc, ulFlags)); VDATEHEAP();
HRESULT hr; #if DBG==1
HRESULT hrCoInit = S_OK; #endif
DWORD cThreadOleInits;
hr = CoInitializeEx(pMalloc, ulFlags);
if (SUCCEEDED(hr)) { Assert (g_hmodOLE2); #if DBG==1
hrCoInit = hr; #endif
COleTls tls; cThreadOleInits = ++ tls->cOleInits;
do { // We only want to do the below initialization once per apartment
if (cThreadOleInits > 1) { // We've already been this way before, just return
Assert(SUCCEEDED(hr) && "Bad OleInitializeEx logic"); break; }
// single thread registration of DDE and clipboard formats.
// Only do this once per process.
COleStaticLock lck(g_mxsSingleThreadOle);
if (++g_cOleProcessInits != 1) { // already done the per-process initialization
break; }
// initialized DDE only if any server objects have
// already been registered.
hr = CheckInitDde(FALSE); if (FAILED(hr)) { Assert (!"DDELibMain failed()"); break; }
// Only need to do the initialization once so check the global
// that gets assigned last.
if( !g_aDropTarget ) { // on NT3.51, clipboard formats are pre-registered for us by user32.
// (This is done in file \ntuser\kernel\server.c.)
// We know they are going to be sequential. This gives us a
// good performance improvement (since the clipboard formats never
// change.
g_cfObjectLink = (CLIPFORMAT) RegisterClipboardFormat(OLESTR("ObjectLink"));
g_cfOwnerLink = g_cfObjectLink + 1; Assert(g_cfOwnerLink == RegisterClipboardFormat(OLESTR("OwnerLink")));
g_cfNative = g_cfObjectLink + 2; Assert(g_cfNative == RegisterClipboardFormat(OLESTR("Native")));
g_cfBinary = g_cfObjectLink + 3; Assert(g_cfBinary == RegisterClipboardFormat(OLESTR("Binary")));
g_cfFileName = g_cfObjectLink + 4; Assert(g_cfFileName == RegisterClipboardFormat(OLESTR("FileName")));
g_cfFileNameW = g_cfObjectLink + 5; Assert(g_cfFileNameW == RegisterClipboardFormat(OLESTR("FileNameW")));
g_cfNetworkName = g_cfObjectLink + 6; Assert(g_cfNetworkName == RegisterClipboardFormat(OLESTR("NetworkName")));
g_cfDataObject = g_cfObjectLink + 7; Assert(g_cfDataObject == RegisterClipboardFormat(OLESTR("DataObject")));
g_cfEmbeddedObject = g_cfObjectLink + 8; Assert(g_cfEmbeddedObject == RegisterClipboardFormat(OLESTR("Embedded Object")));
g_cfEmbedSource = g_cfObjectLink + 9; Assert(g_cfEmbedSource == RegisterClipboardFormat(OLESTR("Embed Source")));
g_cfCustomLinkSource = g_cfObjectLink + 10; Assert(g_cfCustomLinkSource == RegisterClipboardFormat(OLESTR("Custom Link Source")));
g_cfLinkSource = g_cfObjectLink + 11; Assert(g_cfLinkSource == RegisterClipboardFormat(OLESTR("Link Source")));
g_cfObjectDescriptor = g_cfObjectLink + 12; Assert(g_cfObjectDescriptor == RegisterClipboardFormat(OLESTR("Object Descriptor")));
g_cfLinkSrcDescriptor = g_cfObjectLink + 13; Assert(g_cfLinkSrcDescriptor == RegisterClipboardFormat(OLESTR("Link Source Descriptor")));
g_cfOleDraw = g_cfObjectLink + 14; Assert(g_cfOleDraw == RegisterClipboardFormat(OLESTR("OleDraw")));
g_cfPBrush = g_cfObjectLink + 15; Assert(g_cfPBrush == RegisterClipboardFormat(OLESTR("PBrush")));
g_cfMSDraw = g_cfObjectLink + 16; Assert(g_cfMSDraw == RegisterClipboardFormat(OLESTR("MSDraw")));
g_cfOlePrivateData = g_cfObjectLink + 17; Assert(g_cfOlePrivateData == RegisterClipboardFormat(OLESTR("Ole Private Data")));
g_cfScreenPicture = g_cfObjectLink + 18; Assert(g_cfScreenPicture == RegisterClipboardFormat(OLESTR("Screen Picture")));
g_cfOleClipboardPersistOnFlush = g_cfObjectLink + 19;
/* turned off till NtUser group checks in for 335613
Assert(g_cfOleClipboardPersistOnFlush == RegisterClipboardFormat(OLESTR("OleClipboardPersistOnFlush"))); */
g_cfMoreOlePrivateData = g_cfObjectLink + 20;
/* turned off till NtUser group checks in for 335613
Assert(g_cfMoreOlePrivateData == RegisterClipboardFormat(OLESTR("MoreOlePrivateData"))); */
g_aDropTarget = GlobalAddAtom(OLE_DROP_TARGET_PROP); AssertSz(g_aDropTarget, "Couldn't add drop target atom\n");
g_aDropTargetMarshalHwnd = GlobalAddAtom(OLE_DROP_TARGET_MARSHALHWND); AssertSz(g_aDropTargetMarshalHwnd, "Couldn't add drop target hwnd atom\n");
}
// Used in Inplace editing
uOmPostWmCommand = RegisterWindowMessage(OLESTR("OM_POST_WM_COMMAND")); uOleMessage = RegisterWindowMessage(OLESTR("OLE_MESSAHE"));
} while (FALSE); // end of do
if (FAILED(hr)) { // clean up and break out
CheckUninitDde(FALSE);
tls->cOleInits--; CoUninitialize(); } else { Assert(SUCCEEDED(hr) && "Bad OleInitializeEx logic");
// If we're overriding the allocator, we return whatever
// CoInitializeEx returned
if (NULL != pMalloc) { Assert(hr == hrCoInit && "Bad OleInit logic"); } else if (1 == cThreadOleInits) { // First successful call to OleInitializeEx - S_OK
hr = S_OK; } else { // Second or greater succesful call to OleInitializeEx - S_FALSE
hr = S_FALSE; }
// Notify the COM verifier about the oleinit, for tracking purposes.
CoVrfNotifyOleInit(); } }
OLETRACEOUT((API_OleInitialize, hr)); return hr; }
//+-------------------------------------------------------------------------
//
// Function: OleUnitialize
//
// Synopsis: Unitializes OLE, releasing any grabbed resources
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: void
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 06-Dec-93 alexgo 32bit port
// 21-Jul-94 AlexT Allow nested OleInit/Uninit calls
//
// Notes:
//
//--------------------------------------------------------------------------
#pragma SEG(OleUninitialize)
STDAPI_(void) OleUninitialize(void) { OLETRACEIN((API_OleUninitialize, NOPARAM));
VDATEHEAP();
COleTls tls(TRUE);
if (tls.IsNULL() || 0 == tls->cOleInits) { CoVrfNotifyExtraOleUninit();
LEDebugOut((DEB_ERROR, "(0 == thread inits) Unbalanced call to OleUninitialize\n")); goto errRtn; }
if (0 == -- tls->cOleInits) { // This thread has called OleUninitialize for the last time. Check if
// we need to do per process uninit now.
ClipboardUninitialize(); // Must be first thing
CheckUninitDde(FALSE);
COleStaticLock lck(g_mxsSingleThreadOle);
if (--g_cOleProcessInits == 0) {
DragDropProcessUninitialize();
// after this point, the uninit should not fail (because we don't
// have code to redo the init).
CheckUninitDde(TRUE);
#if DBG==1
// check for unreleased globals
UtGlobalFlushTracking(); #endif
} }
// Notify the COM verifier about the oleuninit, for tracking purposes.
CoVrfNotifyOleUninit();
// We call CoInitialize each time we call OleInitialize, so here we
// balance that call
CoUninitialize();
errRtn: OLETRACEOUTEX((API_OleUninitialize, NORETURN));
return; }
|