windows-nt/Source/XPSP1/NT/base/mvdm/wow16/ole/client/main.c
2020-09-26 16:20:57 +08:00

782 lines
20 KiB
C

/****************************** Module Header ******************************\
* Module Name: MAIN.C
*
* PURPOSE: WinMain, WEP and some other misc routines
*
* Created: 1991
*
* Copyright (c) 1990, 1991 Microsoft Corporation
*
* History:
* Srinik (04/01/91) Pulled some routines, into this, from ole.c.
*
\***************************************************************************/
#include <windows.h>
#include <shellapi.h>
#include "dll.h"
#ifndef WF_WLO
#define WF_WLO 0x8000
#endif
// ordinal number new win31 API IsTask
#define ORD_IsTask 320
#define NUM_DLL 30 /* space for this many DLL_ENTRYs is created on */
/* each alloc/realloc */
OLECLIPFORMAT cfOwnerLink = 0; // global variables for clip frmats
OLECLIPFORMAT cfObjectLink = 0;
OLECLIPFORMAT cfLink = 0;
OLECLIPFORMAT cfNative = 0;
OLECLIPFORMAT cfBinary = 0;
OLECLIPFORMAT cfFileName = 0;
OLECLIPFORMAT cfNetworkName = 0;
ATOM aStdHostNames;
ATOM aStdTargetDevice ;
ATOM aStdDocDimensions;
ATOM aStdDocName;
ATOM aStdColorScheme;
ATOM aNullArg = 0;
ATOM aSave;
ATOM aChange;
ATOM aClose;
ATOM aSystem;
ATOM aOle;
ATOM aClipDoc;
ATOM aPackage;
// Used in work around for MSDraw bug
ATOM aMSDraw;
extern LPCLIENTDOC lpHeadDoc;
extern LPCLIENTDOC lpTailDoc;
extern RENDER_ENTRY stdRender[];
HANDLE hInstDLL;
BOOL bProtMode;
BOOL bWLO = FALSE;
/* HANDLE hDllTable; !!! Add this when bug in WEP is fixed */
DLL_ENTRY lpDllTable[NUM_DLL]; //!!! change this when WEP bug is fixed
DWORD dllTableSize;
int iLast = 0;
int iMax = NUM_DLL -1;
int iUnloadableDll = NULL; // index to handler than can be freed up
char packageClass[] = "Package";
// For QuerySize() API & methods.
extern OLESTREAMVTBL dllStreamVtbl;
extern CLIENTDOC lockDoc;
#ifdef FIREWALLS
BOOL bShowed = FALSE;
char szDebugBuffer[80];
short ole_flags;
void FARINTERNAL ShowVersion (void);
void FARINTERNAL SetOleFlags(void);
#endif
// LOWWORD - BYTE 0 major verision, BYTE1 minor version,
// HIWORD reserved
DWORD dwOleVer = 0x2001L; // change this when we want to update dll version
// number
DWORD dwVerToFile = 0x0501L; // This is used while object is being saved to
// file. There is no need to change this value
// whenever we change ole dll version number
static BOOL bLibInit = FALSE;
WORD wWinVer;
HANDLE hModule;
#define MAX_HIMETRIC 0x7FFF
int maxPixelsX = MAX_HIMETRIC;
int maxPixelsY = MAX_HIMETRIC;
void SetMaxPixel (void);
VOID FAR PASCAL WEP (int);
#pragma alloc_text(WEP_TEXT, WEP)
FARPROC lpfnIsTask = NULL; // the API IsTask() became available from
// win31 onwards, hence we are trying to
// get it's address through GetProcAddress
//////////////////////////////////////////////////////////////////////////////
//
// int FAR PASCAL LibMain (hInst, wDataSeg, cbHeapSize, lpszCmdLine)
//
// The main library entry point. This routine is called when the library
// is loaded.
//
// Arguments:
//
// hInst - dll's instance handle
// wDataSeg - DS register value
// cbHeapSize - heap size defined def file
// lpszCmdLine - command line info
//
// Returns:
//
// 0 - failure
// 1 - success
//
// Effects:
//
//////////////////////////////////////////////////////////////////////////////
int FAR PASCAL LibMain (hInst, wDataSeg, cbHeapSize, lpszCmdLine)
HANDLE hInst;
WORD wDataSeg;
WORD cbHeapSize;
LPSTR lpszCmdLine;
{
WNDCLASS wc;
int i;
Puts("LibMain");
#ifdef FIREWALLS
SetOleFlags();
#endif
bLibInit = TRUE;
hInstDLL = hInst;
hModule = GetModuleHandle ("OLECLI");
bProtMode = (BOOL) (GetWinFlags() & WF_PMODE);
bWLO = (BOOL) (GetWinFlags() & WF_WLO);
wWinVer = (WORD) GetVersion();
// REGISTER LINK FORMAT
cfObjectLink = RegisterClipboardFormat("ObjectLink");
cfLink = RegisterClipboardFormat("Link");
cfOwnerLink = RegisterClipboardFormat("OwnerLink");
cfNative = RegisterClipboardFormat("Native");
cfBinary = RegisterClipboardFormat("Binary");
cfFileName = RegisterClipboardFormat("FileName");
cfNetworkName = RegisterClipboardFormat("NetworkName");
if (!(cfObjectLink && cfOwnerLink && cfNative && cfLink))
return 0;
// SET UP OLEWNDCLASS
wc.style = NULL;
wc.lpfnWndProc = DocWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(LONG); //we are storing longs
wc.hInstance = hInst;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground= NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName= "OleDocWndClass";
if (!RegisterClass(&wc))
return 0;
wc.lpfnWndProc = SrvrWndProc;
wc.lpszClassName = "OleSrvrWndClass";
if (!RegisterClass(&wc))
return 0;
/*
// !!! Add this when bug in WEP is fixed.
// Allocate memory for DLL table
dllTableSize = NUM_DLL * sizeof(DLL_ENTRY);
if (!(hDllTable = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT,
dllTableSize)))
return 0;
if (!(lpDllTable = (DLL_ENTRY FAR *) GlobalLock (hDllTable)))
return 0;
*/
// !!! remove the following when WEP bug is fixed
for (i = 0; i < NUM_DLL; i++)
lpDllTable[i].aDll = 0;
// !!! BEGIN hack for Pbrush.
lpDllTable[0].hDll = NULL;
lpDllTable[0].aDll = GlobalAddAtom ((LPSTR) "ole");
lpDllTable[0].Load = PbLoadFromStream;
lpDllTable[0].Clip = PbCreateFromClip;
lpDllTable[0].Link = PbCreateLinkFromClip;
lpDllTable[0].Create = PbCreate;
lpDllTable[0].CreateFromTemplate = PbCreateFromTemplate;
lpDllTable[0].CreateFromFile = PbCreateFromFile;
lpDllTable[0].CreateLinkFromFile = PbCreateLinkFromFile;
lpDllTable[0].CreateInvisible = PbCreateInvisible;
// !!! END hack for pbrush
// For ObjectSize API
dllStream.lpstbl = (LPOLESTREAMVTBL) &dllStreamVtbl;
dllStream.lpstbl->Put = DllPut;
// add the atoms required.
aStdDocName = GlobalAddAtom ((LPSTR)"StdDocumentName");
aSave = GlobalAddAtom ((LPSTR)"Save");
aChange = GlobalAddAtom ((LPSTR)"Change");
aClose = GlobalAddAtom ((LPSTR)"Close");
aSystem = GlobalAddAtom ((LPSTR)"System");
aOle = GlobalAddAtom ((LPSTR)"OLEsystem");
aPackage = GlobalAddAtom ((LPSTR) packageClass);
// Used in work around for MSDraw bug
aMSDraw = GlobalAddAtom ((LPSTR) "MSDraw");
// clipboard document name atom
aClipDoc = GlobalAddAtom ((LPSTR)"Clipboard");
stdRender[0].aClass = GlobalAddAtom ("METAFILEPICT");
stdRender[1].aClass = GlobalAddAtom ("DIB");
stdRender[2].aClass = GlobalAddAtom ("BITMAP");
SetMaxPixel();
if (wWinVer != 0x0003) {
HANDLE hModule;
if (hModule = GetModuleHandle ("KERNEL"))
lpfnIsTask = GetProcAddress (hModule,
(LPSTR) MAKELONG (ORD_IsTask, 0));
}
if (cbHeapSize != 0)
UnlockData(0);
return 1;
}
//////////////////////////////////////////////////////////////////////////////
//
// VOID FAR PASCAL WEP (nParameter)
//
// Called just before the library is being unloaded. Delete all the atoms
// added by this dll and also frees up all unloaded handler dlls.
//
// Arguments:
//
// nParameter - Termination code
//
// Returns:
//
// none
//
// Effects:
//
//////////////////////////////////////////////////////////////////////////////
VOID FAR PASCAL WEP (nParameter)
int nParameter;
{
int i;
Puts("LibExit");
// case when the DLLs are missing
if (!bLibInit)
return;
if (nParameter == WEP_SYSTEM_EXIT)
DEBUG_OUT ("---L&E DLL EXIT on system exit---",0)
else if (nParameter == WEP_FREE_DLL)
DEBUG_OUT ("---L&E DLL EXIT---\n",0)
else
return;
// Delete atoms added by us
for (i = 0; i < NUM_RENDER; i++) {
if (stdRender[i].aClass)
GlobalDeleteAtom (stdRender[i].aClass);
}
if (aStdDocName)
GlobalDeleteAtom (aStdDocName);
if (aSave)
GlobalDeleteAtom (aSave);
if (aChange)
GlobalDeleteAtom (aChange);
if (aClose)
GlobalDeleteAtom (aClose);
if (aSystem)
GlobalDeleteAtom (aSystem);
if (aOle)
GlobalDeleteAtom (aOle);
if (aPackage)
GlobalDeleteAtom (aPackage);
if (aClipDoc)
GlobalDeleteAtom (aClipDoc);
if (aMSDraw)
GlobalDeleteAtom (aMSDraw);
// Free handler dlls if there are any still loaded. Entry 0 is used for
// Pbrush handler which is part of this dll.
for (i = 0; i <= iLast; i++) {
if (lpDllTable[i].aDll)
GlobalDeleteAtom (lpDllTable[i].aDll);
if (lpDllTable[i].hDll)
FreeLibrary (lpDllTable[i].hDll);
}
#ifdef FIREWALLS
ASSERT(!lpHeadDoc, "Some client doc structures are not deleted");
ASSERT(!lockDoc.lpHeadObj, "Some servers are left in a locked state");
#endif
/* !!! Add this when bug in WEP is fixed
if (lpDllTable)
GlobalUnlock (hDllTable);
if (hDllTable)
GlobalFree (hDllTable);
*/
}
//////////////////////////////////////////////////////////////////////////////
//
// void FARINTERNAL SetOleFlags()
//
// Sets the debug level flags for controlling the level of debug information
// on the comm terminal. This will be included only in the debug version.
//
// Arguments:
//
// none
//
// Returns:
//
// none
//
// Effects:
//
//////////////////////////////////////////////////////////////////////////////
#ifdef FIREWALLS
void FARINTERNAL SetOleFlags()
{
char buffer[80];
if(GetProfileString ("OLE",
"Puts","", (LPSTR)buffer, 80))
ole_flags = DEBUG_PUTS;
else
ole_flags = 0;
if(GetProfileString ("OLE",
"DEBUG_OUT","", (LPSTR)buffer, 80))
ole_flags |= DEBUG_DEBUG_OUT;
if(GetProfileString ("OLE",
"MESSAGEBOX","", (LPSTR)buffer, 80))
ole_flags |= DEBUG_MESSAGEBOX;
}
//////////////////////////////////////////////////////////////////////////////
//
// void FARINTERNAL ShowVersion (void)
//
// Displays version, date, time and copyright info in client app's window.
// Called by all the object create functions after checking the flag bShowed.
// This will be included only in the debug version.
//
// Arguments:
//
// none
//
// Returns:
//
// none
//
// Effects:
//
// sets bShowed
//
//////////////////////////////////////////////////////////////////////////////
void FARINTERNAL ShowVersion ()
{
if (!bShowed && (ole_flags & DEBUG_MESSAGEBOX)) {
MessageBox (NULL, "\
VER: 1.09.000\n\
TIME: 16:00:00\n\
DATE: 01/31/1992\n\
Copyright (c) 1990, 1991 Microsoft Corp.\n\
All Rights Reserved.",
"Ole Client Library",
MB_OK | MB_TASKMODAL);
bShowed = TRUE;
}
}
#endif
int FARINTERNAL LoadDll (lpClass)
LPSTR lpClass;
{
char str[MAX_STR];
char str1[MAX_STR];
ATOM aDll = NULL;
int index;
int iEmpty;
BOOL found = FALSE;
HANDLE hDll;
int refcnt;
LONG cb = MAX_STR;
if (!lstrcmpi (lpClass, "Pbrush"))
return 0;
lstrcpy (str, lpClass);
lstrcat (str, "\\protocol\\StdFileEditing\\handler");
if (RegQueryValue (HKEY_CLASSES_ROOT, str, str1, &cb))
return INVALID_INDEX;
if (aDll = GlobalFindAtom (str1)) {
for (index = 1; index <= iLast; index++) {
if (lpDllTable[index].aDll == aDll) { // Dll already loaded
lpDllTable[index].cObj ++;
if (index == iUnloadableDll) {
// since the object count is not zero anymore, this
// handler can not be freed up.
iUnloadableDll = NULL;
}
return index;
}
}
}
aDll = GlobalAddAtom (str1);
// Look for an empty entry
for (iEmpty = 1; iEmpty <= iLast; iEmpty++) {
if (!lpDllTable[iEmpty].aDll) {
found = TRUE;
break;
}
}
if (iEmpty > iMax)
goto errLoad;
/*
if (!found) {// no empty entry exists create a new one if necessary.
if (iEmpty > iMax) {
dllTableSize += (blockSize = NUM_DLL * sizeof(DLL_ENTRY));
hTable = GlobalReAlloc (hDllTable, dllTableSize,
GMEM_MOVEABLE | GMEM_ZEROINIT);
if (hTable == hDllTable)
iMax += NUM_DLL;
else {
dllTableSize -= blockSize;
iEmpty = INVALID_INDEX;
}
}
}
*/
// !!! reference count of OLECLI is increasing by 2 when the handlers are
// are loaded, looks like windows bug. Following is a temporary fix.
refcnt = GetModuleUsage (hModule);
hDll = LoadLibrary ((LPSTR) str1);
refcnt = (GetModuleUsage (hModule) - refcnt);
while (refcnt > 1) {
FreeModule (hModule);
refcnt--;
}
if (hDll < 32)
goto errLoad;
if (!(lpDllTable[iEmpty].Load = GetProcAddress (hDll,
"DllLoadFromStream")))
goto errLoad;
if (!(lpDllTable[iEmpty].Clip = GetProcAddress (hDll,
"DllCreateFromClip")))
goto errLoad;
if (!(lpDllTable[iEmpty].Link = GetProcAddress (hDll,
"DllCreateLinkFromClip")))
goto errLoad;
if (!(lpDllTable[iEmpty].CreateFromTemplate = GetProcAddress (hDll,
"DllCreateFromTemplate")))
goto errLoad;
if (!(lpDllTable[iEmpty].Create = GetProcAddress (hDll, "DllCreate")))
goto errLoad;
if (!(lpDllTable[iEmpty].CreateFromFile = GetProcAddress (hDll,
"DllCreateFromFile")))
goto errLoad;
if (!(lpDllTable[iEmpty].CreateLinkFromFile = GetProcAddress (hDll,
"DllCreateLinkFromFile")))
goto errLoad;
lpDllTable[iEmpty].CreateInvisible = GetProcAddress (hDll,
"DllCreateInvisible");
lpDllTable[iEmpty].aDll = aDll;
lpDllTable[iEmpty].cObj = 1;
lpDllTable[iEmpty].hDll = hDll;
if (iEmpty > iLast)
iLast++;
return iEmpty;
errLoad:
if (aDll)
GlobalDeleteAtom (aDll);
if (hDll >= 32)
FreeLibrary (hDll);
return INVALID_INDEX;
}
// unload the the handler that can be free up (whose object count is NULL)
void FARINTERNAL UnloadDll ()
{
if (!iUnloadableDll)
return;
if (iUnloadableDll == iLast)
iLast--;
if (lpDllTable[iUnloadableDll].aDll)
GlobalDeleteAtom (lpDllTable[iUnloadableDll].aDll);
lpDllTable[iUnloadableDll].aDll = NULL;
FreeLibrary (lpDllTable[iUnloadableDll].hDll);
lpDllTable[iUnloadableDll].hDll = NULL;
iUnloadableDll = NULL;
}
//
// Reduce the object count of the handler, refered to by the index, by one.
// If the object count becomes NULL, free up the handler that is ready to be
// freed (refered to by index iUnloadableDll), and then make this handler the
// freeable one.
//
// As you can see we are trying to implement a simple mechanism of caching.
//
void FARINTERNAL DecreaseHandlerObjCount (iTable)
int iTable;
{
if (!iTable)
return;
if (iTable != INVALID_INDEX) {
ASSERT (lpDllTable[iTable].cObj, "Handler Obj count is already NULL");
if (!--lpDllTable[iTable].cObj) {
UnloadDll ();
iUnloadableDll = iTable;
}
}
}
/***************************** Public Function ****************************\
*
* OLESTATUS FARINTERNAL CreatePictFromClip (lpclient, lhclientdoc, lpobjname, lplpoleobject, optRender, cfFormat, lpClass, ctype)
*
* CreatePictFromClip: This function creates the LP to an object
* from the clipboard. It will try to create a static picture object if
* it understands any rendering formats on the clipboard. Currently, it
* understands only bitmaps and metafiles.
*
* Effects:
*
* History:
* Wrote it.
\***************************************************************************/
OLESTATUS FARINTERNAL CreatePictFromClip (lpclient, lhclientdoc, lpobjname, lplpobj, optRender, cfFormat, lpClass, objType)
LPOLECLIENT lpclient;
LHCLIENTDOC lhclientdoc;
LPSTR lpobjname;
LPOLEOBJECT FAR * lplpobj;
OLEOPT_RENDER optRender;
OLECLIPFORMAT cfFormat;
LPSTR lpClass;
LONG objType;
{
OLESTATUS retVal = OLE_ERROR_OPTION;
*lplpobj = NULL;
if (optRender == olerender_none)
return OLE_OK;
else if (optRender == olerender_format) {
switch (cfFormat) {
case NULL:
return OLE_ERROR_FORMAT;
case CF_METAFILEPICT:
return MfPaste (lpclient, lhclientdoc, lpobjname,
lplpobj, objType);
case CF_DIB:
return DibPaste (lpclient, lhclientdoc, lpobjname,
lplpobj, objType);
case CF_BITMAP:
return BmPaste (lpclient, lhclientdoc, lpobjname,
lplpobj, objType);
default:
return GenPaste (lpclient, lhclientdoc, lpobjname, lplpobj,
lpClass, cfFormat, objType);
}
}
else if (optRender == olerender_draw) {
cfFormat = EnumClipboardFormats (NULL);
while ((cfFormat) && (retVal > OLE_WAIT_FOR_RELEASE)) {
switch (cfFormat) {
case CF_METAFILEPICT:
retVal = MfPaste (lpclient, lhclientdoc,
lpobjname, lplpobj, objType);
break;
case CF_DIB:
retVal = DibPaste (lpclient, lhclientdoc,
lpobjname, lplpobj, objType);
break;
case CF_BITMAP:
retVal = BmPaste (lpclient, lhclientdoc,
lpobjname, lplpobj, objType);
break;
}
cfFormat = EnumClipboardFormats (cfFormat);
}
}
return retVal;
}
OLESTATUS FARINTERNAL CreatePackageFromClip (lpclient, lhclientdoc, lpobjname, lplpobj, optRender, cfFormat, objType)
LPOLECLIENT lpclient;
LHCLIENTDOC lhclientdoc;
LPSTR lpobjname;
LPOLEOBJECT FAR * lplpobj;
OLEOPT_RENDER optRender;
OLECLIPFORMAT cfFormat;
LONG objType;
{
char file[MAX_STR+6];
HANDLE hData;
LPSTR lpFileName;
if (!(hData = GetClipboardData (cfFileName))
|| !(lpFileName = GlobalLock (hData)))
return OLE_ERROR_CLIPBOARD;
if (objType == OT_LINK) {
lstrcpy (file, lpFileName);
lstrcat (file, "/Link");
lpFileName = (LPSTR) file;
}
GlobalUnlock (hData);
return CreateEmbLnkFromFile (lpclient, packageClass, lpFileName,
NULL, lhclientdoc, lpobjname, lplpobj,
optRender, cfFormat, OT_EMBEDDED);
}
void FARINTERNAL RemoveLinkStringFromTopic (lpobj)
LPOBJECT_LE lpobj;
{
char buf[MAX_STR+6];
int i = 0;
if (GlobalGetAtomName (lpobj->topic, buf, sizeof(buf))) {
// scan the topic for "/Link"
while (buf[i] != '/') {
if (!buf[i])
return;
i++;
}
buf[i] = '\0';
if (lpobj->topic)
GlobalDeleteAtom (lpobj->topic);
lpobj->topic = GlobalAddAtom (buf);
}
}
void SetMaxPixel ()
{
HDC hdc;
// find out the pixel equivalent of MAX_HIMETRIC in X and Y directions
if (hdc = GetDC (NULL)) {
maxPixelsX = MulDiv (MAX_HIMETRIC, GetDeviceCaps(hdc, LOGPIXELSX),
2540);
maxPixelsY = MulDiv (MAX_HIMETRIC, GetDeviceCaps(hdc, LOGPIXELSY),
2540);
ReleaseDC (NULL, hdc);
}
}