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.
 
 
 
 
 
 

520 lines
21 KiB

/****************************************************************************/
// cdapi.cpp
//
// Component Decoupler API functions
// Copyright (C) 1997-1999 Microsoft Corporation
/****************************************************************************/
#include <adcg.h>
extern "C" {
#define TRC_GROUP TRC_GROUP_CORE
#define TRC_FILE "cdapi"
#include <atrcapi.h>
}
#include "autil.h"
#include "cd.h"
#include "wui.h"
CCD::CCD(CObjs* objs)
{
_pClientObjects = objs;
_fCDInitComplete = FALSE;
/************************************************************************/
/* Initialize the global data. */
/************************************************************************/
DC_MEMSET(&_CD, 0, sizeof(_CD));
}
CCD::~CCD()
{
}
/****************************************************************************/
/* Name: CD_Init */
/* */
/* Purpose: Component Decoupler initialization function */
/****************************************************************************/
DCVOID DCAPI CCD::CD_Init(DCVOID)
{
WNDCLASS wc;
WNDCLASS tmpWndClass;
DC_BEGIN_FN("CD_Init");
TRC_ASSERT(_pClientObjects, (TB,_T("_pClientObjects is NULL")));
_pClientObjects->AddObjReference(CD_OBJECT_FLAG);
//Setup local object pointers
_pUt = _pClientObjects->_pUtObject;
_pUi = _pClientObjects->_pUiObject;
//
// Only register the class if not already registered (previous instance)
//
if(!GetClassInfo( _pUi->UI_GetInstanceHandle(), CD_WINDOW_CLASS, &tmpWndClass))
{
/************************************************************************/
/* Register the CD window class. */
/************************************************************************/
wc.style = 0;
wc.lpfnWndProc = CDStaticWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(void*);
wc.hInstance = _pUi->UI_GetInstanceHandle();
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = CD_WINDOW_CLASS;
if (!RegisterClass(&wc))
{
// $$$v-reddya. Hack to avoid bug #923.
TRC_ERR((TB, _T("Failed to register window class")));
//_pUi->UI_FatalError(DC_ERR_OUTOFMEMORY);
}
}
_fCDInitComplete = TRUE;
DC_END_FN();
}
/****************************************************************************/
/* Name: CD_Term */
/* */
/* Purpose: Component Decoupler termination function */
/****************************************************************************/
DCVOID DCAPI CCD::CD_Term(DCVOID)
{
DC_BEGIN_FN("CD_Term");
if(_fCDInitComplete)
{
if (!UnregisterClass(CD_WINDOW_CLASS, _pUi->UI_GetInstanceHandle())) {
//Failure to unregister could happen if another instance is still running
//that's ok...unregistration will happen when the last instance exits.
TRC_ERR((TB, _T("Failed to unregister window class")));
}
_pClientObjects->ReleaseObjReference(CD_OBJECT_FLAG);
}
DC_END_FN();
}
/****************************************************************************/
/* Name: CD_RegisterComponent */
/* */
/* Purpose: Register a new component */
/* */
/* Params: IN component: component id */
/****************************************************************************/
HRESULT DCAPI CCD::CD_RegisterComponent(DCUINT component)
{
HRESULT hr = E_FAIL;
DC_BEGIN_FN("CD_RegisterComponent");
TRC_ASSERT((component <= CD_MAX_COMPONENT),
(TB, _T("Invalid component %u"), component));
TRC_ASSERT((_CD.hwnd[component] == NULL),
(TB, _T("Component %u already registered"), component));
/************************************************************************/
/* Create window for this component. */
/************************************************************************/
_CD.hwnd[component] = CreateWindow(
CD_WINDOW_CLASS, /* See RegisterClass() call */
NULL, /* Text for window title bar */
0, /* Window style */
0, /* Default horizontal position */
0, /* Default vertical position */
0, /* Width */
0, /* Height */
NULL, /* hwndParent - none */
NULL, /* hMenu - none */
_pUi->UI_GetInstanceHandle(),
this /* Window creation data */
);
if (_CD.hwnd[component] != NULL) {
hr = S_OK;
}
else {
hr = HRESULT_FROM_WIN32(GetLastError());
TRC_ERR((TB,_T("Failed to create window: 0x%x"),hr));
}
TRC_NRM((TB, _T("Component(%u) hwnd(%p)"), component, _CD.hwnd[component]));
DC_END_FN();
return hr;
} /* CD_RegisterComponent */
/****************************************************************************/
/* Name: CD_UnregisterComponent */
/* */
/* Purpose: Unregister component from CD */
/* */
/* Params: IN component: component ID */
/****************************************************************************/
HRESULT DCAPI CCD::CD_UnregisterComponent(DCUINT component)
{
HRESULT hr = E_FAIL;
DC_BEGIN_FN("CD_UnregisterComponent");
TRC_ASSERT((component <= CD_MAX_COMPONENT),
(TB, _T("Invalid component %u"), component));
/************************************************************************/
/* Destroy this component's window, if it exists. */
/************************************************************************/
if (_CD.hwnd[component] != NULL)
{
DestroyWindow(_CD.hwnd[component]);
_CD.hwnd[component] = NULL;
}
hr = S_OK;
DC_END_FN();
return hr;
} /* CD_UnregisterComponent */
// Note that we have several copies of very similar code below. This is
// to trade a bit of code size (easy to predict and cache) against
// 50%-predictable branches created by parameterizing sync/async, which are
// very CPU expensive on modern processors. Since notifications are often
// used in performance paths (send/receive data), this optimization is
// worthwhile.
/****************************************************************************/
/* Name: CD_DecoupleNotification */
/* */
/* Purpose: Call given function with specified data */
/* */
/* Params: IN component: target thread */
/* IN pInst target object instance pointer */
/* IN pNotificationFn: target function */
/* IN pData: pointer to data to pass: cannot be NULL */
/* IN dataLength: data length in bytes: cannot be zero */
/* */
/* Operation: Copy supplied data into data buffer and post message to */
/* corresponding component window. */
/****************************************************************************/
BOOL DCAPI CCD::CD_DecoupleNotification(
unsigned component,
PDCVOID pInst,
PCD_NOTIFICATION_FN pNotificationFn,
PDCVOID pData,
unsigned dataLength)
{
PCDTRANSFERBUFFER pTransferBuffer;
DC_BEGIN_FN("CD_DecoupleNotificationEx");
TRC_ASSERT(((dataLength <= CD_MAX_NOTIFICATION_DATA_SIZE) &&
(dataLength > 0 )),
(TB, _T("dataLength(%u) invalid"), dataLength));
TRC_ASSERT((component <= CD_MAX_COMPONENT),
(TB, _T("Invalid component %u"), component));
TRC_ASSERT((pNotificationFn != NULL),(TB, _T("Null pNotificationFn")));
TRC_ASSERT((pData != NULL),(TB, _T("Null pData")));
TRC_ASSERT((pInst != NULL),(TB, _T("Null pInst")));
// Check that the target component is still registered.
if (_CD.hwnd[component] != NULL) {
pTransferBuffer = CDAllocTransferBuffer(dataLength);
if(pTransferBuffer) {
pTransferBuffer->hdr.pNotificationFn = pNotificationFn;
pTransferBuffer->hdr.pInst = pInst;
DC_MEMCPY(pTransferBuffer->data, pData, dataLength);
TRC_NRM((TB, _T("Notify component %u (%p) of %u bytes of data"),
component, _CD.hwnd[component], dataLength));
TRC_DATA_DBG("notification data", pData, dataLength);
// For now, we only use async data notifications. If we
// need sync data notifications, copy this code to a new
// func and use the ifdef'd SendMessage.
if (!PostMessage(_CD.hwnd[component], CD_NOTIFICATION_MSG,
(WPARAM)dataLength, (LPARAM)pTransferBuffer)) {
_pUi->UI_FatalError(DC_ERR_POSTMESSAGEFAILED);
}
else {
return TRUE;
}
#ifdef DC_DEBUG
// Trace is before increment so that the point at which we're most
// likely to get pre-empted (TRC_GetBuffer) is before all references
// to the variable we're interested in.
TRC_NRM((TB, _T("Messages now pending: %ld"), _CD.pendingMessageCount + 1));
_pUt->UT_InterlockedIncrement(&_CD.pendingMessageCount);
#endif
}
else {
TRC_ERR((TB,_T(" CDAllocTransferBuffer returned NULL")));
}
}
else {
TRC_ERR((TB, _T("Null hwnd for component(%u)"), component));
}
DC_END_FN();
return FALSE;
} /* CD_DecoupleNotification */
/****************************************************************************/
/* Name: CD_DecoupleSyncDataNotification */
/* */
/* Purpose: Call given function with specified data */
/* */
/* Params: IN component: target thread */
/* IN pInst target object instance pointer */
/* IN pNotificationFn: target function */
/* IN pData: pointer to data to pass: cannot be NULL */
/* IN dataLength: data length in bytes: cannot be zero */
/* */
/* Operation: Copy supplied data into data buffer and post message to */
/* corresponding component window. */
/****************************************************************************/
BOOL DCAPI CCD::CD_DecoupleSyncDataNotification(
unsigned component,
PDCVOID pInst,
PCD_NOTIFICATION_FN pNotificationFn,
PDCVOID pData,
unsigned dataLength)
{
PCDTRANSFERBUFFER pTransferBuffer;
DC_BEGIN_FN("CD_DecoupleSyncDataNotification");
TRC_ASSERT(((dataLength <= CD_MAX_NOTIFICATION_DATA_SIZE) &&
(dataLength > 0 )),
(TB, _T("dataLength(%u) invalid"), dataLength));
TRC_ASSERT((component <= CD_MAX_COMPONENT),
(TB, _T("Invalid component %u"), component));
TRC_ASSERT((pNotificationFn != NULL),(TB, _T("Null pNotificationFn")));
TRC_ASSERT((pData != NULL),(TB, _T("Null pData")));
TRC_ASSERT((pInst != NULL),(TB, _T("Null pInst")));
// Check that the target component is still registered.
if (_CD.hwnd[component] != NULL) {
pTransferBuffer = CDAllocTransferBuffer(dataLength);
//
// If CDAllocTransferBuffer fails, it calls UI_FatalError
// don't need to do that from here again.
//
if(pTransferBuffer) {
pTransferBuffer->hdr.pNotificationFn = pNotificationFn;
pTransferBuffer->hdr.pInst = pInst;
DC_MEMCPY(pTransferBuffer->data, pData, dataLength);
TRC_NRM((TB, _T("Notify component %u (%p) of %u bytes of data"),
component, _CD.hwnd[component], dataLength));
TRC_DATA_DBG("notification data", pData, dataLength);
if (0 != SendMessage(_CD.hwnd[component], CD_NOTIFICATION_MSG,
(WPARAM)dataLength, (LPARAM)pTransferBuffer))
{
_pUi->UI_FatalError(DC_ERR_SENDMESSAGEFAILED);
}
else
{
return TRUE;
}
#ifdef DC_DEBUG
// Trace is before increment so that the point at which we're most
// likely to get pre-empted (TRC_GetBuffer) is before all references
// to the variable we're interested in.
TRC_NRM((TB, _T("Messages now pending: %ld"), _CD.pendingMessageCount + 1));
_pUt->UT_InterlockedIncrement(&_CD.pendingMessageCount);
#endif
}
else {
TRC_ERR((TB,_T("CDAllocTransferBuffer returned NULL")));
}
}
else {
TRC_ERR((TB, _T("Null hwnd for component(%u)"), component));
}
DC_END_FN();
return FALSE;
}
/****************************************************************************/
/* Name: CD_DecoupleSimpleNotification */
/* */
/* Purpose: Call given function with specified message (DCUINT) */
/* */
/* Params: IN component - target thread */
/* IN pInst target object instance pointer */
/* IN pNotificationFn - address of notification function */
/* IN data - message data */
/****************************************************************************/
BOOL DCAPI CCD::CD_DecoupleSimpleNotification(
unsigned component,
PDCVOID pInst,
PCD_SIMPLE_NOTIFICATION_FN pNotificationFn,
ULONG_PTR msg)
{
PCDTRANSFERBUFFER pTransferBuffer;
DC_BEGIN_FN("CD_DecoupleSimpleNotification");
TRC_ASSERT((component <= CD_MAX_COMPONENT),
(TB, _T("Invalid component %u"), component));
TRC_ASSERT((pNotificationFn != NULL),
(TB, _T("Null pNotificationFn")));
TRC_NRM((TB, _T("Notify component %u (%p) of %x"), component,
_CD.hwnd[component], msg));
TRC_ASSERT((pInst != NULL),(TB, _T("Null pInst")));
// Check that the target component is still registered.
if (_CD.hwnd[component] != NULL) {
//
// We need to pass instance pointer, function pointer and message
// so we need a transfer buffer (with no data) message is posted
// in WPARAM
//
pTransferBuffer = CDAllocTransferBuffer(0);
if(pTransferBuffer) {
pTransferBuffer->hdr.pSimpleNotificationFn = pNotificationFn;
pTransferBuffer->hdr.pInst = pInst;
#ifdef DC_DEBUG
{
// Check on the number of pending messages - if this deviates too
// far from 0 then something has probably gone wrong.
DCINT32 msgCount = _CD.pendingMessageCount;
_pUt->UT_InterlockedIncrement(&_CD.pendingMessageCount);
if ( msgCount > 50 ) {
TRC_ERR((TB, _T("Now %u pending messages - too high"), msgCount));
}
else {
TRC_NRM((TB, _T("Now %u pending messages"), msgCount));
}
}
#endif
if (PostMessage(_CD.hwnd[component], CD_SIMPLE_NOTIFICATION_MSG,
(WPARAM)msg, (LPARAM)pTransferBuffer))
{
return TRUE;
}
else
{
_pUi->UI_FatalError(DC_ERR_POSTMESSAGEFAILED);
}
}
else {
TRC_ERR((TB,_T(" CDAllocTransferBuffer returned NULL")));
}
}
else
{
TRC_ERR((TB, _T("Null hwnd for component(%u)"), component));
}
DC_END_FN();
return FALSE;
}
/****************************************************************************/
/* Name: CD_DecoupleSyncNotification */
/* */
/* Purpose: Synchronously call given function with specified message */
/* */
/* Params: IN component - target thread */
/* IN pInst target object instance pointer */
/* IN pNotificationFn - address of notification function */
/* IN data - message data */
/****************************************************************************/
BOOL DCAPI CCD::CD_DecoupleSyncNotification(
unsigned component,
PDCVOID pInst,
PCD_SIMPLE_NOTIFICATION_FN pNotificationFn,
ULONG_PTR msg)
{
PCDTRANSFERBUFFER pTransferBuffer;
DC_BEGIN_FN("CD_DecoupleSyncNotification");
TRC_ASSERT((component <= CD_MAX_COMPONENT),
(TB, _T("Invalid component %u"), component));
TRC_ASSERT((pNotificationFn != NULL),
(TB, _T("Null pNotificationFn")) );
TRC_NRM((TB, _T("Notify component %u (%p) of %x"), component,
_CD.hwnd[component], msg));
TRC_ASSERT((pInst != NULL),(TB, _T("Null pInst")));
// Check that the target component is still registered.
if (_CD.hwnd[component] != NULL)
{
//
// We need to pass instance pointer, function pointer and message
// so we need a transfer buffer (with no data) message is posted
// in WPARAM
//
pTransferBuffer = CDAllocTransferBuffer(0);
if(pTransferBuffer) {
pTransferBuffer->hdr.pSimpleNotificationFn = pNotificationFn;
pTransferBuffer->hdr.pInst = pInst;
#ifdef DC_DEBUG
{
// Check on the number of pending messages - if this deviates too
// far from 0 then something has probably gone wrong.
DCINT32 msgCount = _CD.pendingMessageCount;
_pUt->UT_InterlockedIncrement(&_CD.pendingMessageCount);
if ( msgCount > 50 ) {
TRC_ERR((TB, _T("Now %u pending messages - too high"), msgCount));
}
else {
TRC_NRM((TB, _T("Now %u pending messages"), msgCount));
}
}
#endif
if (0 != SendMessage(_CD.hwnd[component], CD_SIMPLE_NOTIFICATION_MSG,
(WPARAM)msg, (LPARAM)pTransferBuffer))
{
_pUi->UI_FatalError(DC_ERR_SENDMESSAGEFAILED);
}
else
{
return TRUE;
}
}
else {
TRC_ERR((TB,_T(" CDAllocTransferBuffer returned NULL")));
}
}
else
{
TRC_ERR((TB, _T("Null hwnd for component(%u)"), component));
}
DC_END_FN();
return FALSE;
}