|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 2000.
//
// File: C O N M A N S A. C P P
//
// Contents: Implementation of ICS connection class manager
//
// Notes:
//
// Author: kenwic 8 Aug 2000
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "conmansa.h"
#include "enumsa.h"
#include "cmsabcon.h"
//+---------------------------------------------------------------------------
// INetConnectionManager
//
CSharedAccessConnectionManager::CSharedAccessConnectionManager() { m_lSearchCookie = 0; m_pDeviceFinder = NULL; m_pDeviceFinderCallback = NULL; m_SocketEvent = WSA_INVALID_EVENT; m_hSocketNotificationWait = INVALID_HANDLE_VALUE; m_DummySocket = INVALID_SOCKET; }
//+---------------------------------------------------------------------------
//
// Member: CSharedAccessConnectionManager::EnumConnections
//
// Purpose: Returns an enumerator object for ICS connections
//
// Arguments:
// Flags [in]
// ppEnum [out] Returns enumerator object
//
// Returns: S_OK if succeeded, OLE or Win32 error code otherwise
//
// Author: kenwic 17 Jul 2000
//
// Notes:
//
STDMETHODIMP CSharedAccessConnectionManager::EnumConnections(NETCONMGR_ENUM_FLAGS Flags, IEnumNetConnection** ppEnum) { *ppEnum = NULL;
CComObject<CSharedAccessConnectionManagerEnumConnection>* pEnum; HRESULT hr = CComObject<CSharedAccessConnectionManagerEnumConnection>::CreateInstance(&pEnum); if(SUCCEEDED(hr)) { *ppEnum = static_cast<IEnumNetConnection*>(pEnum); pEnum->AddRef(); }
TraceHr (ttidError, FAL, hr, FALSE, "CSharedAccessConnectionManager::EnumConnections"); return hr; }
HRESULT CSharedAccessConnectionManager::FinalConstruct(void) { HRESULT hr = S_OK; TraceTag(ttidConman, "CSharedAccessConnectionManager::FinalConstruct");
m_DummySocket = socket(AF_INET, SOCK_DGRAM, 0); if(INVALID_SOCKET != m_DummySocket) { m_SocketEvent = CreateEvent(NULL, FALSE, TRUE, NULL); if(NULL != m_SocketEvent) { if(0 != WSAEventSelect(m_DummySocket, m_SocketEvent, FD_ADDRESS_LIST_CHANGE)) { hr = E_FAIL; } } else { hr = E_FAIL; } } else { hr = E_FAIL; }
if(SUCCEEDED(hr)) // start up the first search on a background thread, this shoud fire immediately
{ // note that there is no addref here because it would keep the object alive forever. In FinalRelease we will make sure we won't get called back
if(0 == RegisterWaitForSingleObject(&m_hSocketNotificationWait, m_SocketEvent, AsyncStartSearching, this, INFINITE, WT_EXECUTEDEFAULT)) { m_hSocketNotificationWait = INVALID_HANDLE_VALUE; }
}
TraceHr (ttidError, FAL, hr, FALSE, "CSharedAccessConnectionManager::FinalConstruct"); return hr; }
HRESULT CSharedAccessConnectionManager::FinalRelease(void) { HRESULT hr = S_OK;
TraceTag(ttidConman, "CSharedAccessConnectionManager::FinalRelease");
if(INVALID_HANDLE_VALUE != m_hSocketNotificationWait) { UnregisterWaitEx(m_hSocketNotificationWait, INVALID_HANDLE_VALUE); // we must block here since we are not addrefed
}
if(INVALID_SOCKET != m_DummySocket) // the event wait must be unregistered first
{ closesocket(m_DummySocket); }
if(WSA_INVALID_EVENT != m_SocketEvent) // the socket must be closed first
{ CloseHandle(m_SocketEvent); }
// After the other thread is shut down, the device finder and callback won't change any more so we don't need a lock.
if(NULL != m_pDeviceFinder) { hr = m_pDeviceFinder->CancelAsyncFind(m_lSearchCookie); m_pDeviceFinder->Release(); }
if(NULL != m_pDeviceFinderCallback) { m_pDeviceFinderCallback->Release(); }
TraceHr (ttidError, FAL, hr, FALSE, "CSharedAccessConnectionManager::FinalRelease");
return hr; }
HRESULT CSharedAccessConnectionManager::StartSearch(void) { HRESULT hr = S_OK;
CComObject<CSharedAccessDeviceFinderCallback>* pDeviceFinderCallback; hr = CComObject<CSharedAccessDeviceFinderCallback>::CreateInstance(&pDeviceFinderCallback); if(SUCCEEDED(hr)) { pDeviceFinderCallback->AddRef(); IUPnPDeviceFinder* pDeviceFinder; hr = CoCreateInstance(CLSID_UPnPDeviceFinder, NULL, CLSCTX_INPROC_SERVER, IID_IUPnPDeviceFinder, reinterpret_cast<void **>(&pDeviceFinder)); if(SUCCEEDED(hr)) { BSTR bstrTypeURI; bstrTypeURI = SysAllocString(L"urn:schemas-upnp-org:device:InternetGatewayDevice:1"); if (NULL != bstrTypeURI) { LONG lSearchCookie; hr = pDeviceFinder->CreateAsyncFind(bstrTypeURI, 0, static_cast<IUPnPDeviceFinderCallback*>(pDeviceFinderCallback), &lSearchCookie); if(SUCCEEDED(hr)) { LONG lOldSearchCookie; IUPnPDeviceFinder* pOldDeviceFinder; CComObject<CSharedAccessDeviceFinderCallback>* pOldDeviceFinderCallback;
Lock(); // swap in the new finder and callback
lOldSearchCookie = m_lSearchCookie; m_lSearchCookie = lSearchCookie;
pOldDeviceFinder = m_pDeviceFinder; m_pDeviceFinder = pDeviceFinder; pDeviceFinder->AddRef(); pOldDeviceFinderCallback = m_pDeviceFinderCallback; m_pDeviceFinderCallback = pDeviceFinderCallback; pDeviceFinderCallback->AddRef(); Unlock(); if(NULL != pOldDeviceFinder)
{ pOldDeviceFinder->CancelAsyncFind(lOldSearchCookie); pOldDeviceFinder->Release(); } if(NULL != pOldDeviceFinderCallback) { pOldDeviceFinderCallback->DeviceRemoved(NULL, NULL); // clear out the old callback, so netshell gets cleaned up
pOldDeviceFinderCallback->Release(); } hr = pDeviceFinder->StartAsyncFind(lSearchCookie); // don't start the search until the new callback is in place
} SysFreeString(bstrTypeURI); } pDeviceFinder->Release(); } pDeviceFinderCallback->Release(); }
DWORD dwBytesReturned; if(SOCKET_ERROR != WSAIoctl(m_DummySocket, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, &dwBytesReturned, NULL, NULL) || WSAEWOULDBLOCK != WSAGetLastError()) { hr = E_FAIL; }
WSANETWORKEVENTS NetworkEvents; ZeroMemory(&NetworkEvents, sizeof(NetworkEvents)); WSAEnumNetworkEvents(m_DummySocket, NULL, &NetworkEvents);
return hr; }
void CSharedAccessConnectionManager::AsyncStartSearching(PVOID lpParameter, BOOLEAN TimerOrWaitFired) { if(FALSE == TimerOrWaitFired) { CSharedAccessConnectionManager* pThis = reinterpret_cast<CSharedAccessConnectionManager*>(lpParameter); HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if(SUCCEEDED(hr)) { hr = pThis->StartSearch(); CoUninitialize(); } } return; }
HRESULT CSharedAccessConnectionManager::GetSharedAccessBeacon(BSTR DeviceId, ISharedAccessBeacon** ppSharedAccessBeacon) { HRESULT hr = S_OK;
*ppSharedAccessBeacon = NULL; CComObject<CSharedAccessDeviceFinderCallback>* pDeviceFinderCallback; Lock(); pDeviceFinderCallback = m_pDeviceFinderCallback; if(NULL != pDeviceFinderCallback) { pDeviceFinderCallback->AddRef(); } Unlock();
if(NULL != pDeviceFinderCallback) { hr = pDeviceFinderCallback->GetSharedAccessBeacon(DeviceId, ppSharedAccessBeacon); pDeviceFinderCallback->Release(); } else { hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); } return hr; }
|