mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
975 lines
31 KiB
975 lines
31 KiB
//+--------------------------------------------------------------------------
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
|