windows-nt/Source/XPSP1/NT/net/config/netcfg/engine/provider.cpp

976 lines
31 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996.
//
// File: P R O V I D E R . C P P
//
// Contents: Net component installer functions for Net providers.
//
// Notes:
//
// Author: billbe 22 Mar 1997
//
//---------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "ncreg.h"
#include "ncsetup.h"
#include "ncsvc.h"
#include "provider.h"
#include "winspool.h"
#include "ncmisc.h"
// constants
//
extern const WCHAR c_szDevice[];
extern const WCHAR c_szProviderOrder[];
extern const WCHAR c_szRegKeyCtlNPOrder[];
extern const WCHAR c_szRegKeyServices[];
const WCHAR c_chComma = L',';
const WCHAR c_szDeviceName[] = L"DeviceName";
const WCHAR c_szDisplayName[] = L"DisplayName";
const WCHAR c_szInfKeyPrintProviderDll[] = L"PrintProviderDll";
const WCHAR c_szInfSubKeyPrintProvider[] = L"PrintProvider";
const WCHAR c_szNetworkProvider[] = L"NetworkProvider";
const WCHAR c_szPrintProviderName[] = L"PrintProviderName";
const WCHAR c_szRegKeyPrintProviders[] = L"System\\CurrentControlSet\\Control\\Print\\Providers";
const WCHAR c_szRegKeyShortName[] = L"System\\CurrentControlSet\\Control\\NetworkProvider\\ShortName";
const WCHAR c_szRegValueName[] = L"Name";
const WCHAR c_szRegValueOrder[] = L"Order";
const WCHAR c_szShortName[] = L"ShortName";
// Functions
//
HRESULT
HrCiCreateShortNameValueIfNeeded(HINF hinf, HKEY hkeyNetworkProvider,
const tstring& strSection,
tstring* pstrShortName);
HRESULT
HrCiSetDeviceName(HINF hinf, HKEY hkeyNetworkProvider,
const tstring& strSection, const tstring& strServiceName);
HRESULT
HrCiWritePrintProviderInfoIfNeeded(HINF hinfFile, const tstring& strSection,
HKEY hkeyInstance, DWORD dwPrintPosition);
HRESULT
HrCiAddPrintProvider(const tstring& strName, const tstring& strDllName,
const tstring& strDisplayName, DWORD dwPrintPosition);
HRESULT
HrCiDeletePrintProviderIfNeeded(HKEY hkeyInstance, DWORD* pdwProviderPosition);
//+--------------------------------------------------------------------------
//
// Function: HrCiAddNetProviderInfo
//
// Purpose: Adds the current component to the list of network
// providers and also adds it as a print provider if
// necessary.
//
// Arguments:
// hinf [in] Handle to component's inf file
// strSection [in] Main inf section
// hkeyInstance [in] Component's instance key
// fPreviouslyInstalled [in] TRUE if this component is being
// reinstalled, FALSE otherwise
//
// Returns: HRESULT. S_OK if successful, an error code otherwise
//
// Author: billbe 22 Mar 1997
// updated 7 Oct 1997
//
// Notes:
//
HRESULT
HrCiAddNetProviderInfo(HINF hinf, PCWSTR pszSection,
HKEY hkeyInstance, BOOL fPreviouslyInstalled)
{
Assert(IsValidHandle(hinf));
Assert(pszSection);
Assert(hkeyInstance);
//tstring strServiceName;
DWORD dwNetworkPosition = 0; // default position is the front.
DWORD dwPrintPosition = 0; // default position is the front.
if (fPreviouslyInstalled)
{
// Because the inf may contain modifications to the print provider.
// e.g. Display name change, dll name change, etc. We delete it
// then readd. We would like to just update the information
// but the print provider api doesn't support it yet. Until
// then, we need to delete and readd to pick up changes.
//
(void) HrCiDeleteNetProviderInfo(hkeyInstance, &dwNetworkPosition,
&dwPrintPosition);
TraceTag(ttidClassInst, "Upgrading provider info. Net Prov Pos %d "
"Print Prov Pos %d", dwNetworkPosition, dwPrintPosition);
}
// Get the service name for this component
WCHAR szServiceName[MAX_SERVICE_NAME_LEN];
DWORD cbServiceName = MAX_SERVICE_NAME_LEN * sizeof(WCHAR);
HKEY hkeyNdi;
HRESULT hr = HrRegOpenKeyEx (hkeyInstance, L"Ndi", KEY_READ, &hkeyNdi);
if (S_OK == hr)
{
hr = HrRegQuerySzBuffer (
hkeyNdi,
L"Service",
szServiceName,
&cbServiceName);
RegCloseKey (hkeyNdi);
}
if (S_OK == hr)
{
// If this is Webclient we need to make sure it is after
// lanmanworkstation in the ordering. This should be temporary
// until mpr.dll is updated to return the union of provider
// information. Right now a server can source smb shares and
// webclient shares but only one set can be retrieved via the mpr.
// Since smb shares are more common, lanmanworkstation needs to be
// before webclient. When mpr.dll changes, both sets will be returned
// and ordering shouldn't matter (expect for performance).
//
if (0 == lstrcmpiW(szServiceName, L"WebClient"))
{
HKEY hkeyNP;
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyCtlNPOrder,
KEY_READ, &hkeyNP);
if (S_OK == hr)
{
PWSTR Order;
hr = HrRegQuerySzWithAlloc(hkeyNP, c_szProviderOrder, &Order);
if (S_OK == hr)
{
DWORD dwPosition;
if (FFindStringInCommaSeparatedList(L"LanmanWorkstation",
Order, NC_IGNORE, &dwPosition))
{
dwNetworkPosition = dwPosition + 1;
}
delete [] Order;
}
RegCloseKey(hkeyNP);
}
}
TraceTag(ttidClassInst, "Adding %S to the network provider "
"order at position %d\n", szServiceName, dwNetworkPosition);
// Add it to the list of network providers
hr = HrRegAddStringToSz(szServiceName, HKEY_LOCAL_MACHINE,
c_szRegKeyCtlNPOrder, c_szProviderOrder,
c_chComma, STRING_FLAG_ENSURE_AT_INDEX, dwNetworkPosition);
if (S_OK == hr)
{
tstring strNetworkProvider = c_szRegKeyServices;
strNetworkProvider.append(L"\\");
strNetworkProvider.append(szServiceName);
strNetworkProvider.append(L"\\");
strNetworkProvider.append(c_szNetworkProvider);
// Open the NetworkProvider key under the component's
// service key
//
HKEY hkey;
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE,
strNetworkProvider.c_str(), KEY_SET_VALUE | KEY_READ,
&hkey);
if (S_OK == hr)
{
// Check if shortname is needed.
// by looking for it in the option
// <main install section>.NetworkProvider section
//
tstring strNetworkSection(pszSection);
strNetworkSection += L'.';
strNetworkSection += c_szNetworkProvider;
tstring strShortName;
HRESULT hr = HrCiCreateShortNameValueIfNeeded(hinf,
hkey, strNetworkSection, &strShortName);
if (S_OK == hr)
{
// If shortname was created then we need to
// also store it under the instance
// key so we can remove it when the component
// is removed
(void) HrRegSetString(hkeyInstance,
c_szShortName, strShortName);
}
// Set the device name in the NetworkProvider key
// under the componet's service key
//
if (SUCCEEDED(hr))
{
hr = HrCiSetDeviceName(hinf, hkey, strNetworkSection,
szServiceName);
}
RegCloseKey(hkey);
}
}
}
// Write out any print provider information if the inf file specifies it
//
if (S_OK == hr)
{
hr = HrCiWritePrintProviderInfoIfNeeded(hinf, pszSection,
hkeyInstance, dwPrintPosition);
}
TraceHr (ttidError, FAL, hr, FALSE, "HrCiAddNetProviderInfo");
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: HrCiDeleteNetProviderInfo
//
// Purpose: Deletes the current component from the list of network
// providers and also deletes it as a print provider if
// necessary.
//
// Arguments:
// hkeyInstance [in] The handle to the component's isntance key.
// pdwNetworkPosition [out] Optional. The positon pf this component in
// the network provider order before removal.
// pdwPrintPosition [out] Optional. The positon of this component in
// the print provider order before removal.
//
// Returns: HRESULT. S_OK if successful, an error code otherwise
//
// Author: billbe 22 Mar 1997
// updated 7 Oct 1997
//
// Notes:
//
HRESULT
HrCiDeleteNetProviderInfo(HKEY hkeyInstance, DWORD* pdwNetworkPosition,
DWORD* pdwPrintPosition)
{
Assert(hkeyInstance);
// Initialize out param.
if (pdwNetworkPosition)
{
*pdwNetworkPosition = 0;
}
// Initialize out param.
if (pdwPrintPosition)
{
*pdwPrintPosition = 0;
}
WCHAR szServiceName[MAX_SERVICE_NAME_LEN];
DWORD cbServiceName = MAX_SERVICE_NAME_LEN * sizeof(WCHAR);
// Get the service name for this component.
HKEY hkeyNdi;
HRESULT hr = HrRegOpenKeyEx (hkeyInstance, L"Ndi", KEY_READ, &hkeyNdi);
if (S_OK == hr)
{
hr = HrRegQuerySzBuffer (
hkeyNdi,
L"Service",
szServiceName,
&cbServiceName);
RegCloseKey(hkeyNdi);
}
if (S_OK == hr)
{
// Open the network provider key.
//
HKEY hkeyNetProvider;
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyCtlNPOrder,
KEY_READ_WRITE, &hkeyNetProvider);
if (S_OK == hr)
{
PWSTR pszOrder = NULL;
PWSTR pszNewOrder;
DWORD dwNetPos;
// Get the current list of providers.
//
hr = HrRegQuerySzWithAlloc(hkeyNetProvider,
c_szProviderOrder, &pszOrder);
// If we managed to get the list and the provider we are
// removing is in the list...
//
if ((S_OK == hr) && FFindStringInCommaSeparatedList(
szServiceName, pszOrder,
NC_IGNORE, &dwNetPos))
{
// Remove the provider from the list.
hr = HrRemoveStringFromDelimitedSz(szServiceName,
pszOrder, c_chComma, STRING_FLAG_REMOVE_ALL,
&pszNewOrder);
if (S_OK == hr)
{
// Set the new provider list back in the registry.
(void) HrRegSetSz(hkeyNetProvider, c_szProviderOrder,
pszNewOrder);
MemFree (pszNewOrder);
}
// If the out param was specified, set the position.
//
if (pdwNetworkPosition)
{
*pdwNetworkPosition = dwNetPos;
}
}
MemFree(pszOrder);
RegCloseKey(hkeyNetProvider);
}
if (S_OK == hr)
{
// If short name was used, we need to remove it
//
tstring strShortName;
hr = HrRegQueryString(hkeyInstance, c_szShortName, &strShortName);
if (S_OK == hr)
{
// ShortName was used so remove it
//
HKEY hkey;
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyShortName,
KEY_SET_VALUE, &hkey);
if (S_OK == hr)
{
hr = HrRegDeleteValue(hkey, strShortName.c_str());
// delete from our instance key as well
// Note: we do this because if this component is being
// reinstalled, the new inf might not have shortname so
// we don't want the old value lying around
(void) HrRegDeleteValue(hkeyInstance, c_szShortName);
RegCloseKey(hkey);
}
}
// If the value wasn't there (in the driver key or the ShortName key,
// then there is nothing to delete and everything is okay
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
{
hr = S_OK;
}
}
}
// Delete this component as a print provider if necessary
//
if (S_OK == hr)
{
hr = HrCiDeletePrintProviderIfNeeded(hkeyInstance, pdwPrintPosition);
}
TraceHr (ttidError, FAL, hr, FALSE, "HrCiDeleteNetProviderInfo");
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: HrCiCreateShortNameValueIfNeeded
//
// Purpose: Creates the short name value for the component under
// the c_szRegKeyShortName registry key if short name is
// present in the inf. The short name value is set to the
// display name as found in the NetworkProvider key under
// the component's service key
//
// Arguments:
// hinf [in] Handle to the component's inf
// hkeyNetworkProvider [in] The hkey to the NetworkProvider
// key under the component's service
// key
// strSection [in] The section name where ShortName
// would be located
// pstrShortName [out] The short name found in the inf
//
// Returns: HRESULT. S_OK if shortname found, S_FALSE if no shortname was
// found, or error code otherwise.
//
// Author: billbe 7 Oct 1997
//
// Notes:
//
HRESULT
HrCiCreateShortNameValueIfNeeded(HINF hinf, HKEY hkeyNetworkProvider,
const tstring& strSection,
tstring* pstrShortName)
{
Assert(IsValidHandle(hinf));
Assert(hkeyNetworkProvider);
Assert(!strSection.empty());
Assert(pstrShortName);
INFCONTEXT ctx;
// Look for optional shortname
HRESULT hr = HrSetupFindFirstLine(hinf, strSection.c_str(),
c_szShortName, &ctx);
if (SUCCEEDED(hr))
{
// Get the shortname value
hr = HrSetupGetStringField(ctx, 1, pstrShortName);
if (SUCCEEDED(hr))
{
HKEY hkey;
// Create the ShortName key
hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE,
c_szRegKeyShortName, REG_OPTION_NON_VOLATILE,
KEY_SET_VALUE, NULL, &hkey, NULL);
if (SUCCEEDED(hr))
{
// Get the provider name to set the short name value
//
tstring strProviderName;
hr = HrRegQueryString(hkeyNetworkProvider, c_szRegValueName,
&strProviderName);
if (SUCCEEDED(hr))
{
// create the component's short name value under
// the ShortName key and set it to the component's
// display name
hr = HrRegSetString(hkey, pstrShortName->c_str(),
strProviderName);
}
RegCloseKey(hkey);
}
}
}
// The line and section were optional so if it didn't exists return S_FALSE
if ((SPAPI_E_LINE_NOT_FOUND == hr) ||
(SPAPI_E_BAD_SECTION_NAME_LINE == hr))
{
hr = S_FALSE;
}
// On failure, initialize the out param
if (FAILED(hr))
{
pstrShortName->erase();
}
TraceHr (ttidError, FAL, hr, S_FALSE == hr,
"HrCiCreateShortNameValueIfNeeded");
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: HrCiSetDeviceName
//
// Purpose: Creates the device name value for the component under
// the NetworkProvider key located in the component's
// service key. The device name by default is
// \Device\<component's service name> unless the inf
// specifies a new device name.
//
// Arguments:
// hinf [in] Handle to the component's inf
// hkeyNetworkProvider [in] The hkey to the NetworkProvider
// key under the component's service
// key
// strSection [in] The section name where ShortName
// would be located
// strServiceName [in] The component's service name
//
// Returns: HRESULT. S_OK if successful, or error code otherwise.
//
// Author: billbe 7 Oct 1997
//
// Notes:
//
HRESULT
HrCiSetDeviceName(HINF hinf, HKEY hkeyNetworkProvider,
const tstring& strSection, const tstring& strServiceName)
{
Assert(IsValidHandle(hinf));
Assert(hkeyNetworkProvider);
INFCONTEXT ctx;
tstring strDeviceName = c_szDevice;
// Look for optional DeviceName
HRESULT hr = HrSetupFindFirstLine(hinf, strSection.c_str(),
c_szDeviceName, &ctx);
if (SUCCEEDED(hr))
{
tstring strName;
// Get the DeviceName value
hr = HrSetupGetStringField(ctx, 1, &strName);
if (SUCCEEDED(hr))
{
// append it to the current value
strDeviceName.append(strName);
}
}
// If the device name line was not found in the inf (or the
// section name wasn't found), use the service name
//
if ((SPAPI_E_LINE_NOT_FOUND == hr) ||
(SPAPI_E_BAD_SECTION_NAME_LINE == hr))
{
strDeviceName.append(strServiceName);
hr = S_OK;
}
if (SUCCEEDED(hr))
{
// Now set the device name value in the service's networkprovider key
hr = HrRegSetString(hkeyNetworkProvider, c_szDeviceName,
strDeviceName);
}
TraceHr (ttidError, FAL, hr, FALSE, "HrCiSetDeviceName");
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: HrCiGetPrintProviderInfoFromInf
//
// Purpose: This function gets the display name and dll name from
// the print provider section strSection.
//
// Arguments:
// hinf [in] handle to inf file. See SetupApi for more info
// strSection [in] The print provider section name
// pstrName [out] The print provider name found in the inf
// pstrDll [out] The dll name found in the inf
// pstrDisplayName [out] The localized display name found in the inf
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 24 Oct 1997
//
// Notes:
HRESULT
HrCiGetPrintProviderInfoFromInf(HINF hinf, tstring strSection, tstring* pstrName,
tstring* pstrDll, tstring* pstrDisplayName)
{
Assert(!strSection.empty());
Assert(pstrName);
Assert(pstrDll);
Assert(pstrDisplayName);
INFCONTEXT ctx;
// find the line containing non-localized ProviderName
HRESULT hr = HrSetupFindFirstLine(hinf, strSection.c_str(),
c_szPrintProviderName, &ctx);
if (S_OK == hr)
{
// Get the ProviderName
hr = HrSetupGetStringField(ctx, 1, pstrName);
if (S_OK == hr)
{
// Now find and get the PrintProviderDll value
//
hr = HrSetupFindFirstLine(hinf, strSection.c_str(),
c_szInfKeyPrintProviderDll, &ctx);
if (S_OK == hr)
{
hr = HrSetupGetStringField(ctx, 1, pstrDll);
if (S_OK == hr)
{
// find the line containing DisplayName
hr = HrSetupFindFirstLine(hinf, strSection.c_str(),
c_szDisplayName, &ctx);
if (S_OK == hr)
{
// Get the DisplayName
hr = HrSetupGetStringField(ctx, 1, pstrDisplayName);
}
}
}
}
}
TraceHr (ttidError, FAL, hr, FALSE, "HrCiGetPrintProviderInfoFromInf");
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: HrCiWritePrintProviderInfoIfNeeded
//
// Purpose: This function updates necessary registry entries for
// NETCLIENT class components that are print providers.
//
// Arguments:
// hinf [in] handle to inf file. See SetupApi for more info.
// strSection [in] The main section name.
// hkeyInstance [in] The hkey to the component's instance key.
// dwPrintPosition [in] The position to place the print provider when
// it is added to the list.
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 22 Mar 1997
// updated 7 Oct 1997
//
// Notes:
HRESULT
HrCiWritePrintProviderInfoIfNeeded(HINF hinf, const tstring& strSection,
HKEY hkeyInstance, DWORD dwPrintPosition)
{
Assert(IsValidHandle(hinf));
Assert(!strSection.empty());
Assert(hkeyInstance);
HRESULT hr = S_OK;
INFCONTEXT ctx;
tstring strDisplayName;
tstring strName;
tstring strPrintProviderDll;
tstring strPrintSection(strSection);
strPrintSection.append(L".");
strPrintSection.append(c_szInfSubKeyPrintProvider);
// First we check for the PrintProvider inf section
hr = HrSetupFindFirstLine(hinf, strPrintSection.c_str(), NULL,
&ctx);
if (S_OK == hr)
{
// Get the print provider information from the inf
hr = HrCiGetPrintProviderInfoFromInf(hinf, strPrintSection,
&strName, &strPrintProviderDll, &strDisplayName);
if (S_OK == hr)
{
// Add the component as a print provider
hr = HrCiAddPrintProvider(strName, strPrintProviderDll,
strDisplayName, dwPrintPosition);
// Now write the Provider name under our instance key
// so we can remove this provider when asked
if (S_OK == hr)
{
(void) HrRegSetString(hkeyInstance,
c_szPrintProviderName, strName);
}
}
}
else
{
// The section is optional so this is not an error
if (SPAPI_E_LINE_NOT_FOUND == hr)
{
hr = S_OK;
}
}
TraceHr (ttidError, FAL, hr, FALSE, "HrCiWritePrintProviderInfoIfNeeded");
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: MoveProviderToIndex
//
// Purpose: This function moves the pszProviderName to the position
// specified.
//
// Arguments:
// pszProviderName [in] Name of the print provider (used in call to
// AddPrintProvidor.
// dwPrintPosition [in] The index to place this provider in the
// provider order.
//
// Returns: nothing
//
// Author: billbe 6 Oct 1998
//
// Notes:
//
VOID
MoveProviderToIndex (
IN PCWSTR pszProviderName,
IN DWORD dwPrintPosition)
{
PROVIDOR_INFO_2 p2info;
// Open the print provider key
//
HKEY hkey;
HRESULT hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyPrintProviders,
KEY_READ, &hkey);
if (S_OK == hr)
{
// Retrieve the current order
//
PWSTR pmszOrder;
hr = HrRegQueryMultiSzWithAlloc(hkey, c_szRegValueOrder, &pmszOrder);
if (S_OK == hr)
{
PWSTR pmszNewOrder;
BOOL fChanged;
// Move the provider to the front
//
hr = HrAddSzToMultiSz(pszProviderName, pmszOrder,
STRING_FLAG_ENSURE_AT_INDEX, dwPrintPosition,
&pmszNewOrder, &fChanged);
if ((S_OK == hr) && fChanged)
{
// Notify Spooler that we want to change the order
//
p2info.pOrder = pmszNewOrder;
if (!AddPrintProvidor(NULL, 2, (LPBYTE)&p2info))
{
hr = HrFromLastWin32Error();
// If we removed duplicates, the last call to
// AddPrintProvidor may have failed with
// ERROR_INVALID_PARAMETER. Trying again will correct
// the problem.
//
if (HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER) == hr)
{
AddPrintProvidor(NULL, 2,
reinterpret_cast<LPBYTE>(&p2info));
}
TraceHr (ttidError, FAL, hr, FALSE,
"AddPrintProvider(class 2) returned an error");
}
MemFree(pmszNewOrder);
}
MemFree(pmszOrder);
}
TraceHr (ttidError, FAL, hr, FALSE, "MoveProviderToIndex");
RegCloseKey(hkey);
}
}
//+--------------------------------------------------------------------------
//
// Function: HrCiAddPrintProvider
//
// Purpose: This function calls the AddPrintProvidor [sic] function
// to add the current component as a provider.
//
// Arguments:
// strName [in] Name of the print provider (used in call to
// AddPrintProvidor.
// strDllName [in] Dll name of the print provider.
// strDisplayName [in] Localized Display Name.
// dwPrintPosition [in] The position to place this provider when it
// is added to the list.
//
// Returns: HRESULT. S_OK if successful, error code otherwise.
//
// Author: billbe 22 Mar 1997
// updated 7 Oct 1997
//
// Notes: See AddPrintProvidor Win32 fcn for more info
HRESULT
HrCiAddPrintProvider(
const tstring& strName,
const tstring& strDllName,
const tstring& strDisplayName,
DWORD dwPrintPosition)
{
Assert(!strName.empty());
Assert(!strDllName.empty());
PROVIDOR_INFO_1 pi1;
HRESULT hr=S_OK;
// Fill the structure with the relevant info
//
pi1.pEnvironment = NULL;
pi1.pDLLName = (PWSTR)strDllName.c_str();
pi1.pName = (PWSTR)strName.c_str();
hr = HrEnableAndStartSpooler();
if (S_OK == hr)
{
if (!AddPrintProvidor(NULL, 1, reinterpret_cast<LPBYTE>(&pi1)))
{
// convert the error
hr = HrFromLastWin32Error();
}
}
if (S_OK == hr)
{
// AddPrintProvidor adds the print provider to the end of list.
// 99% of the time, the goal is to have the provider be somewhere
// else. We will attempt to move it to the position given to us. This
// is either the beginning of the list or the previous position of
// this provider (i.e. if we are reinstalling) If it fails we can
// still go on.
(void) MoveProviderToIndex(pi1.pName, dwPrintPosition);
tstring strPrintProvider = c_szRegKeyPrintProviders;
strPrintProvider.append(L"\\");
strPrintProvider.append(strName);
HKEY hkey;
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE,
strPrintProvider.c_str(),
KEY_SET_VALUE, &hkey);
if (S_OK == hr)
{
// Write DisplayName in the new key created by the
// AddPrintProvidor [sic] call.
// Not sure who the consumer of this value is but
// the NT4 code did this
hr = HrRegSetString(hkey, c_szDisplayName, strDisplayName);
RegCloseKey(hkey);
}
}
TraceHr (ttidError, FAL, hr, FALSE, "HrCiAddPrintProvider");
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: HrCiDeletePrintProviderIfNeeded
//
// Purpose: This function calls the DeletePrintProvidor [sic] function
// if this component was a print provider
//
// Arguments:
// hkeyInstance [in] The hkey for the component's instance key.
// pdwProviderPosition [out] Optional. The position of the print
// provider in the order list before it was
// deleted.
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 22 Mar 1997
// updated 7 Oct 1997
//
// Notes: See DeletePrintProvidor Win32 fcn for more info
//
HRESULT
HrCiDeletePrintProviderIfNeeded(HKEY hkeyInstance, DWORD* pdwProviderPosition)
{
// Check if this component is a print provider
//
tstring strName;
HRESULT hr = HrRegQueryString(hkeyInstance, c_szPrintProviderName,
&strName);
if (SUCCEEDED(hr))
{
// If the out param was specified, we may need to get the current position of this print provider
// in the list of providers
if (pdwProviderPosition)
{
*pdwProviderPosition = 0;
// Open the print key
//
HKEY hkeyPrint;
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyPrintProviders,
KEY_READ, &hkeyPrint);
if (SUCCEEDED(hr))
{
// Get the current order of providers
//
PWSTR pmszOrder;
hr = HrRegQueryMultiSzWithAlloc(hkeyPrint,
c_szRegValueOrder, &pmszOrder);
if (S_OK == hr)
{
// Get this provider's current position
(void) FGetSzPositionInMultiSzSafe(
strName.c_str(), pmszOrder, pdwProviderPosition,
NULL, NULL);
MemFree(pmszOrder);
}
RegCloseKey(hkeyPrint);
}
}
// The component was a print provider so we need to delete it as such
//
DeletePrintProvidor(NULL, NULL, (PWSTR)strName.c_str());
// delete from our instance key as well
// Note: we do this because if this component is being
// reinstalled, the new inf might not have a providername so
// we don't want the old value lying around
(void) HrRegDeleteValue(hkeyInstance, c_szPrintProviderName);
}
else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
{
// This component was not a print provider so there
// is nothing to remove
hr = S_OK;
}
TraceHr (ttidError, FAL, hr, FALSE, "HrCiDeletePrintProviderIfNeeded");
return hr;
}