Windows2003-3790/inetcore/urlmon/trans/transmgr.cxx
2020-09-30 16:53:55 +02:00

650 lines
17 KiB
C++

//+---------------------------------------------------------------------------
//
// 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;
}