windows-nt/Source/XPSP1/NT/net/upnp/host/upnphost/registrar/devicepersistencemanager.cpp
2020-09-26 16:20:57 +08:00

662 lines
19 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 2000.
//
// File: D E V I C E P E R S I S T E N C E M A N A G E R . C P P
//
// Contents: Persistence for UPnP device host registrar settings to registry
//
// Notes:
//
// Author: mbend 6 Sep 2000
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "uhbase.h"
#include "hostp.h"
#include "DevicePersistenceManager.h"
#include "uhsync.h"
#include "ncreg.h"
#include "Array.h"
#include "ComUtility.h"
#include "uhutil.h"
#include "uhcommon.h"
// String constants
const wchar_t c_szDevices[] = L"Devices";
const wchar_t c_szProviders[] = L"Providers";
const wchar_t c_szProgId[] = L"ProgId";
const wchar_t c_szInitString[] = L"Init String";
const wchar_t c_szContainerId[] = L"Container Id";
const wchar_t c_szResourcePath[] = L"Resource Path";
const wchar_t c_szLifeTime[] = L"Life Time";
const wchar_t c_szProgIdProviderClass[] = L"Provider ProgId";
// Helper functions
HRESULT HrCreateOrOpenDevicesKey(HKEY * phKeyDevices)
{
CHECK_POINTER(phKeyDevices);
HRESULT hr = S_OK;
HKEY hKeyDeviceHost;
hr = HrCreateOrOpenDeviceHostKey(&hKeyDeviceHost);
if(SUCCEEDED(hr))
{
HKEY hKeyDevices;
DWORD dwDisposition = 0;
hr = HrRegCreateKeyEx(hKeyDeviceHost, c_szDevices, 0, KEY_ALL_ACCESS, NULL, &hKeyDevices, &dwDisposition);
if(SUCCEEDED(hr))
{
*phKeyDevices = hKeyDevices;
}
RegCloseKey(hKeyDeviceHost);
}
TraceHr(ttidError, FAL, hr, FALSE, "HrCreateOrOpenDevicesKey");
return hr;
}
HRESULT HrCreateOrOpenProvidersKey(HKEY * phKeyProviders)
{
CHECK_POINTER(phKeyProviders);
HRESULT hr = S_OK;
HKEY hKeyDeviceHost;
hr = HrCreateOrOpenDeviceHostKey(&hKeyDeviceHost);
if(SUCCEEDED(hr))
{
HKEY hKeyProviders;
DWORD dwDisposition = 0;
hr = HrRegCreateKeyEx(hKeyDeviceHost, c_szProviders, 0, KEY_ALL_ACCESS, NULL, &hKeyProviders, &dwDisposition);
if(SUCCEEDED(hr))
{
*phKeyProviders = hKeyProviders;
}
RegCloseKey(hKeyDeviceHost);
}
TraceHr(ttidError, FAL, hr, FALSE, "HrCreateOrOpenProvidersKey");
return hr;
}
CDevicePersistenceManager::CDevicePersistenceManager()
{
}
CDevicePersistenceManager::~CDevicePersistenceManager()
{
}
STDMETHODIMP CDevicePersistenceManager::SavePhyisicalDevice(
/*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
/*[in, string]*/ const wchar_t * szProgIdDeviceControlClass,
/*[in, string]*/ const wchar_t * szInitString,
/*[in, string]*/ const wchar_t * szContainerId,
/*[in, string]*/ const wchar_t * szResourcePath,
/*[in]*/ long nLifeTime)
{
HRESULT hr = S_OK;
// Create the string to use
CUString strUuid;
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
if (SUCCEEDED(hr))
{
hr = strUuid.HrInitFromGUID(guidPhysicalDeviceIdentifier);
}
if(SUCCEEDED(hr))
{
HKEY hKeyDevices;
hr = HrCreateOrOpenDevicesKey(&hKeyDevices);
if(SUCCEEDED(hr))
{
// Create key to house values
HKEY hKeyPid;
DWORD dwDisposition = 0;
hr = HrRegCreateKeyEx(hKeyDevices, strUuid, 0, KEY_ALL_ACCESS, NULL, &hKeyPid, &dwDisposition);
if(SUCCEEDED(hr))
{
// Save all of the values
hr = HrRegSetSz(hKeyPid, c_szProgId, szProgIdDeviceControlClass);
if(SUCCEEDED(hr))
{
hr = HrRegSetSz(hKeyPid, c_szInitString, szInitString);
if(SUCCEEDED(hr))
{
hr = HrRegSetSz(hKeyPid, c_szContainerId, szContainerId);
if(SUCCEEDED(hr))
{
hr = HrRegSetSz(hKeyPid, c_szResourcePath, szResourcePath);
if(SUCCEEDED(hr))
{
hr = HrRegSetDword(hKeyPid, c_szLifeTime, nLifeTime);
}
}
}
}
RegCloseKey(hKeyPid);
if(FAILED(hr))
{
// If anything fails, remove the whole tree
HrRegDeleteKeyTree(hKeyDevices, strUuid);
}
}
RegCloseKey(hKeyDevices);
}
}
TraceHr(ttidError, FAL, hr, FALSE, "CDevicePersistenceManager::SavePhyisicalDevice");
return hr;
}
STDMETHODIMP CDevicePersistenceManager::LookupPhysicalDevice(
/*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
/*[out, string]*/ wchar_t ** pszProgIdDeviceControlClass,
/*[out, string]*/ wchar_t ** pszInitString,
/*[out, string]*/ wchar_t ** pszContainerId,
/*[out, string]*/ wchar_t ** pszResourcePath,
/*[out]*/ long * pnLifeTime)
{
CHECK_POINTER(pszProgIdDeviceControlClass);
CHECK_POINTER(pszInitString);
CHECK_POINTER(pszContainerId);
CHECK_POINTER(pszResourcePath);
CHECK_POINTER(pnLifeTime);
HRESULT hr = S_OK;
// Create the string to use
CUString strUuid;
CUString strProgIdDeviceControlClass;
CUString strInitString;
CUString strContainerId;
CUString strResourcePath;
DWORD dwLifeTime;
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
if (SUCCEEDED(hr))
{
hr = strUuid.HrInitFromGUID(guidPhysicalDeviceIdentifier);
}
if(SUCCEEDED(hr))
{
HKEY hKeyDevices;
hr = HrCreateOrOpenDevicesKey(&hKeyDevices);
if(SUCCEEDED(hr))
{
// Open the key housing the values
HKEY hKeyPid;
DWORD dwDisposition = 0;
hr = HrRegOpenKeyEx(hKeyDevices, strUuid, KEY_ALL_ACCESS, &hKeyPid);
if(SUCCEEDED(hr))
{
// Load all of the values
hr = HrRegQueryString(hKeyPid, c_szProgId, strProgIdDeviceControlClass);
if(SUCCEEDED(hr))
{
hr = HrRegQueryString(hKeyPid, c_szInitString, strInitString);
if(SUCCEEDED(hr))
{
hr = HrRegQueryString(hKeyPid, c_szContainerId, strContainerId);
if(SUCCEEDED(hr))
{
hr = HrRegQueryString(hKeyPid, c_szResourcePath, strResourcePath);
if(SUCCEEDED(hr))
{
hr = HrRegQueryDword(hKeyPid, c_szLifeTime, &dwLifeTime);
}
}
}
}
RegCloseKey(hKeyPid);
}
RegCloseKey(hKeyDevices);
}
}
// Set strings to NULL
*pszProgIdDeviceControlClass = NULL;
*pszInitString = NULL;
*pszContainerId = NULL;
*pszResourcePath = NULL;
// On success set the out params
if(SUCCEEDED(hr))
{
hr = strProgIdDeviceControlClass.HrGetCOM(pszProgIdDeviceControlClass);
if(SUCCEEDED(hr))
{
hr = strInitString.HrGetCOM(pszInitString);
if(SUCCEEDED(hr))
{
hr = strContainerId.HrGetCOM(pszContainerId);
if(SUCCEEDED(hr))
{
hr = strResourcePath.HrGetCOM(pszResourcePath);
if(SUCCEEDED(hr))
{
*pnLifeTime = dwLifeTime;
}
}
}
}
if(FAILED(hr))
{
// If one fails, they all fail
if(pszInitString)
{
CoTaskMemFree(pszInitString);
*pszInitString = NULL;
}
if(pszContainerId)
{
CoTaskMemFree(pszContainerId);
*pszContainerId = NULL;
}
if(pszResourcePath)
{
CoTaskMemFree(pszResourcePath);
*pszResourcePath = NULL;
}
}
}
TraceHr(ttidError, FAL, hr, FALSE, "CDevicePersistenceManager::LookupPhysicalDevice");
return hr;
}
STDMETHODIMP CDevicePersistenceManager::RemovePhysicalDevice(
/*[in]*/ REFGUID guidPhysicalDeviceIdentifier)
{
HRESULT hr = S_OK;
// Create the string to use
CUString strUuid;
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
if (SUCCEEDED(hr))
{
hr = strUuid.HrInitFromGUID(guidPhysicalDeviceIdentifier);
}
if(SUCCEEDED(hr))
{
HKEY hKeyDevices;
hr = HrCreateOrOpenDevicesKey(&hKeyDevices);
if(SUCCEEDED(hr))
{
hr = HrRegDeleteKeyTree(hKeyDevices, strUuid);
RegCloseKey(hKeyDevices);
}
}
TraceHr(ttidError, FAL, hr, FALSE, "CDevicePersistenceManager::RemovePhysicalDevice");
return hr;
}
STDMETHODIMP CDevicePersistenceManager::GetPhysicalDevices(
/*[out]*/ long * pnDevices,
/*[out, size_is(,*pnDevices)]*/
GUID ** parguidPhysicalDeviceIdentifiers)
{
CHECK_POINTER(pnDevices);
CHECK_POINTER(parguidPhysicalDeviceIdentifiers);
// Set this to NULL at the beginning
*parguidPhysicalDeviceIdentifiers = NULL;
HRESULT hr = S_OK;
// Do work in an array
CUArray<GUID> arPids;
HKEY hKeyDevices;
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
if (SUCCEEDED(hr))
{
// Open devices key
hr = HrCreateOrOpenDevicesKey(&hKeyDevices);
}
if(SUCCEEDED(hr))
{
DWORD dwSize;
wchar_t szBuf[_MAX_PATH];
FILETIME ft;
DWORD dwIndex = 0;
UUID uuid;
while(SUCCEEDED(hr))
{
// Enumerate all of the keys
dwSize = _MAX_PATH;
hr = HrRegEnumKeyEx(hKeyDevices, dwIndex, szBuf, &dwSize, NULL, NULL, &ft);
++dwIndex;
if(S_OK == hr)
{
hr = CLSIDFromString(szBuf, &uuid);
if(SUCCEEDED(hr))
{
hr = arPids.HrPushBack(uuid);
}
else
{
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CDevicePersistenceManager::GetPhysicalDevices - CLSIDFromString failed!");
hr = S_OK;
// Ignore and skip it - this shouldn't happen
continue;
}
}
else
{
// This is not an error, we are out of subkeys
hr = S_OK;
break;
}
}
RegCloseKey(hKeyDevices);
}
// Attempt to copy to output parameters
if(SUCCEEDED(hr))
{
long nCount = arPids.GetCount();
if(nCount)
{
// Allocate output array
HrCoTaskMemAllocArray(nCount, parguidPhysicalDeviceIdentifiers);
// Fill in array
for(long n = 0; n < nCount; ++n)
{
(*parguidPhysicalDeviceIdentifiers)[n] = arPids[n];
}
}
else
{
*parguidPhysicalDeviceIdentifiers = NULL;
}
*pnDevices = nCount;
}
if(FAILED(hr))
{
*pnDevices = 0;
if(*parguidPhysicalDeviceIdentifiers)
{
CoTaskMemFree(*parguidPhysicalDeviceIdentifiers);
}
*parguidPhysicalDeviceIdentifiers = NULL;
}
TraceHr(ttidError, FAL, hr, FALSE, "CDevicePersistenceManager::GetPhysicalDevices");
return hr;
}
STDMETHODIMP CDevicePersistenceManager::SaveDeviceProvider(
/*[in, string]*/ const wchar_t * szProviderName,
/*[in, string]*/ const wchar_t * szProgIdProviderClass,
/*[in, string]*/ const wchar_t * szInitString,
/*[in, string]*/ const wchar_t * szContainerId)
{
CHECK_POINTER(szProviderName);
CHECK_POINTER(szProgIdProviderClass);
CHECK_POINTER(szInitString);
CHECK_POINTER(szContainerId);
HRESULT hr = S_OK;
HKEY hKeyProviders;
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
if (SUCCEEDED(hr))
{
hr = HrCreateOrOpenProvidersKey(&hKeyProviders);
}
if(SUCCEEDED(hr))
{
// Create key to house values
HKEY hKeyProviderName;
DWORD dwDisposition = 0;
hr = HrRegCreateKeyEx(hKeyProviders, szProviderName, 0, KEY_ALL_ACCESS, NULL, &hKeyProviderName, &dwDisposition);
if(SUCCEEDED(hr))
{
// Save all of the values
hr = HrRegSetSz(hKeyProviderName, c_szProgIdProviderClass, szProgIdProviderClass);
if(SUCCEEDED(hr))
{
hr = HrRegSetSz(hKeyProviderName, c_szInitString, szInitString);
if(SUCCEEDED(hr))
{
hr = HrRegSetSz(hKeyProviderName, c_szContainerId, szContainerId);
}
}
RegCloseKey(hKeyProviderName);
if(FAILED(hr))
{
// If anything fails, remove the whole tree
HrRegDeleteKeyTree(hKeyProviders, szProviderName);
}
}
RegCloseKey(hKeyProviders);
}
TraceHr(ttidError, FAL, hr, FALSE, "CDevicePersistenceManager::SaveDeviceProvider");
return hr;
}
STDMETHODIMP CDevicePersistenceManager::LookupDeviceProvider(
/*[in, string]*/ const wchar_t * szProviderName,
/*[out, string]*/ wchar_t ** pszProgIdProviderClass,
/*[out, string]*/ wchar_t ** pszInitString,
/*[out, string]*/ wchar_t ** pszContainerId)
{
CHECK_POINTER(szProviderName);
CHECK_POINTER(pszProgIdProviderClass);
CHECK_POINTER(pszInitString);
CHECK_POINTER(pszContainerId);
HRESULT hr = S_OK;
CUString strProgIdProviderClass;
CUString strInitString;
CUString strContainerId;
HKEY hKeyProviders;
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
if (SUCCEEDED(hr))
{
hr = HrCreateOrOpenProvidersKey(&hKeyProviders);
}
if(SUCCEEDED(hr))
{
// Open the key housing the values
HKEY hKeyProviderName;
DWORD dwDisposition = 0;
hr = HrRegOpenKeyEx(hKeyProviders, szProviderName, KEY_ALL_ACCESS, &hKeyProviderName);
if(SUCCEEDED(hr))
{
// Load all of the values
hr = HrRegQueryString(hKeyProviderName, c_szProgIdProviderClass, strProgIdProviderClass);
if(SUCCEEDED(hr))
{
hr = HrRegQueryString(hKeyProviderName, c_szInitString, strInitString);
if(SUCCEEDED(hr))
{
hr = HrRegQueryString(hKeyProviderName, c_szContainerId, strContainerId);
}
}
RegCloseKey(hKeyProviderName);
}
RegCloseKey(hKeyProviders);
}
// Set strings to NULL
*pszProgIdProviderClass = NULL;
*pszInitString = NULL;
*pszContainerId = NULL;
// On success set the out params
if(SUCCEEDED(hr))
{
hr = strProgIdProviderClass.HrGetCOM(pszProgIdProviderClass);
if(SUCCEEDED(hr))
{
hr = strInitString.HrGetCOM(pszInitString);
if(SUCCEEDED(hr))
{
hr = strContainerId.HrGetCOM(pszContainerId);
}
}
if(FAILED(hr))
{
// If one fails, they all fail
if(pszInitString)
{
CoTaskMemFree(pszInitString);
*pszInitString = NULL;
}
if(pszContainerId)
{
CoTaskMemFree(pszContainerId);
*pszContainerId = NULL;
}
}
}
TraceHr(ttidError, FAL, hr, FALSE, "CDevicePersistenceManager::LookupDeviceProvider");
return hr;
}
STDMETHODIMP CDevicePersistenceManager::RemoveDeviceProvider(
/*[in, string]*/ const wchar_t * szProviderName)
{
HRESULT hr = S_OK;
HKEY hKeyProviders;
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
if (SUCCEEDED(hr))
{
hr = HrCreateOrOpenProvidersKey(&hKeyProviders);
}
if(SUCCEEDED(hr))
{
hr = HrRegDeleteKeyTree(hKeyProviders, szProviderName);
RegCloseKey(hKeyProviders);
}
TraceHr(ttidError, FAL, hr, FALSE, "CDevicePersistenceManager::RemoveDeviceProvider");
return hr;
}
STDMETHODIMP CDevicePersistenceManager::GetDeviceProviders(
/*[out]*/ long * pnProviders,
/*[out, string, size_is(,*pnProviders,)]*/
wchar_t *** parszProviderNames)
{
CHECK_POINTER(pnProviders);
CHECK_POINTER(parszProviderNames);
// Set this to NULL at the beginning
*parszProviderNames = NULL;
HRESULT hr = S_OK;
// Do work in an array
CUArray<wchar_t*> arszProviders;
HKEY hKeyProviders;
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
if (SUCCEEDED(hr))
{
// Open devices key
hr = HrCreateOrOpenProvidersKey(&hKeyProviders);
}
if(SUCCEEDED(hr))
{
DWORD dwSize;
wchar_t szBuf[_MAX_PATH];
FILETIME ft;
DWORD dwIndex = 0;
while(SUCCEEDED(hr))
{
// Enumerate all of the keys
dwSize = _MAX_PATH;
hr = HrRegEnumKeyEx(hKeyProviders, dwIndex, szBuf, &dwSize, NULL, NULL, &ft);
if(S_OK == hr)
{
wchar_t * sz = NULL;
hr = HrCoTaskMemAllocString(szBuf, &sz);
if(SUCCEEDED(hr))
{
// Insert pointer to dynamically allocated string
hr = arszProviders.HrPushBack(sz);
}
}
else
{
// This is not an error, we have no more subkeys
hr = S_OK;
break;
}
++dwIndex;
}
RegCloseKey(hKeyProviders);
}
// Attempt to copy to output parameters
if(SUCCEEDED(hr))
{
long nCount = arszProviders.GetCount();
if(nCount)
{
// Allocate output array
HrCoTaskMemAllocArray(nCount, parszProviderNames);
// Fill in array
for(long n = 0; n < nCount; ++n)
{
(*parszProviderNames)[n] = arszProviders[n];
}
}
else
{
*parszProviderNames = NULL;
}
*pnProviders = nCount;
}
if(FAILED(hr))
{
*pnProviders = 0;
if(*parszProviderNames)
{
CoTaskMemFree(*parszProviderNames);
}
*parszProviderNames = NULL;
// Cleanup dynamically allocated strings
long nCount = arszProviders.GetCount();
for(long n = 0; n < nCount; ++n)
{
CoTaskMemFree(arszProviders[n]);
}
}
TraceHr(ttidError, FAL, hr, FALSE, "CDevicePersistenceManager::GetDeviceProviders");
return hr;
}