⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 event.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//=--------------------------------------------------------------------------=
// event.Cpp
//=--------------------------------------------------------------------------=
//
// the MSMQEvent object
//
//
#include "IPServer.H"

#include "LocalObj.H"
#include "dispids.h"

#include "globals.h"    // for framework globals
#include "oautil.h"
#include "event.h"
#include "msg.h"
#include "q.h"

// for ASSERT and FAIL
//
SZTHISFILE

// debug...
#define new DEBUG_NEW
#if DEBUG
#define SysAllocString DebSysAllocString
#define SysReAllocString DebSysReAllocString
#define SysFreeString DebSysFreeString
#endif // DEBUG

#define CREATEWINDOW

// Used to coordinate user-thread queue ops and 
//  queue lookup in falcon-thread callback 
//
CRITICAL_SECTION g_csCallback;

// per-class hwnd
HWND CMSMQEvent::m_hwnd = NULL;
WNDPROC CMSMQEvent::m_lpPrevWndFunc = NULL;
UINT CMSMQEvent::m_cInstance = 0;
WNDCLASS CMSMQEvent::m_wndclass;
HANDLE g_hEvent = INVALID_HANDLE_VALUE;

// MSMQEvent event stuff...
typedef enum {
    MSMQEventEvent_Arrived = 0,
    MSMQEventEvent_ArrivedError = 1,
} MSMQEventEVENTS;

VARTYPE rgI4[] = {VT_I4};
VARTYPE rgI4I4[] = {VT_I4, VT_I4};
VARTYPE rgDISPATCHI4[] = {VT_DISPATCH, VT_I4};
VARTYPE rgDISPATCHI4I4[] = {VT_DISPATCH, VT_I4, VT_I4};

EVENTINFO g_rgMSMQEventEvents[] = {
    {DISPID_MQEVENTEVENTS_ARRIVED, 2, rgDISPATCHI4},
    {DISPID_MQEVENTEVENTS_ARRIVEDERROR, 3, rgDISPATCHI4I4}
};



//=--------------------------------------------------------------------------=
// CMSMQEvent::Create
//=--------------------------------------------------------------------------=
// creates a new MSMQMessage object.
//
// Parameters:
//    IUnknown *        - [in] controlling unkonwn
//
// Output:
//    IUnknown *        - new object.
//
// Notes:
//
IUnknown *CMSMQEvent::Create
(
    IUnknown *pUnkOuter
)
{
    // make sure we return the private unknown so that we support aggegation
    // correctly!
    //
    CMSMQEvent *pNew = new CMSMQEvent(pUnkOuter);
    return pNew ? pNew->PrivateUnknown() : NULL;
}

//=--------------------------------------------------------------------------=
// CMSMQEvent::CMSMQEvent
//=--------------------------------------------------------------------------=
// create the object and initialize the refcount
//
// Parameters:
//    IUnknown *    - [in] controlling unknown
//
// Notes:
//
#pragma warning(disable:4355)  // using 'this' in constructor
CMSMQEvent::CMSMQEvent
(
    IUnknown *pUnkOuter
)
: CAutomationObjectWEvents(pUnkOuter, OBJECT_TYPE_OBJMQEVENT, (void *)this)
{

    // TODO: initialize anything here
    HWND hwnd;

    // Register our "sub-classed" windowproc so that we can
    //  send a message from the Falcon thread to the user's VB
    //  thread in order to fire async events in the correct
    //  context.
    //
    if (m_cInstance++ == 0) {
#ifdef CREATEWINDOW
      hwnd = CreateHiddenWindow();
#else
      hwnd = GetActiveWindow();
#endif // CREATEWINDOW
      ASSERT(IsWindow(hwnd), L"should have a valid window.");
#ifndef CREATEWINDOW

      m_lpPrevWndFunc = (WNDPROC)SetWindowLong(
                                   NULL, // hwnd,
                                   GWL_WNDPROC,
                                   (LONG)CMSMQEvent_WindowProc
                                   );
#endif // CREATEWINDOW
      m_hwnd = hwnd;
      //
      // Event for inter-thread synchronization
      //
      g_hEvent = CreateEvent(NULL,
                              FALSE,  // manual reset
                              FALSE,  // not signalled
                              NULL);
      ASSERT(g_hEvent != NULL, L"CreateEvent failed!");
    } // if m_hwnd == NULL
}
#pragma warning(default:4355)  // using 'this' in constructor

//=--------------------------------------------------------------------------=
// CMSMQEvent::CMSMQEvent
//=--------------------------------------------------------------------------=
// "We all labour against our own cure, for death is the cure of all diseases"
//    - Sir Thomas Browne (1605 - 82)
//
// Notes:
//
CMSMQEvent::~CMSMQEvent ()
{
    // TODO: clean up anything here.

#ifndef CREATEWINDOW
    // Un-subclass if the sub-classed window is still valid.
    if (m_hwnd && m_lpPrevWndFunc) {
      if (IsWindow(m_hwnd)) {
        SetWindowLong(NULL, // m_hwnd,
                      GWL_WNDPROC,
                      (LONG)m_lpPrevWndFunc);
      }
    }
    m_hwnd = NULL;
    m_lpPrevWndFunc = NULL;
#else
    if (--m_cInstance == 0) {
      DestroyHiddenWindow();
      if (g_hEvent != INVALID_HANDLE_VALUE) {
        SetEvent(g_hEvent);
        CloseHandle(g_hEvent);
        g_hEvent = INVALID_HANDLE_VALUE;
      }
    }
#endif // CREATEWINDOW
}

//=--------------------------------------------------------------------------=
// CMSMQEvent::InternalQueryInterface
//=--------------------------------------------------------------------------=
// the controlling unknown will call this for us in the case where they're
// looking for a specific interface.
//
// Parameters:
//    REFIID        - [in]  interface they want
//    void **       - [out] where they want to put the resulting object ptr.
//
// Output:
//    HRESULT       - S_OK, E_NOINTERFACE
//
// Notes:
//
HRESULT CMSMQEvent::InternalQueryInterface
(
    REFIID riid,
    void **ppvObjOut
)
{
    CHECK_POINTER(ppvObjOut);

    // we support IMSMQEvent and ISupportErrorInfo and now IMSMQPrivateEvent
    //
    if (DO_GUIDS_MATCH(riid, IID_IMSMQEvent)) {
        *ppvObjOut = (void *)(IMSMQEvent *)this;
        AddRef();
        return S_OK;
    } else if (DO_GUIDS_MATCH(riid, IID_ISupportErrorInfo)) {
        *ppvObjOut = (void *)(ISupportErrorInfo *)this;
        AddRef();
        return S_OK;
    } else if (DO_GUIDS_MATCH(riid, IID_IMSMQPrivateEvent)) {
        *ppvObjOut = (void *)(IMSMQPrivateEvent *)this;
        AddRef();
        return S_OK;
    }

    // call the super-class version and see if it can oblige.
    //
    return CAutomationObjectWEvents::InternalQueryInterface(riid, ppvObjOut);
}


    //
    // IMSMQPrivateEvent methods
    //

//=--------------------------------------------------------------------------=
// CMSMQEvent::FireArrivedEvent
//=--------------------------------------------------------------------------=
//
// Parameters:
//
// Output:
//
// Notes:
HRESULT CMSMQEvent::FireArrivedEvent(
    IMSMQQueue __RPC_FAR *pq,
    long msgcursor)
{

    FireEvent(
      &g_rgMSMQEventEvents[MSMQEventEvent_Arrived],
      (long)pq,
      msgcursor);
    return NOERROR;
}



//=--------------------------------------------------------------------------=
// CMSMQEvent::FireArrivedErrorEvent
//=--------------------------------------------------------------------------=
//
// Parameters:
//
// Output:
//
// Notes:
HRESULT CMSMQEvent::FireArrivedErrorEvent(
    IMSMQQueue __RPC_FAR *pq,
    HRESULT hrStatus,
    long msgcursor)
{

    FireEvent(
      &g_rgMSMQEventEvents[MSMQEventEvent_ArrivedError],
      (long)pq,
      (long)hrStatus,
      (long)msgcursor);
    return NOERROR;
}

extern WNDPROC g_lpPrevWndFunc;

//=--------------------------------------------------------------------------=
// InternalReceiveCallback
//=--------------------------------------------------------------------------=
// Async callback handler.  Runs in Falcon created thread.
// We send message to user thread so that event is fired
//  in correct execution context.
//
// Parameters:
//	hrStatus,
//	hReceiveQueue,
//    	dwTimeout,
//    	dwAction,
//    	pMessageProps,
//    	lpOverlapped,
//    	hCursor
//      MQMSG_CURSOR
//
// Output:
//    HRESULT       - S_OK, E_NOINTERFACE
//
// Notes:
//
void APIENTRY InternalReceiveCallback(
    HRESULT hrStatus,
    QUEUEHANDLE hReceiveQueue,
    DWORD dwTimeout,
    DWORD dwAction,
    MQMSGPROPS* pmsgprops,
    LPOVERLAPPED lpOverlapped,
    HANDLE hCursor,
    MQMSGCURSOR msgcursor)
{
    // FireEvent...
    // Map handle to associated queue object
    //
    CMSMQQueue *pq;
    HWND hwnd;
    VARIANT_BOOL isOpen;
    LRESULT lr;
    BOOL fInCritSect = FALSE;
    IMSMQEvent *pqevent;
    IMSMQPrivateEvent *pprivateevent = NULL;
    HRESULT hresult;

    //
    // UNDONE: 905: decrement dll refcount that we incremented
    //  when we registered the callback.
    //
    EnterCriticalSection(&g_csCallback);      // syncs other queue ops
    fInCritSect = TRUE;
    pq = CMSMQQueue::PqOfHandle(hReceiveQueue);
    
    // if no queue, then ignore the callback otherwise
    //  if the queue is open and it has a window
    //  then send message to user-thread that will
    //  trigger event firing.
    //
    if (pq) {
      hresult = pq->get_IsOpen(&isOpen);
      ASSERT(hresult == NOERROR, L"IsOpen should never fail.");
      if (isOpen) {
        pqevent = pq->Pqevent();
        if (pqevent) {
          //
          // don't get the private interface here since MTS might cache it
          //  and then we'll have ITC problems
          //
          hwnd = CMSMQEvent::Hwnd();
          if (IsWindow(hwnd)) {
            //        
            // Need to exit critsect now so that
            //  we don't deadlock with user closing queue
            //  in user thread.
            //
            LeaveCriticalSection(&g_csCallback);
            fInCritSect = FALSE;
            //
            // 1212: In principle, need to special case BUFFER_OVERFLOW
            //  by growing buffer and synchronously peeking...
            //  but since it's the user's responsibility to 
            //  receive the actual message, we'll just let our
            //  usual InternalReceive handling deal with the
            //  overflow...
            //
            //
            // 1900: pass msgcursor to event handler 
            //
            WindowsMessage *pwinmsg = new WindowsMessage;
			if (! pwinmsg) {
				RETAILMSG(1, (L"MQOA: OUT OF MEMORY - DATA WILL BE LOST!\r\n"));
				goto cleanup;
			}

            pwinmsg->m_msgcursor = msgcursor;
            if ((hrStatus == MQ_ERROR_BUFFER_OVERFLOW) || 
                  SUCCEEDED(hrStatus)) {
              //
              // Since we are in a Falcon created callback thread,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -