Leaked source code of windows server 2003
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.
 
 
 
 
 
 

504 lines
14 KiB

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
/**********************************************************************/
/*
ccompont.cpp
base classes for IComponent and IComponentData
FILE HISTORY:
*/
#include "stdafx.h"
#include "util.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
TFSCORE_API(HRESULT)
InitWatermarkInfo
(
HINSTANCE hInstance,
LPWATERMARKINFO pWatermarkInfo,
UINT uIDHeader,
UINT uIDWatermark,
HPALETTE hPalette,
BOOL bStretch
)
{
pWatermarkInfo->hHeader = ::LoadBitmap(hInstance, MAKEINTRESOURCE(uIDHeader));
if (pWatermarkInfo->hHeader == NULL)
return E_FAIL;
pWatermarkInfo->hWatermark = ::LoadBitmap(hInstance, MAKEINTRESOURCE(uIDWatermark));
if (pWatermarkInfo->hWatermark == NULL)
return E_FAIL;
pWatermarkInfo->hPalette = hPalette;
pWatermarkInfo->bStretch = bStretch;
return S_OK;
}
TFSCORE_API(HRESULT)
ResetWatermarkInfo(LPWATERMARKINFO pWatermarkInfo)
{
if(pWatermarkInfo->hHeader)
{
DeleteObject(pWatermarkInfo->hHeader);
pWatermarkInfo->hHeader = NULL;
}
if(pWatermarkInfo->hWatermark)
{
DeleteObject(pWatermarkInfo->hWatermark);
pWatermarkInfo->hWatermark = NULL;
}
return S_OK;
}
/*!--------------------------------------------------------------------------
InterfaceUtilities::SetI
Encapsulates the common Release/Assign/AddRef sequence.
Handles null ptrs.
Author: GaryBu
---------------------------------------------------------------------------*/
TFSCORE_API(void) SetI(IUnknown * volatile *ppunkL, IUnknown *punkR)
{
if (*ppunkL)
{
IUnknown *punkRel = *ppunkL;
*ppunkL = 0;
punkRel->Release();
}
*ppunkL = punkR;
if (punkR)
punkR->AddRef();
}
/*!--------------------------------------------------------------------------
InterfaceUtilities::ReleaseI
Release interface, handles null interface pointer.
Use Set(&pFoo, 0) if you want to set interface pointer to zero.
Author: GaryBu
---------------------------------------------------------------------------*/
TFSCORE_API(void) ReleaseI(IUnknown *punk)
{
#if 0
__try
#endif
{
if (punk)
{
if (IsBadReadPtr(punk,sizeof(void *)))
{
AssertSz(FALSE,"Bad Punk");
return;
}
if (IsBadReadPtr(*((LPVOID FAR *) punk),sizeof(void *) * 3))
{
AssertSz(FALSE, "Bad Vtable");
return;
}
// if (IsBadCodePtr((FARPROC) punk->Release))
// {
// AssertSz(fFalse, "Bad Release Address");
// return;
// }
punk->Release();
}
}
#if 0
__except(1)
{
Trace0("Exception ignored in ReleaseI()\n");
}
#endif
}
TFSCORE_API(HRESULT) HrQueryInterface(IUnknown *punk, REFIID iid, LPVOID *ppv)
{
HRESULT hr;
#ifdef DEBUG
if (IsBadReadPtr(punk,sizeof(void *)))
{
AssertSz(FALSE,"CRASHING BUG! Bad Punk in QueryInterface");
return ResultFromScode(E_NOINTERFACE);
}
if (IsBadReadPtr(*((LPVOID FAR *) punk),sizeof(void *) * 3))
{
AssertSz(FALSE, "CRASHING BUG! Bad Vtable in QueryInterface");
return ResultFromScode(E_NOINTERFACE);
}
#endif
IfDebug(*ppv = (void*)0xCCCCCCCC;)
hr = punk->QueryInterface(iid, ppv);
if (FHrFailed(hr))
{
*ppv = 0;
}
return hr;
}
TFSCORE_API(HRESULT) LoadAndAddMenuItem
(
IContextMenuCallback* pIContextMenuCallback,
LPCTSTR pszMenuString, // has text & status text separated by '\n'
LONG lCommandID,
LONG lInsertionPointID,
LONG fFlags,
LPCTSTR pszLangIndStr
)
{
Assert( pIContextMenuCallback != NULL );
// load the resource
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString strText(pszMenuString);
CString strStatusText;
if (!(fFlags & MF_SEPARATOR))
{
Assert( !strText.IsEmpty() );
// split the resource into the menu text and status text
int iSeparator = strText.Find(_T('\n'));
if (0 > iSeparator)
{
Panic0("Could not find separator between menu text and status text");
strStatusText = strText;
}
else
{
strStatusText = strText.Right( strText.GetLength()-(iSeparator+1) );
strText = strText.Left( iSeparator );
}
}
// add the menu item
USES_CONVERSION;
HRESULT hr = S_OK;
BOOL bAdded = FALSE;
// if language independent string is specified, then try to use IContextMenuCallback2
if(pszLangIndStr)
{
CONTEXTMENUITEM2 contextmenuitem;
IContextMenuCallback2* pIContextMenuCallback2 = NULL;
hr = pIContextMenuCallback->QueryInterface(IID_IContextMenuCallback2, (void**)&pIContextMenuCallback2);
if(hr == S_OK && pIContextMenuCallback2 != NULL)
{
::ZeroMemory( &contextmenuitem, sizeof(contextmenuitem) );
contextmenuitem.strName = T2OLE(const_cast<LPTSTR>((LPCWSTR)strText));
contextmenuitem.strStatusBarText = T2OLE(const_cast<LPTSTR>((LPCWSTR)strStatusText));
contextmenuitem.lCommandID = lCommandID;
contextmenuitem.lInsertionPointID = lInsertionPointID;
contextmenuitem.fFlags = fFlags;
contextmenuitem.fSpecialFlags = ((fFlags & MF_POPUP) ? CCM_SPECIAL_SUBMENU : 0L);
contextmenuitem.fSpecialFlags |= ((fFlags & MF_SEPARATOR) ? CCM_SPECIAL_SEPARATOR : 0L);
contextmenuitem.strLanguageIndependentName = T2OLE(const_cast<LPTSTR>((LPCWSTR)pszLangIndStr));
hr = pIContextMenuCallback2->AddItem( &contextmenuitem );
if( hr == S_OK)
bAdded = TRUE;
pIContextMenuCallback2->Release();
pIContextMenuCallback2 = NULL;
}
}
// if not added above for any reason, we try to use the IContextMenuCallback
if (!bAdded)
{
CONTEXTMENUITEM contextmenuitem;
::ZeroMemory( &contextmenuitem, sizeof(contextmenuitem) );
contextmenuitem.strName = T2OLE(const_cast<LPTSTR>((LPCWSTR)strText));
contextmenuitem.strStatusBarText = T2OLE(const_cast<LPTSTR>((LPCWSTR)strStatusText));
contextmenuitem.lCommandID = lCommandID;
contextmenuitem.lInsertionPointID = lInsertionPointID;
contextmenuitem.fFlags = fFlags;
contextmenuitem.fSpecialFlags = ((fFlags & MF_POPUP) ? CCM_SPECIAL_SUBMENU : 0L);
contextmenuitem.fSpecialFlags |= ((fFlags & MF_SEPARATOR) ? CCM_SPECIAL_SEPARATOR : 0L);
hr = pIContextMenuCallback->AddItem( &contextmenuitem );
}
Assert(hr == S_OK);
return hr;
}
/*---------------------------------------------------------------------------
CHiddenWnd implementation
---------------------------------------------------------------------------*/
DEBUG_DECLARE_INSTANCE_COUNTER(CHiddenWnd);
BEGIN_MESSAGE_MAP( CHiddenWnd, CWnd )
ON_MESSAGE(WM_HIDDENWND_REGISTER, OnNotifyRegister)
END_MESSAGE_MAP( )
/*!--------------------------------------------------------------------------
CHiddenWnd::Create
-
Author: KennT
---------------------------------------------------------------------------*/
BOOL CHiddenWnd::Create()
{
CString s_szHiddenWndClass = AfxRegisterWndClass(
0x0, //UINT nClassStyle,
NULL, //HCURSOR hCursor,
NULL, //HBRUSH hbrBackground,
NULL //HICON hIcon
);
// Initialize our bit mask to 0
::ZeroMemory(&m_bitMask, sizeof(m_bitMask));
// Reserve position 0. This means that
// we can use from WM_USER to WM_USER+15 for our own purposes.
SetBitMask(m_bitMask, 0);
m_iLastObjectIdSet = 1;
return CreateEx(
0x0, //DWORD dwExStyle,
s_szHiddenWndClass, //LPCTSTR lpszClassName,
NULL, //LPCTSTR lpszWindowName,
0x0, //DWORD dwStyle,
0, //int x,
0, //int y,
0, //int nWidth,
0, //int nHeight,
NULL, //HWND hwndParent,
NULL, //HMENU nIDorHMenu,
NULL //LPVOID lpParam = NULL
);
}
/*!--------------------------------------------------------------------------
CHiddenWnd::WindowProc
-
Author: KennT
---------------------------------------------------------------------------*/
LRESULT CHiddenWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT lReturn = 0;
if ((message >= (WM_USER+16)) && (message < (WM_USER+(HIDDENWND_MAXTHREADS*16))))
{
// Ok, this is one of our special messages
UINT uObjectId = WM_TO_OBJECTID(message);
UINT uMsgId = WM_TO_MSGID(message);
// look up the object id in our list of registered users
if (FIsIdRegistered(uObjectId))
{
// forward the message down to the right window
if (uMsgId == WM_HIDDENWND_INDEX_HAVEDATA)
lReturn = OnNotifyHaveData(wParam, lParam);
else if (uMsgId == WM_HIDDENWND_INDEX_ERROR)
lReturn = OnNotifyError(wParam, lParam);
else if (uMsgId == WM_HIDDENWND_INDEX_EXITING)
lReturn = OnNotifyExiting(wParam, lParam);
#ifdef DEBUG
else
{
Panic1("Unknown message %d", uMsgId);
}
#endif
}
else if (uObjectId != 0)
{
// If we get a message that is not registered, go into
// our message queue and remove any other messages that
// have the same id. This will reduce accidents that
// occur because different threads were assigned the
// same id.
MSG msg;
Assert(GetSafeHwnd());
while(::PeekMessage(&msg,
GetSafeHwnd(),
OBJECTID_TO_WM(uObjectId),
OBJECTID_TO_WM(uObjectId)+WM_HIDDENWND_INDEX_MAX,
PM_REMOVE))
;
// Trace1("Ignoring message: 0x%08x, removing other msgs\n", message);
}
// If the object is not registered, eat up the message
return lReturn;
}
return CWnd::WindowProc(message, wParam, lParam);
}
/*!--------------------------------------------------------------------------
CHiddenWnd::FIsIdRegistered
-
Author: KennT
---------------------------------------------------------------------------*/
BOOL CHiddenWnd::FIsIdRegistered(UINT uObjectId)
{
Assert(uObjectId > 0);
Assert(uObjectId < HIDDENWND_MAXTHREADS);
// 0 is not allowed as an object id
return (uObjectId != 0) && !!(IsBitMaskSet(m_bitMask, uObjectId));
}
/*!--------------------------------------------------------------------------
CHiddenWnd::OnNotifyRegister
If we fail to find an empty slot, return 0.
Author: KennT
---------------------------------------------------------------------------*/
LONG CHiddenWnd::OnNotifyRegister(WPARAM wParam, LPARAM lParam)
{
LONG lReturn = 0;
// Look for a valid hole in our mask
// The point of using the m_iLastObjectIdSet is to avoid the
// problem of reusing ids. This doesn't totally eliminate the
// problem but it should reduce the likelihood to practically 0.
// That is, unless someone actually runs a snapin that utilizes
// 512 threads!
if (wParam)
{
if (((m_iLastObjectIdSet+1) < HIDDENWND_MAXTHREADS) &&
!IsBitMaskSet(m_bitMask, m_iLastObjectIdSet))
{
SetBitMask(m_bitMask, m_iLastObjectIdSet);
lReturn = OBJECTID_TO_WM(m_iLastObjectIdSet);
m_iLastObjectIdSet++;
}
else
{
// do this the painful way
Assert(IsBitMaskSet(m_bitMask, 0));
for (int iLoop=0; iLoop<2; iLoop++)
{
for (int i=m_iLastObjectIdSet; i<HIDDENWND_MAXTHREADS; i++)
{
if (!IsBitMaskSet(m_bitMask, i))
{
m_iLastObjectIdSet = i;
SetBitMask(m_bitMask, m_iLastObjectIdSet);
lReturn = OBJECTID_TO_WM(i);
break;
}
}
if (lReturn || (m_iLastObjectIdSet == 1))
break;
// restart the loop from the beginning
m_iLastObjectIdSet = 1;
}
}
}
else
{
LONG_PTR uObjectId = WM_TO_OBJECTID(lParam);
Assert(uObjectId > 0);
Assert(IsBitMaskSet(m_bitMask, uObjectId));
ClearBitMask(m_bitMask, uObjectId);
}
return lReturn;
}
/*!--------------------------------------------------------------------------
CHiddenWnd::OnNotifyHaveData
-
Author: KennT
---------------------------------------------------------------------------*/
afx_msg LONG CHiddenWnd::OnNotifyHaveData(WPARAM wParam, LPARAM lParam)
{
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
//Trace0("CHiddenWnd::OnNotifyHaveData()\n");
ITFSThreadHandler *phandler = reinterpret_cast<ITFSThreadHandler*>(wParam);
Assert(phandler);
// If there is an error, we can't do anything
phandler->OnNotifyHaveData(lParam);
}
COM_PROTECT_CATCH
return 0;
}
/*!--------------------------------------------------------------------------
CHiddenWnd::OnNotifyError
-
Author: KennT
---------------------------------------------------------------------------*/
afx_msg LONG CHiddenWnd::OnNotifyError(WPARAM wParam, LPARAM lParam)
{
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
// Trace0("CHiddenWnd::OnNotifyError()\n");
ITFSThreadHandler *phandler = reinterpret_cast<ITFSThreadHandler*>(wParam);
Assert(phandler);
// If there is an error, we can't do anything
phandler->OnNotifyError(lParam);
}
COM_PROTECT_CATCH
return 0;
}
/*!--------------------------------------------------------------------------
CHiddenWnd::OnNotifyExiting
-
Author: KennT
---------------------------------------------------------------------------*/
afx_msg LONG CHiddenWnd::OnNotifyExiting(WPARAM wParam, LPARAM lParam)
{
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
// Trace0("CHiddenWnd::OnNotifyExiting()\n");
ITFSThreadHandler *phandler = reinterpret_cast<ITFSThreadHandler*>(wParam);
Assert(phandler);
// If there is an error, we can't do anything
phandler->OnNotifyExiting(lParam);
}
COM_PROTECT_CATCH
return 0;
}