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.
649 lines
17 KiB
649 lines
17 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1995.
|
|
//
|
|
// File: transmgr.cxx
|
|
//
|
|
// Contents:
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 12-02-95 JohannP (Johann Posch) Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#include <trans.h>
|
|
|
|
PerfDbgTag(tagCTransMgr, "Urlmon", "Log CTransactionMgr", DEB_TRANSMGR);
|
|
DbgTag(tagCTransMgrErr, "Urlmon", "Log CTransMgr Errors", DEB_TRANSMGR|DEB_ERROR);
|
|
|
|
extern HINSTANCE g_hInst;
|
|
LRESULT CALLBACK TransactionWndProc(HWND hWnd, UINT msg,WPARAM wParam, LPARAM lParam);
|
|
|
|
#define szURLMonClassName "URL Moniker Notification Window"
|
|
static BOOL g_fWndClassRegistered = FALSE;
|
|
CMutexSem g_mxsTransMgr;
|
|
|
|
URLMON_TS* GetTS(DWORD);
|
|
HRESULT AddTSToList(URLMON_TS*);
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetThreadTransactionMgr
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [fCreate] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-14-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CTransactionMgr * GetThreadTransactionMgr(BOOL fCreate)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANSMGR,
|
|
Pointer,
|
|
"GetThreadTransactionMgr",
|
|
"%B",
|
|
fCreate
|
|
));
|
|
|
|
PerfDbgLog(tagCTransMgr, NULL, "+GetThreadTransactionMgr");
|
|
// only one thread should be here
|
|
CLock lck(g_mxsMedia);
|
|
|
|
HRESULT hr = NOERROR;
|
|
CTransactionMgr *pCTMgr = NULL;
|
|
|
|
CUrlMkTls tls(hr);
|
|
if (hr == NOERROR)
|
|
{
|
|
pCTMgr = tls->pCTransMgr;
|
|
|
|
if ((pCTMgr == NULL) && fCreate)
|
|
{
|
|
// the transaction mgr has an refcount of 1
|
|
tls->pCTransMgr = pCTMgr = new CTransactionMgr;
|
|
}
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransMgr, NULL, "-GetThreadTransactionMgr (pCTMgr:%lx)", pCTMgr);
|
|
|
|
DEBUG_LEAVE(pCTMgr);
|
|
return pCTMgr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetTransactionMgr
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [fCreate] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-06-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CTransactionMgr * GetTransactionMgr(BOOL fCreate)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANSMGR,
|
|
Pointer,
|
|
"GetTransactionMgr",
|
|
"%B",
|
|
fCreate
|
|
));
|
|
|
|
CTransactionMgr* pCTransMgr = GetThreadTransactionMgr(fCreate);
|
|
|
|
DEBUG_LEAVE(pCTransMgr);
|
|
return pCTransMgr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RegisterUrlMkWndClass
|
|
//
|
|
// Synopsis: register the Url Moniker window class on demand
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns: return FALSE if class could not be registered
|
|
//
|
|
// History: 12-02-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL RegisterUrlMkWndClass()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANSMGR,
|
|
Bool,
|
|
"RegisterUrlMkWndClass",
|
|
NULL
|
|
));
|
|
|
|
// only one thread should be here
|
|
CLock lck(g_mxsMedia);
|
|
|
|
if (g_fWndClassRegistered == FALSE)
|
|
{
|
|
// else register the window class
|
|
WNDCLASS wndclass;
|
|
|
|
wndclass.style = 0;
|
|
wndclass.lpfnWndProc = &TransactionWndProc;
|
|
wndclass.cbClsExtra = 0;
|
|
wndclass.cbWndExtra = 0;
|
|
wndclass.hInstance = g_hInst;
|
|
wndclass.hIcon = NULL;
|
|
wndclass.hCursor = NULL;;
|
|
wndclass.hbrBackground = (HBRUSH)NULL;
|
|
wndclass.lpszMenuName = NULL;
|
|
wndclass.lpszClassName = szURLMonClassName;
|
|
|
|
// Register the window class
|
|
if (!RegisterClass(&wndclass))
|
|
{
|
|
DWORD dwLastError = GetLastError();
|
|
|
|
if(dwLastError == ERROR_CLASS_ALREADY_EXISTS)
|
|
{
|
|
g_fWndClassRegistered = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DEBUG_PRINT(TRANSMGR, ERROR, ("RegisterUrlMkWndClass(): RegisterClass failed, GetLastError: %ld\n", dwLastError));
|
|
TransAssert(FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_fWndClassRegistered = TRUE;
|
|
}
|
|
}
|
|
|
|
DEBUG_LEAVE(g_fWndClassRegistered);
|
|
return g_fWndClassRegistered;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: UnregisterUrlMkWndClass
|
|
//
|
|
// Synopsis: unregisters the hidden windows class
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 10-16-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes: called during process detach
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL UnregisterUrlMkWndClass()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANSMGR,
|
|
Bool,
|
|
"UnregisterUrlMkWndClass",
|
|
NULL
|
|
));
|
|
|
|
if (g_fWndClassRegistered == TRUE)
|
|
{
|
|
// Register the window class
|
|
if (UnregisterClass(szURLMonClassName,g_hInst))
|
|
{
|
|
g_fWndClassRegistered = FALSE;
|
|
}
|
|
else
|
|
{
|
|
DEBUG_PRINT(TRANSMGR, ERROR, ("UnregisterUrlMkWndClass(): UnregisterClass failed, GetLastError: %ld\n", GetLastError()));
|
|
}
|
|
}
|
|
|
|
DEBUG_LEAVE(g_fWndClassRegistered);
|
|
return g_fWndClassRegistered;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetThreadNotificationWnd
|
|
//
|
|
// Synopsis: return the notification for the current
|
|
// the window is created if
|
|
//
|
|
// Arguments: [fCreate] -- TRUE if the window should be created
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-02-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#ifndef HWND_MESSAGE
|
|
#define HWND_MESSAGE ((HWND)-3)
|
|
#endif
|
|
|
|
extern BOOL g_bNT5OrGreater;
|
|
|
|
HWND GetThreadNotificationWnd(BOOL fCreate)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANSMGR,
|
|
Dword,
|
|
"GetThreadNotificationWnd",
|
|
"%B",
|
|
fCreate
|
|
));
|
|
|
|
HRESULT hr = NOERROR;
|
|
HWND hwnd = NULL;
|
|
|
|
DWORD tid = GetCurrentThreadId();
|
|
URLMON_TS* ts = NULL;
|
|
|
|
ts = GetTS(tid);
|
|
if( ts )
|
|
{
|
|
hwnd = ts->_hwndNotify;
|
|
TransAssert((hwnd != NULL && "TS Corrupted!"));
|
|
}
|
|
else
|
|
{
|
|
ts = new URLMON_TS;
|
|
|
|
if( ts )
|
|
{
|
|
if ( fCreate
|
|
&& (hwnd == NULL)
|
|
&& RegisterUrlMkWndClass() )
|
|
{
|
|
hwnd = CreateWindowEx(0, szURLMonClassName, NULL,
|
|
0, 0, 0, 0, 0,
|
|
g_bNT5OrGreater ? HWND_MESSAGE : NULL,
|
|
NULL, g_hInst, NULL);
|
|
|
|
TransAssert((hwnd != NULL && "can't create Notify window"));
|
|
if (hwnd)
|
|
{
|
|
ts->_dwTID = tid;
|
|
ts->_hwndNotify = hwnd;
|
|
|
|
AddTSToList(ts);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delete ts;
|
|
}
|
|
}
|
|
|
|
}
|
|
/**************************************************************************
|
|
CUrlMkTls tls(hr);
|
|
|
|
if (hr == NOERROR)
|
|
{
|
|
hwnd = tls->hwndUrlMkNotify;
|
|
|
|
if ( fCreate
|
|
&& (hwnd == NULL)
|
|
&& RegisterUrlMkWndClass() )
|
|
{
|
|
hwnd = CreateWindowEx(0, szURLMonClassName, NULL,
|
|
0, 0, 0, 0, 0, NULL, NULL, g_hInst, NULL);
|
|
|
|
TransAssert((hwnd != NULL && "GetNotificationWnd: could not create window"));
|
|
if (hwnd)
|
|
{
|
|
tls->hwndUrlMkNotify = hwnd;
|
|
char achProgname[256];
|
|
achProgname[0] = '\0';
|
|
GetModuleFileNameA(NULL, achProgname, sizeof(achProgname));
|
|
}
|
|
}
|
|
}
|
|
***************************************************************************/
|
|
|
|
DEBUG_LEAVE(hwnd);
|
|
return hwnd;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransactionMgr::CTransactionMgr
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-14-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CTransactionMgr::CTransactionMgr() : CLifePtr()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANSMGR,
|
|
None,
|
|
"CTransactionMgr::CTransactionMgr",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
_pCTransFirst = NULL;
|
|
_pCTransLast = NULL;
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransactionMgr::~CTransactionMgr
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-14-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CTransactionMgr::~CTransactionMgr()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANSMGR,
|
|
None,
|
|
"CTransactionMgr::~CTransactionMgr",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
// The list should be empty by the time it gets destroyed
|
|
if (_pCTransFirst)
|
|
{
|
|
DbgLog1(tagCTransMgr, this, "CTransactionMgr::~CTransactionMgr (list not empty:%lx)", _pCTransFirst);
|
|
}
|
|
|
|
//TransAssert(( _pCTransFirst == NULL ));
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransactionMgr::AddTransaction
|
|
//
|
|
// Synopsis: Add an internet transaction to the linked list.
|
|
//
|
|
// Arguments: [pCTrans] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-12-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransactionMgr::AddTransaction(CTransaction *pCTrans)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANSMGR,
|
|
Hresult,
|
|
"CTransactionMgr::AddTransaction",
|
|
"this=%#x, %#x",
|
|
this, pCTrans
|
|
));
|
|
|
|
PerfDbgLog(tagCTransMgr, this, "+CTransMgr::AddTransaction");
|
|
TransAssert((pCTrans != NULL));
|
|
|
|
|
|
TransAssert((pCTrans->GetNextTransaction() == NULL));
|
|
|
|
pCTrans->SetNextTransaction(_pCTransFirst);
|
|
_pCTransFirst = pCTrans;
|
|
AddRef();
|
|
|
|
PerfDbgLog1(tagCTransMgr, this, "-CTransMgr::AddTransaction(hr:%lx)", NOERROR);
|
|
|
|
DEBUG_LEAVE(NOERROR);
|
|
return NOERROR;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransactionMgr::RemoveTransaction
|
|
//
|
|
// Synopsis: Removes a transaction from the linked list. If the transaction
|
|
// cannot be found, E_FAIL is returned.
|
|
//
|
|
// Arguments: [pCTrans] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-12-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransactionMgr::RemoveTransaction(CTransaction *pCTrans)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANSMGR,
|
|
Hresult,
|
|
"CTransactionMgr::RemoveTransaction",
|
|
"this=%#x, %#x",
|
|
this, pCTrans
|
|
));
|
|
|
|
PerfDbgLog(tagCTransMgr, this, "+CTransMgr::RemoveTransaction");
|
|
CLock lck(g_mxsTransMgr);
|
|
CTransaction *pCTransPrev = NULL;
|
|
CTransaction *pCTransTmp;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
TransAssert((pCTrans != NULL));
|
|
|
|
|
|
pCTransTmp = _pCTransFirst;
|
|
|
|
TransAssert((pCTransTmp != NULL));
|
|
|
|
// Search all the nodes in the linked list
|
|
if (_pCTransFirst == pCTrans)
|
|
{
|
|
_pCTransFirst = _pCTransFirst->GetNextTransaction();
|
|
hr = NOERROR;
|
|
Release();
|
|
}
|
|
else while (pCTransTmp != NULL)
|
|
{
|
|
// If a match is found
|
|
if (pCTransTmp == pCTrans)
|
|
{
|
|
// Remove it from the linked list
|
|
if (pCTransPrev == NULL)
|
|
{
|
|
_pCTransFirst = pCTrans->GetNextTransaction();
|
|
}
|
|
else
|
|
{
|
|
pCTransPrev->SetNextTransaction(pCTrans->GetNextTransaction());
|
|
}
|
|
|
|
hr = NOERROR;
|
|
Release();
|
|
}
|
|
|
|
pCTransPrev = pCTransTmp;
|
|
pCTransTmp = pCTransTmp->GetNextTransaction();
|
|
}
|
|
|
|
TransAssert((hr == NOERROR));
|
|
|
|
PerfDbgLog1(tagCTransMgr, this, "-CTransMgr::RemoveTransaction (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetTransactionObjects
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pBndCtx] --
|
|
// [wzUrl] --
|
|
// [pUnkOuter] --
|
|
// [ppUnk] --
|
|
// [ppCTrans] --
|
|
// [dwOption] --
|
|
// [ppCTranSData] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 4-12-1997 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT GetTransactionObjects(LPBC pBndCtx, LPCWSTR wzUrl, IUnknown *pUnkOuter, IUnknown **ppUnk,
|
|
IOInetProtocol **ppCTrans, DWORD dwOption, CTransData **ppCTransData)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANSMGR,
|
|
Hresult,
|
|
"GetTransactionObjects",
|
|
"%#x, %.80wq, %#x, %#x, %#x, %#x, %#x",
|
|
pBndCtx, wzUrl, pUnkOuter, ppUnk, ppCTrans, dwOption, ppCTransData
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
PerfDbgLog(tagCTransMgr, NULL, "+GetTransactionObjects");
|
|
TransAssert((ppCTrans != NULL));
|
|
CTransaction *pCTransTmp = NULL;
|
|
|
|
BOOL fFound = FALSE;
|
|
CLock lck(g_mxsTransMgr);
|
|
|
|
CBindCtx *pCBndCtx = NULL;
|
|
|
|
if (pBndCtx)
|
|
{
|
|
hr = pBndCtx->QueryInterface(IID_IAsyncBindCtx, (void **) &pCBndCtx);
|
|
|
|
if (hr == NOERROR)
|
|
{
|
|
TransAssert((pCBndCtx));
|
|
hr = pCBndCtx->GetTransactionObjects(&pCTransTmp, ppCTransData);
|
|
if (hr == NOERROR)
|
|
{
|
|
TransAssert((pCTransTmp));
|
|
|
|
if (!pCTransTmp->IsApartmentThread())
|
|
{
|
|
pCBndCtx->SetTransactionObject(NULL);
|
|
}
|
|
|
|
fFound = TRUE;
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
|
|
if (hr != S_FALSE && hr != NOERROR)
|
|
{
|
|
CBinding *pCBdgBindToObject = NULL;
|
|
hr = pBndCtx->GetObjectParam(SZ_BINDING, (IUnknown **)&pCBdgBindToObject);
|
|
|
|
if (pCBdgBindToObject)
|
|
{
|
|
pCTransTmp = (CTransaction *) pCBdgBindToObject->GetOInetBinding();
|
|
fFound = pCTransTmp ? true : false;
|
|
pCTransTmp->AddRef();
|
|
pCBdgBindToObject->Release();
|
|
DbgLog1(tagCTransMgr, NULL, "=== CTransMgr::GetTransaction Found Transaction:%lx", pCTransTmp);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (!fFound)
|
|
{
|
|
CTransactionMgr *pCTransMgr = GetThreadTransactionMgr();
|
|
|
|
if (!pCTransMgr)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
// create a new transaction add it to the list
|
|
hr = CTransaction::Create(pCBndCtx, dwOption, 0, 0, &pCTransTmp);
|
|
if (hr == NOERROR)
|
|
{
|
|
hr = pCTransTmp->QueryInterface(IID_IOInetProtocol, (void **) ppCTrans);
|
|
|
|
if (hr == NOERROR)
|
|
{
|
|
pCTransTmp->Release();
|
|
pCTransMgr->AddTransaction(pCTransTmp);
|
|
}
|
|
|
|
if (!pCBndCtx && pBndCtx)
|
|
{
|
|
pBndCtx->QueryInterface(IID_IAsyncBindCtx, (void **) &pCBndCtx);
|
|
}
|
|
if (pCBndCtx)
|
|
{
|
|
pCBndCtx->SetTransactionObject(pCTransTmp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (pCTransTmp)
|
|
{
|
|
DbgLog1(tagCTransMgr, NULL, "GetTransactionObjects Found existing transaction(%lx)", pCTransTmp);
|
|
// return false to indicate found existing transaction
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
if (pCBndCtx)
|
|
{
|
|
pCBndCtx->Release();
|
|
}
|
|
|
|
*ppCTrans = pCTransTmp;
|
|
|
|
if (*ppCTrans && ppCTransData && *ppCTransData)
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
if( hr == S_FALSE && ppCTransData && !*ppCTransData )
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
PerfDbgLog2(tagCTransMgr, NULL, "-API GetTransactionObjects (pCTrans:%lx; hr:%lx)", pCTransTmp, hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
|