?? exchangeclient.cpp
字號:
//
// 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 + -