mirror of https://github.com/lianthony/NT4.0
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.
757 lines
18 KiB
757 lines
18 KiB
/*
|
|
ddesrvr.cpp
|
|
|
|
Author:
|
|
Jason Fuller jasonful 8-11-92
|
|
*/
|
|
|
|
#include <ole2int.h>
|
|
#include <dde.h>
|
|
#include <olerem.h>
|
|
#include "srvr.h"
|
|
#include "ddeatoms.h"
|
|
#include "ddesrvr.h"
|
|
#include "ddedebug.h"
|
|
#include "map_up.h"
|
|
|
|
#include "map_dwp.h"
|
|
|
|
ASSERTDATA
|
|
|
|
// Dde Common Window stuff
|
|
|
|
UINT cCommonWindows = 0;
|
|
|
|
#ifdef _CHICAGO_
|
|
// Note: we have to create a unique string so that get
|
|
// register a unique class for each 16 bit app.
|
|
// The class space is global on chicago.
|
|
//
|
|
LPSTR szOLE_CLASSA = "Ole2WndClass 0x######## ";
|
|
LPSTR szSRVR_CLASSA = "SrvrWndClass 0x######## ";
|
|
|
|
LPSTR szDdeServerWindow = "DDE Server Window";
|
|
#define szDdeCommonWindowClass szCOMMONCLASSA
|
|
#else
|
|
const LPOLESTR szDdeServerWindow = OLESTR("DDE Server Window");
|
|
const LPOLESTR szDdeCommonWindowClass = OLESTR("DdeCommonWindowClass");
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CreateDdeSrvrWindow
|
|
//
|
|
// Synopsis: When CoRegisterClassObject is called, this function
|
|
// is called to create a DDE window to listen for DDE messages
|
|
// from a 1.0 client.
|
|
//
|
|
// Effects:
|
|
//
|
|
// Arguments: [clsid] --
|
|
// [aClass] --
|
|
// [phwnd] --
|
|
// [fIsRunning] --
|
|
// [aOriginalClass] --
|
|
// [cnvtyp] --
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Signals:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// Algorithm:
|
|
//
|
|
// History: 5-27-94 kevinro Commented/cleaned
|
|
// 13-Jul-94 BruceMa Make register/unregister dde window class
|
|
// thread safe
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
INTERNAL CreateDdeSrvrWindow
|
|
(REFCLSID clsid,
|
|
ATOM aClass,
|
|
HWND FAR* phwnd, // optional out parm: created window
|
|
BOOL fIsRunning, // Is the item atom a file in the ROT?
|
|
ATOM aOriginalClass, // for TreatAs/ConvertTo case
|
|
CNVTYP cnvtyp)
|
|
{
|
|
intrDebugOut((DEB_DDE_INIT,"0 _IN CreateDdeSrvrWindow\n"));
|
|
|
|
VDATEHEAP();
|
|
HWND hwnd = NULL;
|
|
|
|
HRESULT hresult = NOERROR;
|
|
|
|
DdeClassInfo ddeClassInfo;
|
|
|
|
ddeClassInfo.dwContextMask = CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER;
|
|
ddeClassInfo.fClaimFactory = FALSE;
|
|
|
|
// Null out parameter in case of error
|
|
if (phwnd)
|
|
{
|
|
*phwnd = NULL;
|
|
}
|
|
|
|
intrAssert (wIsValidAtom (aClass));
|
|
|
|
//
|
|
// See if this process is registered as a class server for
|
|
// the requested class. If it isn't, then check for a running
|
|
// object.
|
|
//
|
|
if (GetClassInformationForDde(clsid,&ddeClassInfo) == FALSE)
|
|
{
|
|
intrDebugOut((DEB_DDE_INIT,
|
|
"CreateDdeSrvrWindow No class information available\n"));
|
|
|
|
//
|
|
// The ClassObject was not found in the table.
|
|
//
|
|
|
|
if (fIsRunning)
|
|
{
|
|
// Link case.
|
|
// An SDI app was launched by the user (without "-Embedding").
|
|
// It did not register its class factory. (It never does.)
|
|
// Meanwhile, a DDE_INIT with a filename as an item atom was
|
|
// broadcasted.
|
|
// We are in the task of the SDI app that loaded that filename,
|
|
// so this function was called.
|
|
// So we need to create the window even though no class factory
|
|
// was registered.
|
|
// Call CDDEServer::Create with a lot of NULLs.
|
|
// Once the DDE_INIT is passed along to the server window, it
|
|
// should immediately cause a doc window to be created.
|
|
// Must be SDI or we wouldn't have this problem.
|
|
//
|
|
// This works because we are going to attempt to 'bind' to the
|
|
// object which is the subject of the link. If the link object
|
|
// was registered as running, we will find it. Otherwise, the
|
|
// attempt to create via the class factory will fail, since the
|
|
// class factory doesn't exist.
|
|
//
|
|
|
|
intrDebugOut((DEB_DDE_INIT,
|
|
"::CreateDdeServerWindow fIsRunning - override dwFlags\n"));
|
|
|
|
//
|
|
// NULL out the entire structure, then set only the flags
|
|
//
|
|
memset(&ddeClassInfo,0,sizeof(ddeClassInfo));
|
|
ddeClassInfo.dwFlags = REGCLS_SINGLEUSE;
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
intrDebugOut((DEB_DDE_INIT,
|
|
"CreateDdeServerWindow Returning FALSE\n"));
|
|
|
|
hresult = S_FALSE;
|
|
goto errRtn;
|
|
}
|
|
}
|
|
intrDebugOut((DEB_DDE_INIT,
|
|
"::CreateDdeServerWindow found class\n"));
|
|
// Create() does the real work: creates a CDDEServer and the window.
|
|
WCHAR szClass[MAX_STR];
|
|
lstrcpyW (szClass, wAtomName (aClass));
|
|
Assert (szClass[0]);
|
|
|
|
hresult = CDDEServer::Create(szClass,
|
|
clsid,
|
|
&ddeClassInfo,
|
|
&hwnd,
|
|
aOriginalClass,
|
|
cnvtyp);
|
|
if (hresult != NOERROR)
|
|
{
|
|
intrDebugOut((DEB_IERROR,
|
|
"CreateDdeServerWindow CDDEServer::Create returns %x\n",
|
|
hresult));
|
|
goto errRtn;
|
|
}
|
|
|
|
Assert (IsWindowValid(hwnd));
|
|
|
|
// Fill in out parameter
|
|
if (phwnd)
|
|
{
|
|
*phwnd = hwnd;
|
|
}
|
|
|
|
|
|
errRtn:
|
|
VDATEHEAP();
|
|
intrDebugOut((DEB_DDE_INIT,
|
|
"0 _OUT CreateDdeSrvrWindow %x\n",
|
|
hresult));
|
|
return hresult;
|
|
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DestroyDdeSrvrWindow
|
|
//
|
|
// Synopsis: Destroy a DDE server window
|
|
//
|
|
// Effects:
|
|
//
|
|
// Arguments: [hwnd] -- Window to destroy
|
|
// [aClass] -- Class for server
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Signals:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// Algorithm:
|
|
//
|
|
// History: 6-24-94 kevinro Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
INTERNAL DestroyDdeSrvrWindow
|
|
(HWND hwnd,
|
|
ATOM aClass)
|
|
{
|
|
intrDebugOut((DEB_ITRACE,
|
|
"0 _IN DestroyDdeSrvrWindow\n"));
|
|
VDATEHEAP();
|
|
Assert (IsAtom (aClass));
|
|
|
|
// Make sure it is a server window
|
|
RetZ (IsWindowValid (hwnd));
|
|
RetZ (GetWindowWord (hwnd, WW_LE) == WC_LE);
|
|
|
|
|
|
// Get the Common window for this task.
|
|
|
|
HWND hwndCommonServer = (HWND)TLSGetDdeServer();
|
|
|
|
if (hwndCommonServer == NULL)
|
|
{
|
|
intrDebugOut((DEB_IERROR,"hwndCommonServer != NULL\n"));
|
|
return(E_UNEXPECTED);
|
|
}
|
|
if (!IsWindow(hwndCommonServer))
|
|
{
|
|
intrAssert(IsWindow(hwndCommonServer));
|
|
return(E_UNEXPECTED);
|
|
}
|
|
|
|
// Get the map from the common window
|
|
CMapUintPtr FAR *pmapClassToHwnd;
|
|
Assert (sizeof (CMapUintPtr FAR *)==sizeof(LONG));
|
|
pmapClassToHwnd = (CMapUintPtr FAR *) GetWindowLong (hwndCommonServer, 0);
|
|
Assert (pmapClassToHwnd);
|
|
|
|
// Make sure the window we're deleting is the server window for this class
|
|
void *hwndSrvr;
|
|
RetZ (pmapClassToHwnd->Lookup (aClass,hwndSrvr) && hwndSrvr == hwnd);
|
|
|
|
RetZ (SSDestroyWindow (hwnd));
|
|
|
|
// Remove this window from the map
|
|
pmapClassToHwnd->RemoveKey (aClass);
|
|
|
|
VDATEHEAP();
|
|
intrDebugOut((DEB_ITRACE,
|
|
"0 _OUT DestroyDdeSrvrWindow\n"));
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DdeCommonWndProc
|
|
//
|
|
// Synopsis: Window proc for the common dde server window that
|
|
// listens for all WM_DDE_INITIATEs
|
|
//
|
|
// Effects: When a DDE_INITIATE comes in, this routine will determine
|
|
// the class of the object being requested. If the class is
|
|
// served by this thread, then it will create a window to
|
|
// converse with the server.
|
|
//
|
|
// Arguments: [hWnd] -- hWnd of Common DDE
|
|
// [wMsg] -- msg
|
|
// [wParam] -- Return Window to converse with
|
|
// [lParam] -- HIWORD(aItem) LOWORD(aClass)
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Signals:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// Algorithm:
|
|
//
|
|
// History: 5-27-94 kevinro Commented/cleaned
|
|
//
|
|
// Notes:
|
|
//
|
|
// When running in a VDM, it is possible that this window was dispatched
|
|
// without having a full window handle. This happens when the getmessage
|
|
// was dispatched from 16-bit. Therefore, we need to convert the hwnd to
|
|
// a full hwnd before doing any comparision functions.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDAPI_(LRESULT)
|
|
DdeCommonWndProc(HWND hwndIn, UINT wMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
|
|
switch (wMsg)
|
|
{
|
|
case WM_DDE_INITIATE:
|
|
{
|
|
VDATEHEAP();
|
|
ATOM aClass = LOWORD(lParam);
|
|
ATOM aItem = HIWORD(lParam);
|
|
HWND hwnd;
|
|
|
|
CNVTYP cnvtyp = cnvtypNone;
|
|
|
|
BOOL fIsFile= FALSE; // Must initialize
|
|
BOOL fIsRunning= FALSE; // Must initialize
|
|
BOOL fUnsavedDoc = FALSE; // Is the "file" really an unsaved doc
|
|
HWND hwndServer;
|
|
HRESULT hresult;
|
|
|
|
|
|
//
|
|
// From this point forward, we need to insure we are using a
|
|
// FULL hwnd.
|
|
//
|
|
hwnd = ConvertToFullHWND(hwndIn);
|
|
|
|
//
|
|
// The following should already be initialized
|
|
//
|
|
intrAssert (aOLE != NULL);
|
|
intrAssert (aSysTopic != NULL);
|
|
|
|
if (aItem==aOLE || aItem==aSysTopic
|
|
|| (fIsFile=IsFile (aItem, &fUnsavedDoc)))
|
|
{
|
|
|
|
|
|
intrDebugOut((DEB_DDE_INIT,
|
|
"DdeCommonWndProc:hWnd(%x) DDE_INITIATE cls(%ws)\n",
|
|
hwnd,
|
|
wAtomName(aClass)));
|
|
|
|
//
|
|
// Get the ClassToHwnd map for this thread
|
|
//
|
|
CMapUintPtr FAR *pmapClassToHwnd;
|
|
Assert (sizeof (CMapUintPtr FAR *)==sizeof(LONG));
|
|
pmapClassToHwnd = (CMapUintPtr FAR *) GetWindowLong (hwnd, 0);
|
|
Assert (pmapClassToHwnd);
|
|
|
|
|
|
// Convert atom to CLSID, taking into account
|
|
// TreatAs and AutoConvert.
|
|
CLSID clsid;
|
|
ATOM aOriginalClass = aClass;
|
|
|
|
if (CLSIDFromAtomWithTreatAs (&aClass, &clsid, &cnvtyp) != NOERROR)
|
|
{
|
|
intrDebugOut((DEB_IERROR,"Could not get clsid for this class\n"));
|
|
return 0L;
|
|
}
|
|
|
|
void *pServerTmp;
|
|
if (TRUE == pmapClassToHwnd->Lookup (aClass, pServerTmp))
|
|
{
|
|
//
|
|
// Since a server window for this class already exists, but is a child window
|
|
// of ours, we will send it this message directly.
|
|
//
|
|
|
|
intrDebugOut((DEB_DDE_INIT,
|
|
"DdeCommonWndProc Server cls exists. Forwarding to %x\n",
|
|
pServerTmp));
|
|
|
|
return SSSendMessage ((HWND)pServerTmp, WM_DDE_INITIATE, wParam,lParam);
|
|
|
|
}
|
|
|
|
if (CoIsOle1Class (clsid))
|
|
{
|
|
// We have no business intercepting Initiates sent
|
|
// to 1.0 servers
|
|
intrDebugOut((DEB_DDE_INIT,
|
|
"DdeCommonWndProc: Its a OLE 1.0 class\n"));
|
|
return 0L;
|
|
}
|
|
|
|
if (fIsFile)
|
|
{
|
|
// Link case
|
|
WCHAR szFile[MAX_STR];
|
|
|
|
WORD cb=GlobalGetAtomName (aItem, szFile, MAX_STR);
|
|
Assert (cb>0 && cb < MAX_STR-1);
|
|
intrDebugOut((DEB_DDE_INIT,
|
|
"Looking for file %ws\n",szFile));
|
|
|
|
IsRunningInThisTask (szFile, &fIsRunning);
|
|
}
|
|
|
|
// If it's not a file, it can't be running, obviously.
|
|
intrAssert (fIsFile || !fIsRunning);
|
|
|
|
if (NOERROR == (hresult=(CreateDdeSrvrWindow (clsid,
|
|
aClass,
|
|
&hwndServer,
|
|
fIsRunning,
|
|
aOriginalClass,
|
|
cnvtyp))))
|
|
{
|
|
|
|
// Indicate that we have created a server window
|
|
// for this class. We could have used any value in
|
|
// place of hwndServer_. It's just a flag.
|
|
// REVIEW jasonful: how to handle OOM?
|
|
|
|
pmapClassToHwnd->SetAt (wDupAtom(aClass), hwndServer);
|
|
|
|
#if DBG == 1
|
|
// Verify the SetAt we just did.
|
|
void FAR* pv;
|
|
Verify (pmapClassToHwnd->Lookup(aClass, pv));
|
|
Assert (pv == hwndServer);
|
|
#endif
|
|
// Pass the INITIATE along to the real,
|
|
// newly-created server window and forge
|
|
// the sender's hwnd to be whoever called
|
|
// the common server window.
|
|
// SendMessage should return 1L is doc is running,
|
|
// indicating an ACK was sent.
|
|
Assert (IsWindowValid (hwndServer));
|
|
SSSendMessage (hwndServer, WM_DDE_INITIATE, wParam,lParam);
|
|
intrDebugOut((DEB_DDE_INIT,
|
|
"DdeCommonWndProc:hWnd(%x) DDE_INITIATE complete(%ws)\n",
|
|
hwnd,
|
|
wAtomName(aClass)));
|
|
VDATEHEAP();
|
|
}
|
|
else
|
|
{
|
|
if (S_FALSE!=GetScode(hresult))
|
|
{
|
|
intrDebugOut((DEB_IERROR,
|
|
"DCWP: CreateDdeSrvrWindow failed %x\n",
|
|
hresult));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We have a DDE_INITIATE message that needs to be forwarded to our
|
|
// child window.
|
|
//
|
|
return SendMsgToChildren(hwnd,wMsg,wParam,lParam);
|
|
}
|
|
return 0L;
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
//
|
|
// When this window is destroyed, we cleanup the
|
|
// windows attached data.
|
|
//
|
|
|
|
CMapUintPtr FAR *pmapClassToHwnd;
|
|
pmapClassToHwnd = (CMapUintPtr FAR *) GetWindowLong (hwndIn, 0);
|
|
|
|
//
|
|
// Make sure there are no server windows
|
|
// created by this common window still extant. If there are, print out
|
|
// a message on a debug build. Otherwise, there really isn't much we
|
|
// can do about it. We are already closing down. The DDE emulation layer
|
|
// will send appropriate terminate messages.
|
|
//
|
|
|
|
#if DBG == 1
|
|
if (pmapClassToHwnd && !pmapClassToHwnd->IsEmpty())
|
|
{
|
|
intrDebugOut((DEB_ERROR,
|
|
"DCDW Leaking active OLE 1.0 clients\n"));
|
|
intrDebugOut((DEB_ERROR,
|
|
"There were active OLE 1.0 connections at shutdown\n"));
|
|
}
|
|
#endif
|
|
delete pmapClassToHwnd;
|
|
return(0);
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
return SSDefWindowProc (hwndIn, wMsg, wParam, lParam);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CreateCommonDdeWindow
|
|
//
|
|
// Synopsis: Creates a DDE window for initiating conversations with this
|
|
// threads objects.
|
|
//
|
|
// Effects: Creates a window that responds to DDE_INITIATE messages, and
|
|
// determines if it needs to respond to the INITIATE. This
|
|
// routine is called by OleInitializeEx()
|
|
//
|
|
// The handle to the created window is placed in the TLS
|
|
// structure.
|
|
//
|
|
// Arguments: [void] --
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Signals:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// Algorithm:
|
|
//
|
|
// History: 5-27-94 kevinro Converted to OLE32
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
INTERNAL CreateCommonDdeWindow
|
|
(void)
|
|
{
|
|
intrDebugOut((DEB_ITRACE,"%p _IN CreateCommonDdeWindow\n",0));
|
|
|
|
HRESULT hr = NOERROR;
|
|
HWND hwndDdeServer;
|
|
|
|
|
|
COleTls tls;
|
|
if (tls->dwFlags & OLETLS_DISABLE_OLE1DDE)
|
|
{
|
|
// If DDE use is disabled we shouldn't have gotten here.
|
|
//
|
|
Assert(!"Executing CreateCommonDdeWindow when DDE is disabled");
|
|
hr = CO_E_OLE1DDE_DISABLED;
|
|
goto exitRtn;
|
|
}
|
|
|
|
//
|
|
// If a DdeServer window already exists, then return NOERROR.
|
|
// If Com has been initialized but Ole has not, then we dont
|
|
// create a window, we just return NOERROR. This way, COM-only
|
|
// servers dont start serving OLE1 clients.
|
|
//
|
|
|
|
if (tls->hwndDdeServer != NULL || tls->cOleInits == 0)
|
|
{
|
|
goto exitRtn;
|
|
}
|
|
|
|
if (!(hwndDdeServer = DdeCreateWindowEx(0, gOleWindowClass,
|
|
szDdeServerWindow,
|
|
WS_POPUP,0,0,0,0,
|
|
NULL,NULL,
|
|
g_hmodOLE2, NULL)))
|
|
{
|
|
intrDebugOut((DEB_IERROR,
|
|
"CreateCommonDocWindow() has failed %x\n",
|
|
GetLastError()));
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
goto exitRtn;
|
|
}
|
|
|
|
// fix up the WindowProc entry point.
|
|
SetWindowLong(hwndDdeServer, GWL_WNDPROC, (LONG)DdeCommonWndProc);
|
|
|
|
intrDebugOut((DEB_ITRACE,
|
|
"CreateCommonDocWindow() hwndDdeServer=%x\n",
|
|
hwndDdeServer));
|
|
|
|
// Give the common window a map from classes to server windows
|
|
|
|
CMapUintPtr FAR *pmapClassToHwnd;
|
|
|
|
Assert (sizeof(LONG)==sizeof (CMapUintPtr FAR*));
|
|
|
|
if ((pmapClassToHwnd = new CMapUintPtr) == NULL)
|
|
{
|
|
intrDebugOut((DEB_ERROR,"pmapClassToHwnd != NULL\n"));
|
|
hr = E_OUTOFMEMORY;
|
|
goto errRtn;
|
|
}
|
|
|
|
SetWindowLong (hwndDdeServer, 0, (LONG)pmapClassToHwnd);
|
|
//
|
|
// Set the pointer to the server in the TLS data
|
|
//
|
|
|
|
tls->hwndDdeServer = hwndDdeServer;
|
|
|
|
exitRtn:
|
|
|
|
intrDebugOut((DEB_ITRACE,"%p _OUT CreateCommonDocWindow (%x)\n",0,hr));
|
|
|
|
return(hr);
|
|
|
|
//
|
|
// In the error case, if the hwnDdeServer != NULL, then destroy it
|
|
//
|
|
errRtn:
|
|
if (hwndDdeServer != NULL)
|
|
{
|
|
SSDestroyWindow(hwndDdeServer);
|
|
}
|
|
|
|
goto exitRtn;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DestroyCommonDdeWindow
|
|
//
|
|
// Synopsis: Destroys the common DDE Server window
|
|
//
|
|
// Effects:
|
|
//
|
|
// Arguments: [void] --
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Signals:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// Algorithm:
|
|
//
|
|
// History: 5-27-94 kevinro Commented/cleaned
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
INTERNAL DestroyCommonDdeWindow
|
|
(void)
|
|
{
|
|
intrDebugOut((DEB_ITRACE,"%p _IN DestroyCommonDdeWindow\n",0));
|
|
|
|
HRESULT hr = S_OK;
|
|
COleTls tls;
|
|
|
|
HWND hwndDdeServer = tls->hwndDdeServer;
|
|
|
|
if (hwndDdeServer == NULL)
|
|
{
|
|
goto errRtn;
|
|
}
|
|
|
|
|
|
//
|
|
// The map from the common window got deleted in DdeCommonWndProc
|
|
//
|
|
|
|
//
|
|
// If destroying this window fails, there isn't much we can
|
|
// do about it.
|
|
//
|
|
if(!SSDestroyWindow (hwndDdeServer))
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
|
|
// NULL out the TLS
|
|
tls->hwndDdeServer = NULL;
|
|
|
|
errRtn:
|
|
intrDebugOut((DEB_ITRACE,"%p _OUT DestroyCommonDdeWindow %x\n",0,hr));
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: IsRunningInThisTask
|
|
//
|
|
// Synopsis: Determine if the given file is running in the current task
|
|
//
|
|
// Effects: Calls a special function in the ROT to determine if the
|
|
// file szFile is loaded as a moniker in the current task
|
|
//
|
|
// Arguments: [szFile] -- Filename
|
|
// [pf] -- Points to a BOOL. Returned TRUE if running
|
|
//
|
|
// History: 6-29-94 kevinro Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
INTERNAL IsRunningInThisTask(LPOLESTR szFileIn,BOOL FAR* pf) // out parm
|
|
{
|
|
HRESULT hresult;
|
|
|
|
intrDebugOut((DEB_DDE_INIT,
|
|
"IsRunninginThisTask szFileIn=%ws\n",
|
|
WIDECHECK(szFileIn)));
|
|
|
|
//
|
|
// The RunningObjectTable always stores LONG filenames, therefore we
|
|
// need to convert this name to the long name for the lookup.
|
|
//
|
|
|
|
WCHAR szFile[MAX_PATH];
|
|
if ((lstrlenW(szFileIn) == 0) || (GetLongPathNameW(szFileIn,szFile,MAX_PATH) == 0))
|
|
{
|
|
//
|
|
// Unable to determine a long path for this object. Use whatever we were
|
|
// handed.
|
|
//
|
|
intrDebugOut((DEB_DDE_INIT,"No conversion to long path. Copy szFileIn\n"));
|
|
lstrcpyW(szFile,szFileIn);
|
|
}
|
|
|
|
intrDebugOut((DEB_DDE_INIT,"Long file szFile(%ws)\n",szFile));
|
|
|
|
hresult = GetLocalRunningObjectForDde(szFile,NULL);
|
|
|
|
*pf = (hresult == S_OK);
|
|
|
|
intrDebugOut((DEB_DDE_INIT,
|
|
"IsRunninginThisTask szFile=%ws returns %s\n",
|
|
WIDECHECK(szFile),
|
|
*pf?"TRUE":"FALSE"));
|
|
return NOERROR;
|
|
}
|
|
|