windows-nt/Source/XPSP1/NT/net/config/netman/conman/conmansa.cpp
2020-09-26 16:20:57 +08:00

278 lines
8.2 KiB
C++

//+---------------------------------------------------------------------------
//
// 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;
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;
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;
}