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

📄 exchangeclient.cpp

📁 一个WinCE6。0下的IP phone的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "ExchangeClient.h"
#include "..\contacts\ContactsFormatHandler.h"
#include "..\galsearch\GALSearchFormatHandler.h"
#include "..\freebusy\FreeBusyFormatHandler.h"
#include "ExchangeRequest.h"
#include "XMLDataRecordParser.h"
#include <algorithm>
#include "Settings.h"
#include "utilities.h"
#include "SecurityUtils.h"

const WCHAR c_wszWindowName[] = L"ExchangeClientHiddenWindow";

#define ECM_WORKER_THREAD_TERMINATED    (WM_USER + 100)
#define ECM_USER_CALLBACK               (ECM_WORKER_THREAD_TERMINATED + 1)

/*------------------------------------

        Constructor/Destructor

------------------------------------*/
CExchangeClient::CExchangeClient()
{
    TRACE_(ZONE_OWAEC_TRACING_CTOR);
    MemTrackAdd();
    
    m_cpCallback       = NULL;
    m_cpHttpRequest    = NULL;
    m_fInitialized     = FALSE;
    m_hEventExit       = NULL;
    m_hEventNewRequest = NULL;
    m_hWorkerThread    = NULL;
    m_hwndCallback     = NULL;
    InitializeRequestLock();
}

CExchangeClient::~CExchangeClient()
{
    TRACE_(ZONE_OWAEC_TRACING_CTOR);
    MemTrackRemove();

    //Force the CComPtr's to release their references
    m_cpCallback    = NULL;
    m_cpHttpRequest = NULL;
    SetCurrentRequest(NULL);
    m_cpXMLHTTPRequestClassFactory = NULL;
    
    //Close the event/thread handles
    CloseHandle(m_hEventExit);
    CloseHandle(m_hEventNewRequest);
    CloseHandle(m_hWorkerThread);
    UnregisterClass(c_wszWindowName, _Module.m_hInst);

    //Free each request in the queue
    CExchangeClientRequest *pRequest      = NULL;
    BOOL                    fMoreRequests = TRUE;
    
    while (fMoreRequests)
    {
        if (GetNextRequest(&pRequest) == S_FALSE)
        {
            fMoreRequests = FALSE;
            break;
        }
        else
        {
            SafeRelease(pRequest);
        }
    }

    DeleteRequestLock();
}

/*--------------------------------------------------------------

        IExchangeClient Implementation

---------------------------------------------------------------*/

/*------------------------------------------------------------------------------
    CExchangeClient::Initialize
    
    Initializes the exchange client by setting up callbacks and internal
    data structures
    
    Returns (HRESULT): Indicating success or failure
------------------------------------------------------------------------------*/
HRESULT CExchangeClient::Initialize(
    IExchangeClientRequestCallback *piCallback
    )
{
    TRACE();
    HRESULT     hr = S_OK;

    //check params
    if (m_fInitialized)
    {
        return OWAEC_E_ALREADYINITIALIZED;
    }

    //Check parameters
    if (piCallback == NULL)
    {
        return E_POINTER;
    }

    //Initialize the callback pointer and the critical section
    m_cpCallback = piCallback;

    if (SUCCEEDED(hr))
    {
        //create the xmlhttp request class factory
        hr = CoGetClassObject(
            CLSID_XMLHTTPRequest,
            CLSCTX_INPROC_SERVER,
            NULL,
            IID_IClassFactory,
            reinterpret_cast<void**>(&m_cpXMLHTTPRequestClassFactory)
            );
    }

    if (SUCCEEDED(hr))
    {
        //Create the XMLHttp request object
        hr = RecreateXMLHttpObject();
    }

    if (SUCCEEDED(hr))
    {
        //register the hidden window for handling callbacks
        hr = RegisterCallbackWindow();
    }

    if (SUCCEEDED(hr))
    {
        //create the events and worker thread that will handle the requests
        hr = CreateWorkerThreadAndEvents();
    }
    
    m_fInitialized = SUCCEEDED(hr);

    //cleanup in case of failure
    if (FAILED(hr))
    {
        //CComPtr's release references to previously allocated objects
        m_cpHttpRequest                = NULL;
        m_cpCallback                   = NULL;
        m_cpXMLHTTPRequestClassFactory = NULL;
    }
    
    return hr;
}

/*------------------------------------------------------------------------------
    CExchangeClient::CreateXMLHttpObject
    
    Create's the IXMLHTTPRequest object through the class factory obtained on initialization
------------------------------------------------------------------------------*/
HRESULT CExchangeClient::RecreateXMLHttpObject()
{
    PREFAST_ASSERT(m_cpXMLHTTPRequestClassFactory != NULL);
    
    m_cpHttpRequest = NULL;

    return m_cpXMLHTTPRequestClassFactory->CreateInstance(
        NULL,
        IID_IXMLHTTPRequest,
        reinterpret_cast<void**>(&m_cpHttpRequest)
        );
}

/*------------------------------------------------------------------------------
    CExchangeClient::CreateWorkerThreadAndEvents
    
    Creates the worker thread and events used for signalling between threads
    
    Returns (HRESULT): Indicating whether the events and threads were initialized
                       successfully
------------------------------------------------------------------------------*/
HRESULT CExchangeClient::CreateWorkerThreadAndEvents()
{
    HRESULT     hr = S_OK;

    if (SUCCEEDED(hr))
    {
        //Create the Exit and NewRequest events
        m_hEventExit       = CreateEvent(NULL, TRUE, FALSE, NULL);
        m_hEventNewRequest = CreateEvent(NULL, TRUE, FALSE, NULL);
        
        if (!m_hEventExit || !m_hEventNewRequest)
        {
            hr = HRESULT_FROM_WIN32(GetLastError());
        }
    }

    if (SUCCEEDED(hr))
    {
        //Include 'this' as the parameter to the worker thread.
        //Add a reference to myself to ensure the thread can always
        //access the object variables correctly
        AddRef();
        
        m_hWorkerThread = CreateThread(
            NULL,
            0,
            s_WorkerThreadProc,
            reinterpret_cast<void*>(this),
            0,
            NULL
            );
        
        if (m_hWorkerThread == NULL)
        {
            //If we couldn't create the thread, release the reference added
            //before the call to CreateThread
            Release();
            hr = HRESULT_FROM_WIN32(GetLastError());
            DEBUGMSG(ZONE_OWAEC_ERROR, (L"OWAExchangeClient:: Failed to create worker thread 0x%x", hr));
        }
    }

    if (FAILED(hr))
    {
        //if creating the thread failed, but we were able to create the events
        //close and delete the event handles
        CloseHandle(m_hEventExit);
        m_hEventExit = NULL;
        
        CloseHandle(m_hEventNewRequest);
        m_hEventExit = NULL;
    }
    return hr;
}


/*------------------------------------------------------------------------------
    CExchangeClient::RegisterCallbackWindow
    
    Register the internal hidden window used to marshall results between threads
    back to the main application
    
    Returns (HRESULT): Indicating whether the window was registered properly or
                       S_FALSE to indicate the window was previously registered
------------------------------------------------------------------------------*/
HRESULT CExchangeClient::RegisterCallbackWindow()
{
    //if the hidden window is already registered, return S_FALSE
    if (m_hwndCallback != NULL)
    {
        return S_FALSE;
    }
    
    HRESULT     hr   = S_OK;
    WNDCLASS    wc   = {0};
    
    wc.lpfnWndProc   = s_CallbackWindowProc;
    wc.cbWndExtra    = sizeof(this); 
    wc.hInstance     = _Module.m_hInst;
    wc.lpszClassName = c_wszWindowName;

    if (RegisterClass(&wc) == 0)
    {
        DWORD dwLastErr = GetLastError();
        if (dwLastErr != ERROR_CLASS_ALREADY_EXISTS)
        {
            hr = HRESULT_FROM_WIN32(dwLastErr);
        }
    }  
    
    if (SUCCEEDED(hr))
    {
        //Going to pack 'this' into the CREATESTRUCT of CreateWindow, so add a reference to myself
        AddRef();
        
        m_hwndCallback = CreateWindow(
            (LPCWSTR)c_wszWindowName,
            NULL,
            WS_OVERLAPPED & ~WS_VISIBLE,
            0,
            0,
            0,
            0,
            NULL,
            NULL,
            _Module.m_hInst,
            reinterpret_cast<VOID*>(this)
            );

        if (m_hwndCallback == NULL)
        {
            //if we couldn't create the window, release the reference added before the call
            //to CreateWindow
            
            Release();
            hr = HRESULT_FROM_WIN32(GetLastError());
            DEBUGMSG(ZONE_OWAEC_ERROR, (L"OWAExchangeClient:: Failed to create hidden window 0x%x", hr));
        }
    }

    //Nothing to clean up
    return hr;
}

/*------------------------------------------------------------------------------
    CExchangeClient::s_CallbackWindowProc
    
    Static Window Proc on the main app thread - used for marshalling data
    between threads
------------------------------------------------------------------------------*/
LRESULT CALLBACK CExchangeClient::s_CallbackWindowProc(
    HWND    hwnd,
    UINT    uMsg,
    WPARAM  wParam,
    LPARAM  lParam
    )
{
    //The client instance to use
    CExchangeClient *pClient = NULL;
    LRESULT          lRes    = 0;
    HRESULT          hr      = S_OK;

    //In the case of WM_CREATE, pack the ExchangeClient instance into the WindowLong of the
    //window and prepare for the rest of the callbacks
    if (uMsg == WM_CREATE)
    {
        CREATESTRUCT *pcs = reinterpret_cast<CREATESTRUCT *>(lParam);
        if (pcs == NULL)
        {
            ASSERT(FALSE);
            return E_UNEXPECTED;
        }

        pClient = reinterpret_cast<CExchangeClient*>(pcs->lpCreateParams);
        if (pClient == NULL)
        {
            ASSERT(FALSE);
            return E_UNEXPECTED;
        }

        //store the pointer in the window class
        SetWindowLong(
            hwnd,
            0,
            reinterpret_cast<LONG_PTR>(pClient)
            );
    }
    //Otherwise get the client from the window long to use in handling the message
    else 
    {
        pClient = reinterpret_cast<CExchangeClient*>(GetWindowLong(hwnd, 0));
        if (pClient == NULL)
        {
            ASSERT(FALSE);
            hr = HRESULT_FROM_WIN32(GetLastError());
        }
    }

    //Dispatch the message to the appopriate handler
    if (SUCCEEDED(hr))
    {
        switch (uMsg)
        {
        //When the window is being destroyed - release the reference to the client
        //that was added before the window was created
        case WM_DESTROY:
            pClient->Release();
            break;

        case ECM_WORKER_THREAD_TERMINATED:
            DestroyWindow(hwnd);
            (VOID)pClient->GetCallbackInterface()->OnShutdown();
            break;

        case ECM_USER_CALLBACK:
            (VOID)pClient->GetCallbackInterface()->OnRequestProgress(
                (IExchangeClientRequest*)wParam,
                (ExchangeClientRequestStatus)lParam
                );
            ((IExchangeClientRequest*)wParam)->Release();
            break;
            
        default:
            lRes = DefWindowProc(hwnd, uMsg, wParam, lParam);
            break;
        }
    }

    return lRes;
}

/*------------------------------------------------------------------------------
    CExchangeClient::s_WorkerThreadProc
    
    Worker Thread ThreadProc - unpacks the CExchangeClient instance and 
    begins the processing of requests

    There was a reference added to the client for the thread proc, 
    before terminating this proc needs to release the reference added to the client
        
    Parameters:
        LPVOID - VOID casted ExchangeClient to unpack
    
------------------------------------------------------------------------------*/
DWORD WINAPI CExchangeClient::s_WorkerThreadProc(LPVOID lpvThreadParam)
{
    TRACE();
    if (lpvThreadParam == NULL)
    {
        ASSERT(FALSE);
        return E_POINTER;
    }

    CExchangeClient *pClient = reinterpret_cast<CExchangeClient*>(lpvThreadParam);

    HRESULT hr =  pClient->WorkerThreadProc();

    //epilogue (notify callback etc)
    (VOID)pClient->OnWorkerThreadTermination();

    //release the reference added before CreateThread
    pClient->Release();

    DEBUGMSG(ZONE_OWAEC_TRACING_INFORMATIONAL, (L"OWAExchangeClient:: Worker thread exiting with hr = 0x%x", hr));
    
    return (DWORD)hr;
}

/*------------------------------------------------------------------------------

⌨️ 快捷键说明

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