|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: N C S E T U P . C P P
//
// Contents: HRESULT wrappers for the Setup Api.
//
// Notes:
//
// Author: shaunco 16 Apr 1997
//
//----------------------------------------------------------------------------
#include <pch.h>
#pragma hdrstop
#include "ncsetup.h"
#include "ncbase.h"
#include "ncmem.h"
#include "ncstring.h"
#include "ncperms.h"
#include "ncmisc.h"
#include <swenum.h>
extern const WCHAR c_szNo[]; extern const WCHAR c_szYes[];
// dwFieldIndex parameter for the first field. Fields indexes are 1 based
// in Setup Api.
//
const DWORD c_dwFirstField = 1;
//+---------------------------------------------------------------------------
//
// Function: HrSetupCommitFileQueue
//
// Purpose: Initializes the context used by the default queue callback
// routine included with the Setup API in the same manner
// as SetupInitDefaultQueueCallback, except that an
// additional window is provided to the callback function
// to accept progress messages.
//
// Arguments:
// hwndOwner [in] See SetupApi for information
// hfq [in]
// pfc [in]
// pvCtx [in]
//
// Returns: S_OK or a Win32 error code.
//
// Author: billbe 23 July 1997
//
// Notes:
//
HRESULT HrSetupCommitFileQueue(HWND hwndOwner, HSPFILEQ hfq, PSP_FILE_CALLBACK pfc, PVOID pvCtx) { Assert(hfq); Assert(INVALID_HANDLE_VALUE != hfq); Assert(pfc); Assert(pvCtx);
HRESULT hr = S_OK;
// Try to commit the queue
if (!SetupCommitFileQueue(hwndOwner, hfq, pfc, pvCtx)) { hr = HrFromLastWin32Error(); }
TraceError ("HrSetupCommitFileQueue", (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr) ? S_OK : hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupInitDefaultQueueCallbackEx
//
// Purpose: Initializes the context used by the default queue callback
// routine included with the Setup API in the same manner
// as SetupInitDefaultQueueCallback, except that an
// additional window is provided to the callback function
// to accept progress messages.
//
// Arguments:
// hwndOwner [in] See SetupApi for information
// hwndAlternate [in]
// uMsg [in]
// dwReserved1 [in]
// dwReserved2 [in]
// ppvCtx [out]
//
// Returns: S_OK or a Win32 error code.
//
// Author: billbe 23 July 1997
//
// Notes:
//
HRESULT HrSetupInitDefaultQueueCallbackEx(HWND hwndOwner, HWND hwndAlternate, UINT uMsg, DWORD dwReserved1, PVOID pvReserved2, PVOID* ppvCtx) { Assert(ppvCtx);
// Try to init default queue callback.
//
HRESULT hr; PVOID pvCtx = SetupInitDefaultQueueCallbackEx(hwndOwner, hwndAlternate, uMsg, dwReserved1, pvReserved2);
if (pvCtx) { hr = S_OK; *ppvCtx = pvCtx; } else { hr = HrFromLastWin32Error (); *ppvCtx = NULL; }
TraceError ("HrSetupInitDefaultQueueCallbackEx", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupOpenFileQueue
//
// Purpose: Creates a setup file queue.
//
// Arguments:
// phfq [out] See SetupApi for information
//
// Returns: S_OK or a Win32 error code.
//
// Author: billbe 23 July 1997
//
// Notes:
//
HRESULT HrSetupOpenFileQueue(HSPFILEQ* phfq) { Assert(phfq); // Try to open the file queue.
//
HRESULT hr; HSPFILEQ hfq = SetupOpenFileQueue(); if (INVALID_HANDLE_VALUE != hfq) { hr = S_OK; *phfq = hfq; } else { hr = HrFromLastWin32Error (); *phfq = NULL; } TraceError ("HrSetupOpenFileQueue", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupOpenInfFile
//
// Purpose: Open an INF file.
//
// Arguments:
// pszFileName [in] See the Setup API documentation.
// pszInfClass [in]
// dwInfStyle [in]
// punErrorLine [out]
// phinf [out]
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 17 Apr 1997
//
// Notes:
//
HRESULT HrSetupOpenInfFile ( PCWSTR pszFileName, PCWSTR pszInfClass, DWORD dwInfStyle, UINT* punErrorLine, HINF* phinf) { HRESULT hr; HINF hinf;
Assert (pszFileName); Assert (phinf);
// Try to open the file.
//
hinf = SetupOpenInfFile (pszFileName, pszInfClass, dwInfStyle, punErrorLine); if (INVALID_HANDLE_VALUE != hinf) { hr = S_OK; *phinf = hinf; } else { hr = HrFromLastWin32Error (); *phinf = NULL; if (punErrorLine) { *punErrorLine = 0; } } TraceHr (ttidError, FAL, hr, FALSE, "HrSetupOpenInfFile (%S)", pszFileName); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupFindFirstLine
//
// Purpose: Find the first line in an INF file with a matching section
// and key.
//
// Arguments:
// hinf [in] See the Setup API documentation.
// pszSection [in]
// pszKey [in]
// pctx [out]
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 16 Apr 1997
//
// Notes:
//
HRESULT HrSetupFindFirstLine ( IN HINF hinf, IN PCWSTR pszSection, IN PCWSTR pszKey, OUT INFCONTEXT* pctx) { Assert (hinf); Assert (pszSection); Assert (pctx);
HRESULT hr; if (SetupFindFirstLine (hinf, pszSection, pszKey, pctx)) { hr = S_OK; } else { hr = HrFromLastWin32Error (); } TraceErrorOptional ("HrSetupFindFirstLine", hr, (SPAPI_E_LINE_NOT_FOUND == hr)); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupFindNextLine
//
// Purpose: Find the next line in an INF file relative to ctxIn.
//
// Arguments:
// ctxIn [in] See the Setup API documentation.
// pctxOut [out]
//
// Returns: S_OK if successful, S_FALSE if there are no more lines, or a
// Win32 error code.
//
// Author: shaunco 16 Apr 1997
//
// Notes:
//
HRESULT HrSetupFindNextLine (const INFCONTEXT& ctxIn, INFCONTEXT* pctxOut) { Assert (pctxOut);
HRESULT hr; if (SetupFindNextLine (const_cast<PINFCONTEXT>(&ctxIn), pctxOut)) { hr = S_OK; } else { hr = HrFromLastWin32Error (); if (SPAPI_E_LINE_NOT_FOUND == hr) { // Translate ERROR_LINE_NOT_FOUND into S_FALSE
hr = S_FALSE; } } TraceError ("HrSetupFindNextLine", (hr == S_FALSE) ? S_OK : hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupFindNextMatchLine
//
// Purpose: Find the next line in an INF file relative to ctxIn and
// matching an optional key.
//
// Arguments:
// ctxIn [in] See the Setup API documentation.
// pszKey [in]
// pctxOut [out]
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 16 Apr 1997
//
// Notes:
//
HRESULT HrSetupFindNextMatchLine ( IN const INFCONTEXT& ctxIn, IN PCWSTR pszKey, OUT INFCONTEXT* pctxOut) { Assert (pctxOut);
HRESULT hr; if (SetupFindNextMatchLine ((PINFCONTEXT)&ctxIn, pszKey, pctxOut)) { hr = S_OK; } else { hr = HrFromLastWin32Error(); if (SPAPI_E_LINE_NOT_FOUND == hr) { // Translate ERROR_LINE_NOT_FOUND into S_FALSE
hr = S_FALSE; } } TraceError ("HrSetupFindNextMatchLine", (hr == S_FALSE) ? S_OK : hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetLineByIndex
//
// Purpose: Locates a line in an INF file by its index value in the
// specified section.
//
// Arguments:
// hinf [in] See the Setup API documentation.
// pszSection [in]
// dwIndex [in]
// pctx [out]
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 16 Apr 1997
//
// Notes:
//
HRESULT HrSetupGetLineByIndex ( IN HINF hinf, IN PCWSTR pszSection, IN DWORD dwIndex, OUT INFCONTEXT* pctx) { Assert (pszSection); Assert (pctx);
HRESULT hr; if (SetupGetLineByIndex (hinf, pszSection, dwIndex, pctx)) { hr = S_OK; } else { hr = HrFromLastWin32Error (); } TraceError ("HrSetupGetLineByIndex", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetLineCount
//
// Purpose: Get the number of lines in the specified section on an
// INF file.
//
// Arguments:
// hinf [in] See the Setup API documentation.
// pszSection [in]
// pulCount [out]
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 16 Apr 1997
//
// Notes:
//
HRESULT HrSetupGetLineCount ( IN HINF hinf, IN PCWSTR pszSection, OUT ULONG* pulCount) { Assert (pszSection); Assert (pulCount);
HRESULT hr; LONG lCount = SetupGetLineCount (hinf, pszSection); if (-1 != lCount) { *pulCount = lCount; hr = S_OK; } else { *pulCount = 0; hr = HrFromLastWin32Error (); } TraceError ("HrSetupGetLineCount", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetBinaryField
//
// Purpose: Gets a binary value from an INF field.
//
// Arguments:
// ctx [in] See the Setup API documentation.
// dwFieldIndex [in]
// pbBuf [out]
// cbBuf [in]
// pbRequired [out]
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 16 Apr 1997
//
// Notes:
//
HRESULT HrSetupGetBinaryField ( IN const INFCONTEXT& ctx, IN DWORD dwFieldIndex, OUT BYTE* pbBuf, IN DWORD cbBuf, OUT DWORD* pbRequired) { HRESULT hr; if (SetupGetBinaryField ((PINFCONTEXT)&ctx, dwFieldIndex, pbBuf, cbBuf, pbRequired)) { hr = S_OK; } else { hr = HrFromLastWin32Error (); if (pbBuf) { *pbBuf = 0; } if (pbRequired) { *pbRequired = 0; } } TraceError ("HrSetupGetBinaryField", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetIntField
//
// Purpose: Gets an integer value from an INF field.
//
// Arguments:
// ctx [in] See the Setup API documentation.
// dwFieldIndex [in]
// pnValue [out]
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 16 Apr 1997
//
// Notes:
//
HRESULT HrSetupGetIntField ( IN const INFCONTEXT& ctx, IN DWORD dwFieldIndex, OUT INT* pnValue) { Assert (pnValue);
HRESULT hr; if (SetupGetIntField (const_cast<PINFCONTEXT>(&ctx), dwFieldIndex, pnValue)) { hr = S_OK; } else { hr = HrFromLastWin32Error (); *pnValue = 0; } TraceError ("HrSetupGetIntField", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetMultiSzField
//
// Purpose: Gets a multi-sz value from an INF field.
//
// Arguments:
// ctx [in] See the Setup API documentation.
// dwFieldIndex [in]
// pszBuf [out]
// cchBuf [in]
// pcchRequired [out]
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 16 Apr 1997
//
// Notes:
//
HRESULT HrSetupGetMultiSzField ( const INFCONTEXT& ctx, DWORD dwFieldIndex, PWSTR pszBuf, DWORD cchBuf, DWORD* pcchRequired) { HRESULT hr; if (SetupGetMultiSzField (const_cast<PINFCONTEXT>(&ctx), dwFieldIndex, pszBuf, cchBuf, pcchRequired)) { hr = S_OK; } else { hr = HrFromLastWin32Error (); if (pszBuf) { *pszBuf = 0; } if (pcchRequired) { *pcchRequired = 0; } } TraceError ("HrSetupGetMultiSzField", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetMultiSzFieldWithAlloc
//
// Purpose: Gets a multi-sz value from an INF field. Allocates space for
// it automatically.
//
// Arguments:
// ctx [in] See the Setup API documentation.
// dwFieldIndex [in]
// ppszBuf [out]
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 16 Apr 1997
//
// Notes: Free the returned multi-sz with MemFree.
//
HRESULT HrSetupGetMultiSzFieldWithAlloc ( const INFCONTEXT& ctx, DWORD dwFieldIndex, PWSTR* ppszBuf) { Assert (ppszBuf);
// Initialize the output parameter.
*ppszBuf = NULL;
// First, get the size required.
//
HRESULT hr; DWORD cchRequired;
hr = HrSetupGetMultiSzField (ctx, dwFieldIndex, NULL, 0, &cchRequired); if (S_OK == hr) { // Allocate the buffer.
//
PWSTR pszBuf = (PWSTR)MemAlloc(cchRequired * sizeof(WCHAR)); if (pszBuf) { // Now fill the buffer.
//
hr = HrSetupGetMultiSzField (ctx, dwFieldIndex, pszBuf, cchRequired, NULL); if (S_OK == hr) { *ppszBuf = pszBuf; } else { MemFree (pszBuf); } } } TraceError ("HrSetupGetMultiSzFieldWithAlloc", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetStringField
//
// Purpose: Gets a string from an INF field. Returns it as a tstring.
//
// Arguments:
// ctx [in] See the Setup API documentation.
// dwFieldIndex [in]
// pstr [out]
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 16 Apr 1997
//
// Notes:
//
HRESULT HrSetupGetStringField (const INFCONTEXT& ctx, DWORD dwFieldIndex, tstring* pstr) { Assert (pstr);
// First, get the size required.
//
DWORD cchRequired = 0; HRESULT hr = HrSetupGetStringField (ctx, dwFieldIndex, NULL, 0, &cchRequired);
// 412390: workaround for bug in NT4 SETUPAPI.dll
//
if ((S_OK == hr) && (0 == cchRequired)) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); }
if (S_OK == hr) { // Allocate a buffer on the stack.
//
PWSTR pszBuf; pszBuf = (PWSTR)PvAllocOnStack(cchRequired * sizeof(WCHAR));
// Now fill the buffer.
//
hr = HrSetupGetStringField (ctx, dwFieldIndex, pszBuf, cchRequired, NULL); if (S_OK == hr) { *pstr = pszBuf; } } // If we failed for any reason, initialize the output parameter.
//
if (FAILED(hr)) { pstr->erase (); } TraceError ("HrSetupGetStringField", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetStringField
//
// Purpose: Gets a string from an INF field.
//
// Arguments:
// ctx [in] See the Setup API documentation.
// dwFieldIndex [in]
// pszBuf [out]
// cchBuf [in]
// pcchRequired [out]
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 16 Apr 1997
//
// Notes:
//
HRESULT HrSetupGetStringField ( IN const INFCONTEXT& ctx, IN DWORD dwFieldIndex, OUT PWSTR pszBuf, IN DWORD cchBuf, OUT DWORD* pcchRequired) { HRESULT hr; if (SetupGetStringField ((PINFCONTEXT)&ctx, dwFieldIndex, pszBuf, cchBuf, pcchRequired)) { hr = S_OK; } else { hr = HrFromLastWin32Error ();
if (pszBuf) { *pszBuf = 0; } if (pcchRequired) { *pcchRequired = 0; } } TraceError ("HrSetupGetStringField", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupScanFileQueueWithNoCallback
//
// Purpose: Scans a setup file queue, performing an operation on each node
// in its copy list. The operation is specified by a set of
// flags. This function can be called either before or after
// the queue has been committed.
//
// Arguments:
// hfq [in] See SetupApi for information
// dwFlags [in]
// hwnd [in]
// pdwResult [out]
//
// Returns: S_OK or a Win32 error code.
//
// Author: billbe 23 July 1997
//
// Notes: This differs from the SetupApi version in that no callback
// can be specified through this wrapper. This is because
// errors from the callback cannot not be reliably mapped
// to an HRESULT. If a user defined callback is needed,
// the original SetupApi function must be used.
//
HRESULT HrSetupScanFileQueueWithNoCallback(HSPFILEQ hfq, DWORD dwFlags, HWND hwnd, PDWORD pdwResult) { Assert(hfq); Assert(INVALID_HANDLE_VALUE != hfq); Assert(pdwResult);
HRESULT hr = S_OK;
// Scan the given queue
if (!SetupScanFileQueue(hfq, dwFlags, hwnd, NULL, NULL, pdwResult)) { hr = HrFromLastWin32Error(); }
TraceError ("HrSetupScanFileQueueWithNoCallback", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetMultiSzFieldMapToDword
//
// Purpose: Gets the values represented as mult-sz in an INF
// and returns the value as a DWORD of bit flags.
// The mapping is specified by the caller through an array of
// pointers to string values and their associated DWORD values.
//
// Example: The value in the INF might be "Ip,Ipx,Nbf".
// This function can map these values to the DWORD
// representation of FLAG_IP | FLAG_IPX | FLAG_NBF.
//
// Arguments:
// ctx [in] See the Setup API documentation.
// dwFieldIndex [in]
// aMapSzDword [in] array of elements mapping a string to a DWORD.
// cMapSzDword [in] count of elements in the array.
// pdwValue [out] the returned value.
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 16 Apr 1997
//
// Notes: _wcsicmp is used to make the string comparisons.
//
HRESULT HrSetupGetMultiSzFieldMapToDword (const INFCONTEXT& ctx, DWORD dwFieldIndex, const MAP_SZ_DWORD* aMapSzDword, UINT cMapSzDword, DWORD* pdwValue) { Assert (aMapSzDword); Assert (cMapSzDword); Assert (pdwValue);
// Initialize the output parameter.
*pdwValue = 0;
// Get the multi-sz value.
//
HRESULT hr; PWSTR pszBuf;
hr = HrSetupGetMultiSzFieldWithAlloc (ctx, dwFieldIndex, &pszBuf); if (S_OK == hr) { DWORD dwValue = 0;
// Map each value in the multi-sz to a DWORD and OR it into
// the result.
for (PCWSTR pszValue = pszBuf; *pszValue; pszValue += lstrlenW (pszValue) + 1) { // Search the map for a matching value. When found, update
// dwValue.
for (UINT i = 0; i < cMapSzDword; i++) { if (0 == lstrcmpiW (aMapSzDword[i].pszValue, pszValue)) { dwValue |= aMapSzDword[i].dwValue; break; } } }
// Assign the output parameter.
*pdwValue = dwValue;
MemFree (pszBuf); } TraceError ("HrSetupGetMultiSzFieldMapToDword", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetStringFieldMapToDword
//
// Purpose: Gets a value represented as multiple strings in an INF
// and returns it as a DWORD. The mapping is specified
// by the caller through an array of pointers to string
// values and their associated DWORD values.
//
// Example: Values in the INF might be "Yes" or "No".
// This function can map these values to DWORD representations
// of "1" and "0" respectively.
//
// Arguments:
// ctx [in] See the Setup API documentation.
// dwFieldIndex [in]
// aMapSzDword [in] array of elements mapping a string to a DWORD.
// cMapSzDword [in] count of elements in the array.
// pdwValue [out] the returned value.
//
// Returns: S_OK if a match was found. If a match wasn't found,
// HRESULT_FROM_WIN32(ERROR_INVALID_DATA) is returned.
// Other Win32 error codes.
//
// Author: shaunco 16 Apr 1997
//
// Notes: lstrcmpiW is used to make the string comparisons.
//
HRESULT HrSetupGetStringFieldMapToDword (const INFCONTEXT& ctx, DWORD dwFieldIndex, const MAP_SZ_DWORD* aMapSzDword, UINT cMapSzDword, DWORD* pdwValue) { Assert (aMapSzDword); Assert (cMapSzDword); Assert (pdwValue);
// Initialize the output parameter.
*pdwValue = 0;
// Get the string value.
//
tstring strValue; HRESULT hr = HrSetupGetStringField (ctx, dwFieldIndex, &strValue); if (SUCCEEDED(hr)) { // Search the map for a matching value. When found, pass
// the DWORD value out.
// If the none of the strings matched, we'll return
// an invalid data error code.
hr = HRESULT_FROM_WIN32 (ERROR_INVALID_DATA); while (cMapSzDword--) { if (0 == lstrcmpiW (aMapSzDword->pszValue, strValue.c_str())) { *pdwValue = aMapSzDword->dwValue; hr = S_OK; break; } aMapSzDword++; } } TraceError ("HrSetupGetStringFieldMapToDword", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetStringFieldAsBool
//
// Purpose: Gets the value of a boolean field represented as the
// strings "Yes" and "No" in an INF file.
//
// Arguments:
// ctx [in] See the Setup API documentation.
// dwFieldIndex [in]
// pfValue [out] the returned value.
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 16 Apr 1997
//
// Notes:
//
HRESULT HrSetupGetStringFieldAsBool (const INFCONTEXT& ctx, DWORD dwFieldIndex, BOOL* pfValue) { Assert (pfValue);
// Initialize the output parameter.
*pfValue = FALSE;
static const MAP_SZ_DWORD aMapYesNo [] = { { c_szYes, TRUE }, { c_szNo, FALSE }, }; DWORD dwValue; HRESULT hr = HrSetupGetStringFieldMapToDword (ctx, dwFieldIndex, aMapYesNo, celems(aMapYesNo), &dwValue); if (SUCCEEDED(hr)) { *pfValue = !!dwValue; } TraceError ("HrSetupGetStringFieldAsBool", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetFirstDword
//
// Purpose: Get a DWORD value from a section in the INF file.
//
// Arguments:
// hinf [in] handle to an open INF file.
// pszSection [in] specifies the section that contains the value.
// pszKey [in] specifies the key that contains the value.
// pdwValue [out] the returned value.
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 17 Apr 1997
//
// Notes:
//
HRESULT HrSetupGetFirstDword ( IN HINF hinf, IN PCWSTR pszSection, IN PCWSTR pszKey, OUT DWORD* pdwValue) { Assert (pszSection); Assert (pszKey);
// Initialize the output parameter.
*pdwValue = 0;
INFCONTEXT ctx; HRESULT hr = HrSetupFindFirstLine (hinf, pszSection, pszKey, &ctx); if (S_OK == hr) { INT nValue; hr = HrSetupGetIntField (ctx, c_dwFirstField, &nValue); if (S_OK == hr) { *pdwValue = nValue; } } TraceErrorOptional ("HrSetupGetFirstDword", hr, (SPAPI_E_LINE_NOT_FOUND == hr)); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetFirstString
//
// Purpose: Get a string value from a section in the INF file.
//
// Arguments:
// hinf [in] handle to an open INF file.
// pszSection [in] specifies the section that contains the value.
// pszKey [in] specifies the key that contains the value.
// pdwValue [out] the returned value.
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 17 Apr 1997
//
// Notes:
//
HRESULT HrSetupGetFirstString ( IN HINF hinf, IN PCWSTR pszSection, IN PCWSTR pszKey, OUT tstring* pstr) { Assert (pszSection); Assert (pszKey);
INFCONTEXT ctx; HRESULT hr = HrSetupFindFirstLine (hinf, pszSection, pszKey, &ctx); if (S_OK == hr) { hr = HrSetupGetStringField (ctx, c_dwFirstField, pstr); } // If we failed for any reason, initialize the output parameter.
//
if (FAILED(hr)) { pstr->erase (); } TraceErrorOptional ("HrSetupGetFirstString", hr, (SPAPI_E_SECTION_NOT_FOUND == hr) || (SPAPI_E_LINE_NOT_FOUND == hr)); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetFirstMultiSzFieldWithAlloc
//
// Purpose: Retrieves the first occurrance of the given key in the given
// section of an INF file, allocates memory for it, and returns
// it in the parameter pszOut.
//
// Arguments:
// hinf [in] handle to an open INF file.
// pszSection [in] specifies the section that contains the value.
// pszKey [in] specifies the key that contains the value.
// pszOut [out] Returns multi-sz field.
//
// Returns: S_OK or a Win32 error code.
//
// Author: danielwe 7 May 1997
//
// Notes: Free the resulting string with MemFree.
//
HRESULT HrSetupGetFirstMultiSzFieldWithAlloc ( IN HINF hinf, IN PCWSTR pszSection, IN PCWSTR pszKey, OUT PWSTR* ppszOut) { Assert(pszSection); Assert(pszKey); Assert(ppszOut);
// Initialize the output parameter.
*ppszOut = 0;
INFCONTEXT ctx; HRESULT hr = HrSetupFindFirstLine (hinf, pszSection, pszKey, &ctx); if (S_OK == hr) { hr = HrSetupGetMultiSzFieldWithAlloc(ctx, c_dwFirstField, ppszOut); }
TraceErrorOptional("HrSetupGetFirstMultiSzFieldWithAlloc", hr, (SPAPI_E_LINE_NOT_FOUND == hr)); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetFirstMultiSzMapToDword
//
// Purpose: Get a DWORD value from a section in the INF file.
// The value is represented in the INF file as a multi-sz, but
// it is mapped to a DWORD value based on a caller-specified
// mapping. The string values in the map are compared using
// a case insensitive compare.
//
// Use this when the INF value can be one or more of a fixed
// set of values represented as strings.
//
// Example: [MySection] with a map of:
// MyKey = Ip,Nbf { "Ip", 0x01 }
// { "Ipx", 0x02 }
// { "Nbf", 0x04 }
//
// yields *pdwValue returned as 0x01 | 0x04 = 0x05.
//
// Arguments:
// hinf [in] handle to an open INF file.
// pszSection [in] specifies the section that contains the value.
// pszKey [in] specifies the key that contains the value.
// aMapSzDword [in] array of elements mapping a string to a DWORD.
// cMapSzDword [in] count of elements in the array.
// pdwValue [out] the returned value.
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 17 Apr 1997
//
// Notes: HrOpen must have been called before this call.
//
HRESULT HrSetupGetFirstMultiSzMapToDword ( IN HINF hinf, IN PCWSTR pszSection, IN PCWSTR pszKey, IN const MAP_SZ_DWORD* aMapSzDword, IN UINT cMapSzDword, OUT DWORD* pdwValue) { Assert (pszSection); Assert (pszKey);
// Initialize the output parameter.
*pdwValue = 0;
INFCONTEXT ctx; HRESULT hr = HrSetupFindFirstLine (hinf, pszSection, pszKey, &ctx); if (S_OK == hr) { hr = HrSetupGetMultiSzFieldMapToDword (ctx, c_dwFirstField, aMapSzDword, cMapSzDword, pdwValue); } TraceErrorOptional ("HrSetupGetFirstMultiSzMapToDword", hr, (SPAPI_E_LINE_NOT_FOUND == hr)); return hr; }
//+---------------------------------------------------------------------------
//
// Member: HrSetupGetFirstStringMapToDword
//
// Purpose: Get a DWORD value from a section in the INF file.
// The value is represented in the INF file as a string, but
// it is mapped to a DWORD value based on a caller-specified
// mapping. The string values in the map are compared using
// a case insensitive compare.
//
// Use this when the INF value can be one of a fixed set of
// values represented as strings.
//
// Example: [MySection] with a map of:
// MyKey = ThisComputer { "Network", 1 }
// { "ThisComputer", 2 }
//
// yields *pdwValue returned as 2.
//
// Arguments:
// hinf [in] handle to an open INF file.
// pszSection [in] specifies the section that contains the value.
// pszKey [in] specifies the key that contains the value.
// aMapSzDword [in] array of elements mapping a string to a DWORD.
// cMapSzDword [in] count of elements in the array.
// pdwValue [out] the returned value.
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 17 Apr 1997
//
// Notes: HrOpen must have been called before this call.
//
HRESULT HrSetupGetFirstStringMapToDword ( IN HINF hinf, IN PCWSTR pszSection, IN PCWSTR pszKey, IN const MAP_SZ_DWORD* aMapSzDword, IN UINT cMapSzDword, OUT DWORD* pdwValue) { Assert (pszSection); Assert (pszKey);
// Initialize the output parameter.
*pdwValue = 0;
INFCONTEXT ctx; HRESULT hr = HrSetupFindFirstLine (hinf, pszSection, pszKey, &ctx); if (S_OK == hr) { hr = HrSetupGetStringFieldMapToDword (ctx, c_dwFirstField, aMapSzDword, cMapSzDword, pdwValue); } TraceErrorOptional ("HrSetupGetFirstStringMapToDword", hr, (SPAPI_E_LINE_NOT_FOUND == hr)); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetFirstStringAsBool
//
// Purpose: Get a boolean value from a section in the INF file.
// The boolean value is represented in the INF file as
// "Yes" or "No" (case insensitive) but the value is returned
// as a BOOL type.
//
// Example: [MySection]
// MyKey = yes
//
// yields *pfValue returned as TRUE.
//
// Arguments:
// hinf [in] handle to an open INF file.
// pszSection [in] specifies the section that contains the value.
// pszKey [in] specifies the key that contains the value.
// pdwValue [out] the returned value.
//
// Returns: S_OK or a Win32 error code.
//
// Author: shaunco 17 Apr 1997
//
// Notes:
//
HRESULT HrSetupGetFirstStringAsBool ( IN HINF hinf, IN PCWSTR pszSection, IN PCWSTR pszKey, OUT BOOL* pfValue) { Assert (hinf); Assert (pszSection); Assert (pszKey); Assert (pfValue);
// Initialize the output parameter.
*pfValue = FALSE;
INFCONTEXT ctx; HRESULT hr = HrSetupFindFirstLine (hinf, pszSection, pszKey, &ctx); if (S_OK == hr) { hr = HrSetupGetStringFieldAsBool (ctx, c_dwFirstField, pfValue); } TraceErrorOptional ("HrSetupGetFirstStringAsBool", hr, (SPAPI_E_LINE_NOT_FOUND == hr)); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupGetInfInformation
//
// Purpose: Returns the SP_INF_INFORMATION structure for the specified
// INF file to a caller-supplied buffer.
//
// Arguments:
// pvInfSpec [in] See SetupApi documentation for more info
// dwSearchControl [in]
// ppinfInfo [out]
//
// Returns: S_OK or a Win32 error code.
//
// Author: BillBe 18 Jan 1998
//
// Notes:
//
HRESULT HrSetupGetInfInformation ( IN LPCVOID pvInfSpec, IN DWORD dwSearchControl, OUT PSP_INF_INFORMATION* ppinfInfo) { DWORD dwSize; BOOL fSuccess;
*ppinfInfo = NULL;
if (fSuccess = SetupGetInfInformation (pvInfSpec, dwSearchControl, NULL, 0, &dwSize)) { *ppinfInfo = (PSP_INF_INFORMATION)MemAlloc (dwSize); fSuccess = SetupGetInfInformation (pvInfSpec, dwSearchControl, *ppinfInfo, dwSize, 0); }
HRESULT hr = S_OK; if (!fSuccess) { hr = HrFromLastWin32Error(); MemFree (*ppinfInfo); *ppinfInfo = NULL; }
TraceError("HrSetupGetInfInformation", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupIsValidNt5Inf
//
// Purpose: Determines if an inf file is a valid NT5 inf by examining
// its signature.
//
// Arguments:
// hinf [in] Handle to the inf file
//
// Returns: S_OK if valid, SPAPI_E_WRONG_INF_STYLE if invalid,
// or a Win32 error code.
//
// Author: BillBe 18 Jan 1998
//
// Notes: $WINDOWS 95$ is invalid and $CHICAGO$ is
// only valid if it has the required Compatible inf key in
// the version info.
//
HRESULT HrSetupIsValidNt5Inf ( IN HINF hinf) { static const WCHAR c_szSignature[] = INFSTR_KEY_SIGNATURE; static const WCHAR c_szCompatible[] = L"Compatible"; static const WCHAR c_szChicagoSig[] = L"$Chicago$"; static const WCHAR c_szWinntSig[] = L"$Windows NT$"; static const WCHAR c_szCompatibleValue[] = L"1";
PSP_INF_INFORMATION pinfInfo;
// Get the inf's version info
HRESULT hr = HrSetupGetInfInformation (hinf, INFINFO_INF_SPEC_IS_HINF, &pinfInfo);
if (S_OK == hr) { PWSTR pszSignature;
// Get the signature info
hr = HrSetupQueryInfVersionInformation (pinfInfo, 0, c_szSignature, &pszSignature);
if (S_OK == hr) {
// if the inf signature is not windows nt...
if (0 != lstrcmpiW (pszSignature, c_szWinntSig)) { // if it isn't Chicago, then we don't support it
if (0 != lstrcmpiW (pszSignature, c_szChicagoSig)) { hr = SPAPI_E_WRONG_INF_STYLE; } else { // The signature is Chicago so now we check if
// the compatible line exists.
//
PWSTR pszCompatible; hr = HrSetupQueryInfVersionInformation (pinfInfo, 0, c_szCompatible, &pszCompatible);
if (S_OK == hr) { // We found the compatible line, now make sure
// it is set to c_szCompatibleValue.
//
if (0 != lstrcmpiW (pszCompatible, c_szCompatibleValue)) { hr = SPAPI_E_WRONG_INF_STYLE; }
MemFree (pszCompatible); } else if (HRESULT_FROM_WIN32(ERROR_INVALID_DATA) == hr) { // The Compatible key didn't exist so this is
// considered a windows 95 net inf
hr = SPAPI_E_WRONG_INF_STYLE; } } } MemFree (pszSignature); } MemFree (pinfInfo); }
TraceError("HrSetupIsValidNt5Inf", (SPAPI_E_WRONG_INF_STYLE == hr) ? S_OK : hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupQueryInfVersionInformation
//
// Purpose: Returns INF file version information from an
// SP_INF_INFORMATION structure to a caller-supplied buffer.
//
//
//
// Arguments:
// pinfInfo [in] See SetupApi documentation for more info
// uiIndex [in]
// szKey [in]
// ppszInfo [out]
//
// Returns: S_OK or a Win32 error code.
//
// Author: BillBe 18 Jan 1998
//
// Notes:
//
HRESULT HrSetupQueryInfVersionInformation ( IN PSP_INF_INFORMATION pinfInfo, IN UINT uiIndex, IN PCWSTR pszKey, OUT PWSTR* ppszInfo) { Assert(pinfInfo);
*ppszInfo = NULL;
DWORD dwSize; BOOL fSuccess = SetupQueryInfVersionInformation (pinfInfo, uiIndex, pszKey, NULL, 0, &dwSize);
if (fSuccess) { *ppszInfo = (PWSTR)MemAlloc (dwSize * sizeof (WCHAR)); fSuccess = SetupQueryInfVersionInformation (pinfInfo, uiIndex, pszKey, *ppszInfo, dwSize, NULL); }
HRESULT hr = S_OK; if (!fSuccess) { MemFree (*ppszInfo); *ppszInfo = NULL; hr = HrFromLastWin32Error(); }
TraceError("HrSetupQueryInfVersionInformation", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Member: CSetupInfFile::Close
//
// Purpose: Close the INF file. It must have previously opened with
// a call to HrOpen().
//
// Arguments:
// (none)
//
// Returns: nothing
//
// Author: shaunco 16 Apr 1997
//
// Notes:
//
void CSetupInfFile::Close () { AssertSz (m_hinf, "You shouldn't be closing a file that is already closed."); ::SetupCloseInfFile (m_hinf); m_hinf = NULL; }
//+---------------------------------------------------------------------------
//
// Member: CSetupInfFile::EnsureClosed
//
// Purpose: Ensure the INF file represented by this object is closed.
//
// Arguments:
// (none)
//
// Returns: nothing
//
// Author: shaunco 16 Apr 1997
//
// Notes:
//
void CSetupInfFile::EnsureClosed() { if (m_hinf) { Close (); } }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiCallClassInstaller
//
// Purpose: calls the appropriate class installer with the specified
// installation request (DI_FUNCTION).
//
// Arguments:
// dif [in] See SetupApi for more info
// hdi [in] See SetupApi for more info
// pdeid [in] See SetupApi for more info
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 25 June 1997
//
// Notes: SPAPI_E_DI_DO_DEFAULT is mapped to S_OK
//
HRESULT HrSetupDiCallClassInstaller( IN DI_FUNCTION dif, IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid) { Assert(INVALID_HANDLE_VALUE != hdi); Assert(hdi);
HRESULT hr = S_OK;
// Call the class installer and convert any errors
if (!SetupDiCallClassInstaller(dif, hdi, pdeid)) { hr = HrFromLastWin32Error(); if (SPAPI_E_DI_DO_DEFAULT == hr) { hr = S_OK; } }
TraceError("HrSetupDiCallClassInstaller", (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr) ? S_OK : hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupCopyOEMInf
//
// Purpose: HRESULT wrapper for SetupCopyOEMInf that returns the
// new file path and name as tstrings
//
// Arguments:
// szSourceName [in] See SetupApi for more info
// szSourceMediaLocation [in]
// dwSourceMediaType [in]
// dwCopyStyle [in]
// pstrDestFilename [out]
// pstrDestFilenameComponent [out]
//
// Returns: HRESULT. S_OK if successful, or Win32 converted error code
//
// Author: billbe 15 May 1997
//
// Notes: See SetupCopyOEMInf in SetupApi for more info
//
HRESULT HrSetupCopyOemInf( IN const tstring& strSourceName, IN const tstring& strSourceMediaLocation, OPTIONAL IN DWORD dwSourceMediaType, IN DWORD dwCopyStyle, OUT tstring* pstrDestFilename, OPTIONAL OUT tstring* pstrDestFilenameComponent OPTIONAL) { Assert(!strSourceName.empty());
BOOL fWin32Success = TRUE; DWORD cchRequiredSize;
// Copy the file and get the size for the new filename in case it is
// needed
if (fWin32Success = SetupCopyOEMInf(strSourceName.c_str(), strSourceMediaLocation.c_str(), dwSourceMediaType, dwCopyStyle, NULL, NULL, &cchRequiredSize, NULL)) { // If any of the out parameters are specified, we need to get the
// information
if (pstrDestFilename || pstrDestFilenameComponent) { PWSTR pszDestPath = NULL; PWSTR pszDestFilename = NULL; // now we allocate space to get the destination file path.
// We allocate on the stack for automatic clean-up
// Note: dwRequiredSize includes the terminating NULL
//
pszDestPath = (PWSTR)_alloca(cchRequiredSize * sizeof(WCHAR));
// Get the new file path and filename
if (fWin32Success = SetupCopyOEMInf(strSourceName.c_str(), strSourceMediaLocation.c_str(), dwSourceMediaType, dwCopyStyle, pszDestPath, cchRequiredSize, NULL, &pszDestFilename)) { // if the file path is needed, assign it
if (pstrDestFilename) { *pstrDestFilename = pszDestPath; }
// If the user wants just the filename, assign it to the
// string
if (pstrDestFilenameComponent) { *pstrDestFilenameComponent = pszDestFilename; } } else { // initialize out params on failure
//
if (pstrDestFilename) { pstrDestFilename->erase(); }
if (pstrDestFilenameComponent) { pstrDestFilenameComponent->erase(); } } }
}
HRESULT hr = S_OK; if (!fWin32Success) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupCopyOEMInf", hr); return hr;
}
//+--------------------------------------------------------------------------
//
// Function: HrSetupCopyOEMInf
//
// Purpose: HRESULT wrapper for SetupCopyOEMInf that returns the
// new file path and name as tstrings
//
// Arguments:
// pszSourceName [in] See SetupApi for more info
// pszSourceMediaLocation [in]
// dwSourceMediaType [in]
// dwCopyStyle [in]
// pszDestFilename [out] // must be at least _MAX_PATH chars.
// ppszDestFilenameComponent [out]
//
// Returns: HRESULT. S_OK if successful, or Win32 converted error code
//
// Author: billbe 15 May 1997
//
// Notes: See SetupCopyOEMInf in SetupApi for more info
//
HRESULT HrSetupCopyOemInfBuffer( IN PCWSTR pszSourceName, IN PCWSTR pszSourceMediaLocation, OPTIONAL IN DWORD SourceMediaType, IN DWORD CopyStyle, OUT PWSTR pszDestFilename, IN DWORD cchDestFilename, OUT PWSTR* ppszDestFilenameComponent OPTIONAL) { Assert(pszSourceName); Assert(pszDestFilename);
BOOL fWin32Success = TRUE;
if (!(fWin32Success = SetupCopyOEMInf(pszSourceName, pszSourceMediaLocation, SourceMediaType, CopyStyle, pszDestFilename, cchDestFilename, NULL, ppszDestFilenameComponent))) { // initialize out params on failure
//
*pszDestFilename = 0; if (*ppszDestFilenameComponent) { *ppszDestFilenameComponent = NULL; } }
HRESULT hr = S_OK; if (!fWin32Success) { hr = HrFromLastWin32Error(); }
TraceHr (ttidError, FAL, hr, FALSE, "HrSetupCopyOEMInf"); return hr;
}
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiBuildDriverInfoList
//
// Purpose: builds a list of drivers associated with a specified device
// instance or with the device information set's global
// class driver list.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in, out]
// dwDriverType [in]
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 26 June 1997
//
// Notes:
//
HRESULT HrSetupDiBuildDriverInfoList(IN HDEVINFO hdi, IN OUT PSP_DEVINFO_DATA pdeid, IN DWORD dwDriverType) { Assert(IsValidHandle(hdi));
HRESULT hr = S_OK;
// Build the list
if (!SetupDiBuildDriverInfoList(hdi, pdeid, dwDriverType)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiBuildDriverInfoList", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiCreateDeviceInfo
//
// Purpose: creates a new device information element and adds it as a
// new member to the specified device information set.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pszDeviceName [in] See SetupApi for more info
// guidClass [in] See SetupApi for more info
// pszDesc [in] See SetupApi for more info
// hwndParent [in] See SetupApi for more info
// dwFlags [in] See SetupApi for more info
// pdeid [out] See SetupApi for more info
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 26 June 1997
//
// Notes: pdeid is initialized and its cbSize field set by this fcn
//
HRESULT HrSetupDiCreateDeviceInfo( IN HDEVINFO hdi, IN PCWSTR pszDeviceName, IN const GUID& guidClass, IN PCWSTR pszDesc, OPTIONAL IN HWND hwndParent, OPTIONAL IN DWORD dwFlags, OUT PSP_DEVINFO_DATA pdeid OPTIONAL) { Assert(IsValidHandle(hdi)); Assert(pszDeviceName);
if (pdeid) { ZeroMemory(pdeid, sizeof(SP_DEVINFO_DATA)); pdeid->cbSize = sizeof(SP_DEVINFO_DATA); }
HRESULT hr = S_OK;
// Create the device info node
if (!SetupDiCreateDeviceInfo (hdi, pszDeviceName, &guidClass, pszDesc, hwndParent, dwFlags, pdeid)) { hr = HrFromLastWin32Error(); }
TraceError ("HrSetupDiCreateDeviceInfo", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiEnumDeviceInfo
//
// Purpose: Enumerates the members of the specified device information
// set.
//
// Arguments:
// hdi [in] See SetupApi for more info
// dwIndex [in] See SetupApi for more info
// pdeid [in] See SetupApi for more info
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 13 June 1997
//
// Notes:
//
HRESULT HrSetupDiEnumDeviceInfo( IN HDEVINFO hdi, IN DWORD dwIndex, OUT PSP_DEVINFO_DATA pdeid) { Assert(IsValidHandle(hdi)); Assert(pdeid);
HRESULT hr;
ZeroMemory(pdeid, sizeof(SP_DEVINFO_DATA)); pdeid->cbSize = sizeof(SP_DEVINFO_DATA);
if (SetupDiEnumDeviceInfo (hdi, dwIndex, pdeid)) { hr = S_OK; } else { hr = HrFromLastWin32Error(); }
TraceErrorOptional("HrSetupDiEnumDeviceInfo", hr, HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiEnumDriverInfo
//
// Purpose: Enumerates the members of a driver information list.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in]
// dwDriverType [in]
// dwIndex [in]
// pdrid [out]
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 26 June 1997
//
// Notes:
//
HRESULT HrSetupDiEnumDriverInfo( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, IN DWORD dwDriverType, IN DWORD dwIndex, OUT PSP_DRVINFO_DATA pdrid) {
Assert(IsValidHandle(hdi)); Assert(pdrid);
HRESULT hr = S_OK;
// initialize the out param
ZeroMemory(pdrid, sizeof(SP_DRVINFO_DATA)); pdrid->cbSize = sizeof(SP_DRVINFO_DATA);
// call the enum fcn
if (!SetupDiEnumDriverInfo(hdi, pdeid, dwDriverType, dwIndex, pdrid)) { hr = HrFromLastWin32Error(); }
TraceErrorOptional("HrSetupDiEnumDriverInfo", hr, HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr);
return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiSelectBestCompatDrv
//
// Purpose: Finds and selects the best driver for the current device.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in][out]
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 26 June 1997
//
// Notes:
//
HRESULT HrSetupDiSelectBestCompatDrv( IN HDEVINFO hdi, IN OUT PSP_DEVINFO_DATA pdeid) {
Assert(IsValidHandle(hdi)); Assert(pdeid);
HRESULT hr = S_OK;
// call the SelectBestCompatDrv fcn
if (!SetupDiSelectBestCompatDrv(hdi, pdeid)) { hr = HrFromLastWin32Error(); }
TraceErrorOptional("HrSetupDiSelectBestCompatDrv", hr, HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr);
return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiGetDeviceInfoListClass
//
// Purpose: Retrieves the class GUID associated with a device
// information set if it has an associated class.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pguid [out]
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 26 June 1997
//
// Notes:
//
HRESULT HrSetupDiGetDeviceInfoListClass ( IN HDEVINFO hdi, OUT GUID* pguid) { Assert(IsValidHandle(hdi)); Assert(pguid);
HRESULT hr = S_OK;
// Get the guid for the HDEVINFO
if (!SetupDiGetDeviceInfoListClass (hdi, pguid)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiGetDeviceInfoListClass", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiGetClassDevs
//
// Purpose: Returns a device information set that contains all installed
// devices of a specified class.
//
// Arguments:
// pguidClass [in] See SetupApi for more info
// pszEnumerator [in] See SetupApi for more info
// hwndParent [in] See SetupApi for more info
// dwFlags [in] See SetupApi for more info
// phdi [out] See SetupApi for more info
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 13 June 1997
//
// Notes:
//
HRESULT HrSetupDiGetClassDevs ( IN const GUID* pguidClass, OPTIONAL IN PCWSTR pszEnumerator, OPTIONAL IN HWND hwndParent, OPTIONAL IN DWORD dwFlags, OUT HDEVINFO* phdi) { Assert(phdi);
HRESULT hr;
HDEVINFO hdi = SetupDiGetClassDevsW (pguidClass, pszEnumerator, hwndParent, dwFlags);
if (INVALID_HANDLE_VALUE != hdi) { hr = S_OK; *phdi = hdi; } else { hr = HrFromLastWin32Error(); *phdi = NULL; }
TraceError ("HrSetupDiGetClassDevs", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiGetDeviceInstanceId
//
// Purpose: HRESULT wrapper for SetupDiGetDeviceInstanceId.
//
// Arguments:
// hdi [in] See SetupApi for more info.
// pdeid [in] See SetupApi for more info.
// pszId [out] The device instance Id for the net card.
// cchId [in] The size of pszId in characters.
// pcchRequired [out] Optional. The required buffer size in characters.
//
//
// Returns: HRESULT. S_OK if successful, error code otherwise.
//
// Author: billbe 26 Mar 1997
//
// Notes: See SetupDiGetDeviceInstanceId in Device Installer for more info.
//
HRESULT HrSetupDiGetDeviceInstanceId( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, OUT PWSTR pszId, IN DWORD cchId, OUT OPTIONAL DWORD* pcchRequired) { Assert(IsValidHandle(hdi)); Assert(pdeid);
DWORD cchRequiredSize; BOOL fSuccess = TRUE; HRESULT hr = S_OK;
// Get the buffer length required for the instance Id.
if (!(fSuccess = SetupDiGetDeviceInstanceIdW(hdi, pdeid, NULL, 0, &cchRequiredSize))) { // If all went well, we should have a buffer error.
if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) { // Since ERROR_INSUFFICIENT_BUFFER is really a success
// for us, we will reset the success flag.
fSuccess = TRUE;
// Set the out param if it was specified.
if (pcchRequired) { *pcchRequired = cchRequiredSize; }
// If the buffer sent in was large enough, go ahead and use it.
if (cchId >= cchRequiredSize) { fSuccess = SetupDiGetDeviceInstanceIdW(hdi, pdeid, pszId, cchId, NULL); } } } #ifdef DBG // Just being safe
else { // This should never happen since we sent in no buffer
AssertSz(FALSE, "SetupDiGetDeviceInstanceId returned success" " even though it was given no buffer"); } #endif // DBG
// We used SetupApi so we need to convert any errors
if (!fSuccess) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiGetDeviceInstanceId", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiInstallDevice
//
// Purpose: Wrapper for SetupDiInstallDevice
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in]
//
// Returns: HRESULT. S_OK if successful, Win32 error code otherwise
//
// Author: billbe 26 June 1997
//
// Notes:
//
HRESULT HrSetupDiInstallDevice ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid) { Assert(IsValidHandle(hdi)); Assert(pdeid);
HRESULT hr = S_OK;
// Let SetupApi install the specfied device
if (!SetupDiInstallDevice (hdi, pdeid)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiInstallDevice", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiOpenDevRegKey
//
// Purpose: Return an HKEY to the hardware device's driver instance key
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in]
// dwScope [in]
// dwHwProfile [in]
// dwKeyType [in]
// samDesired [in]
// phkey [out]
//
//
// Returns: HRESULT. S_OK if successful, Win32 error code otherwise
//
// Author: billbe 7 May 1997
//
// Notes:
//
HRESULT HrSetupDiOpenDevRegKey ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, IN DWORD dwScope, IN DWORD dwHwProfile, IN DWORD dwKeyType, IN REGSAM samDesired, OUT HKEY* phkey) { Assert(IsValidHandle(hdi)); Assert(pdeid); Assert(phkey);
// Try to open the registry key
//
HRESULT hr;
HKEY hkey = SetupDiOpenDevRegKey(hdi, pdeid, dwScope, dwHwProfile, dwKeyType, samDesired);
if (INVALID_HANDLE_VALUE != hkey) { hr = S_OK; *phkey = hkey; } else { hr = HrFromLastWin32Error(); *phkey = NULL; }
TraceErrorOptional("HrSetupDiOpenDevRegKey", hr, (SPAPI_E_DEVINFO_NOT_REGISTERED == hr) || (SPAPI_E_KEY_DOES_NOT_EXIST == hr));
return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiSetClassInstallParams
//
// Purpose: sets or clears class install parameters for a device
// information set or a particular device information element.
//
// Arguments:
// hdi [in] See Device Installer API for more info
// pdeid [in]
// pcih [in]
// cbSize [in]
//
//
// Returns: HRESULT. S_OK if successful, Win32 error code otherwise
//
// Author: billbe 26 June 1997
//
// Notes:
//
HRESULT HrSetupDiSetClassInstallParams ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, OPTIONAL IN PSP_CLASSINSTALL_HEADER pcih, OPTIONAL IN DWORD cbSize) { Assert(IsValidHandle(hdi));
HRESULT hr = S_OK;
// Set or clear the params
if (!SetupDiSetClassInstallParams(hdi, pdeid, pcih, cbSize)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiSetClassInstallParams", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiGetFixedSizeClassInstallParams
//
// Purpose: Gets a fixed size of an info list's ot device's class install
// parameters for a device.
//
// Arguments:
// hdi [in] See Device Installer for more info
// pdeid [in]
// pcih [in]
// cbSize [in]
//
//
// Returns: HRESULT. S_OK if successful, Win32 error code otherwise
//
// Author: billbe 26 June 1997
//
// Notes:
//
HRESULT HrSetupDiGetFixedSizeClassInstallParams ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, IN PSP_CLASSINSTALL_HEADER pcih, IN INT cbSize) { Assert(IsValidHandle(hdi)); Assert(pcih);
HRESULT hr = S_OK;
ZeroMemory(pcih, cbSize); pcih->cbSize = sizeof(SP_CLASSINSTALL_HEADER);
// Device Installer Api uses an all purpose GetClassInstallParams
// function. Several structures contain an SP_CLASSINSTALL_HEADER
// as their first member.
if (!SetupDiGetClassInstallParams(hdi, pdeid, pcih, cbSize, NULL)) { hr = HrFromLastWin32Error(); }
TraceErrorOptional("HrSetupDiGetFixedSizeClassInstallParams", hr, SPAPI_E_NO_CLASSINSTALL_PARAMS == hr);
return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiGetSelectedDriver
//
// Purpose: Retrieves the member of a driver list that has been selected
// as the controlling driver.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in]
// pdrid [out]
//
//
// Returns: HRESULT. S_OK if successful, Win32 error code otherwise
//
// Author: billbe 26 June 1997
//
// Notes:
//
HRESULT HrSetupDiGetSelectedDriver ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, OUT PSP_DRVINFO_DATA pdrid) { Assert(IsValidHandle(hdi)); Assert(pdrid);
// initialize and set the cbSize field
ZeroMemory(pdrid, sizeof(*pdrid)); pdrid->cbSize = sizeof(*pdrid);
HRESULT hr = S_OK;
// Set pdrid as the selected driver
if (!SetupDiGetSelectedDriver(hdi, pdeid, pdrid)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiGetSelectedDriver", (SPAPI_E_NO_DRIVER_SELECTED == hr) ? S_OK : hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupDiGetDriverInfoDetail
//
// Purpose: Gets details on the driver referenced by the given parameters.
//
// Arguments:
// hdi []
// pdeid [] See SetupAPI for more info
// pdrid []
// ppdridd []
//
// Returns: HRESULT. S_OK if successful, Win32 error code otherwise
//
// Author: danielwe 5 May 1998
//
// Notes:
//
HRESULT HrSetupDiGetDriverInfoDetail ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, IN PSP_DRVINFO_DATA pdrid, OUT PSP_DRVINFO_DETAIL_DATA* ppdridd) { HRESULT hr = S_OK; BOOL fSuccess = TRUE; DWORD dwRequiredSize = 0;
Assert(IsValidHandle(hdi)); Assert(pdrid); Assert(ppdridd); Assert(pdrid);
*ppdridd = NULL;
// Get the size needed for the driver detail
if (!(fSuccess = SetupDiGetDriverInfoDetailW (hdi, pdeid, pdrid, NULL, 0, &dwRequiredSize))) { // We should have received an insufficient buffer error since we
// sent no buffer
if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) { // Since this is ERROR_INSUFFICIENT_BUFFER is really a
// success for us, we will reset the success flag.
fSuccess = TRUE;
// Now we allocate our buffer for the driver detail data
// The size of the buffer is variable but it is a
// PSP_DEVINFO_DETAIL_DATA.
*ppdridd = (PSP_DRVINFO_DETAIL_DATA)MemAlloc (dwRequiredSize);
if (*ppdridd) { //initialize the variable
ZeroMemory(*ppdridd, dwRequiredSize); (*ppdridd)->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
// Get detailed info
fSuccess = SetupDiGetDriverInfoDetailW (hdi, pdeid, pdrid, *ppdridd, dwRequiredSize, NULL); } else { hr = E_OUTOFMEMORY; } } } else { // This should NEVER happen
AssertSz(FALSE, "HrSetupDiGetDriverInfoDetail succeeded with no " "buffer!"); }
// We have been using Device Installer Api so convert any errors
if (!fSuccess) { hr = HrFromLastWin32Error(); }
// clean up on failure
if (FAILED(hr)) { MemFree (*ppdridd); *ppdridd = NULL; }
TraceError("HrSetupDiGetDriverInfoDetail", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiSetSelectedDriver
//
// Purpose: Sets the specified member of a driver list as the
// currently-selected driver. It can also be used to reset
// the driver list so that there is no currently-selected
// driver.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in]
// pdrid [in, out]
//
//
// Returns: HRESULT. S_OK if successful, Win32 error code otherwise
//
// Author: billbe 26 June 1997
//
// Notes:
//
HRESULT HrSetupDiSetSelectedDriver ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, IN OUT PSP_DRVINFO_DATA pdrid) { Assert(IsValidHandle(hdi)); Assert(pdrid);
HRESULT hr = S_OK;
// Set pdrid as the selected driver
if (!SetupDiSetSelectedDriver(hdi, pdeid, pdrid)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiSetSelectedDriver", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiCreateDevRegKey
//
// Purpose: Creates and returns an HKEY to the hardware device's driver
// instance key
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in]
// dwScope [in]
// dwHwProfile [in]
// dwKeyType [in]
// hinf [in] OPTIONAL
// pszInfSectionName [in] OPTIONAL
// phkey [out]
//
//
// Returns: HRESULT. S_OK if successful, Win32 error code otherwise
//
// Author: billbe 4 June 1997
//
// Notes:
//
HRESULT HrSetupDiCreateDevRegKey ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, IN DWORD dwScope, IN DWORD dwHwProfile, IN DWORD dwKeyType, IN HINF hinf, PCWSTR pszInfSectionName, OUT HKEY* phkey) { Assert(IsValidHandle(hdi)); Assert(pdeid); Assert(phkey);
// Try to create the registry key and process the inf section, if
// specified
//
HRESULT hr;
HKEY hkey = SetupDiCreateDevRegKeyW(hdi, pdeid, dwScope, dwHwProfile, dwKeyType, hinf, pszInfSectionName);
if (INVALID_HANDLE_VALUE != hkey) { hr = S_OK; *phkey = hkey; } else { hr = HrFromLastWin32Error(); *phkey = NULL; }
TraceError("HrSetupDiCreateDevRegKey", hr);
return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiGetActualSectionToInstall
//
// Purpose: The sections in an inf file may have OS and platform suffixes
// appended to them. This function searches for a section that
// has pszSectionName as its base and has a certain suffix.
// For example on an x86 NT machine, given a section name of
// INSTALL, the search would start with INSTALL.NTx86, if that
// is not found, then INSTALL.NT is searched for.
// If that is not found INSTALL is returned.
//
// Arguments:
// hinf [in] SetupApi inf file handle
// pszSectionName [in] the section name to base the search on
// pstrActualSectionName [out] The actual section name with extension
// pstrExtension [out] OPTIONAL. The extension part of the
// pstrActualSectionName.
// This includes "."
//
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 27 Mar 1997
//
// Notes: See SetupDiGetActualSectionToInstall in SetupApi documention
// for more info
//
HRESULT HrSetupDiGetActualSectionToInstall( IN HINF hinf, IN PCWSTR pszSectionName, OUT tstring* pstrActualSectionName, OUT tstring* pstrExtension OPTIONAL) { Assert(IsValidHandle(hinf)); Assert(pszSectionName); Assert(pstrActualSectionName);
// strSectionName might need to be decorated with OS
// and Platform specific suffixes. The next call will return the actual
// decorated section name or our current section name if the decorated
// one does not exist.
//
BOOL fSuccess = TRUE; DWORD cchRequiredSize;
// Get the buffer length required
if (fSuccess = SetupDiGetActualSectionToInstallW(hinf, pszSectionName, NULL, 0, &cchRequiredSize, NULL)) { // now we allocate space to get the actual section name
// we allocate on the stack for automatic clean-up
// Note: dwRequiredSize includes the terminating NULL
//
PWSTR pszActualSection = NULL; pszActualSection = (PWSTR)_alloca(cchRequiredSize * sizeof(WCHAR));
PWSTR pszExtension = NULL; // Now fill the temporary and assign it to the OUT parameter
if (fSuccess = SetupDiGetActualSectionToInstallW(hinf, pszSectionName, pszActualSection, cchRequiredSize, NULL, &pszExtension)) { *pstrActualSectionName = pszActualSection;
// If the user wants the extension assign it to the string
// or assign the empty string if no extension was found
if (pstrExtension) { *pstrExtension = (pszExtension ? pszExtension : c_szEmpty); } } else { // initialize out params on failure
pstrActualSectionName->erase(); if (pstrExtension) { pstrExtension->erase(); } } }
// We used SetupApi so errors have to be converted
HRESULT hr = S_OK; if (!fSuccess) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiGetActualSectionToInstall", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiGetActualSectionToInstallWithAlloc
//
// Purpose: The sections in an inf file may have OS and platform suffixes
// appended to them. This function searches for a section that
// has pszSectionName as its base and has a certain suffix.
// For example on an x86 NT machine, given a section name of
// INSTALL, the search would start with INSTALL.NTx86, if that
// is not found, then INSTALL.NT is searched for.
// If that is not found INSTALL is returned.
//
// Arguments:
// hinf [in] SetupApi inf file handle.
// pszSection [in] the section name to base the search on.
// ppszActualSection [out] The actual section name with extension.
// If the actual section is the same as
// pszSectionName, *ppszActualSectionName
// will be NULL.
// ppszExtension [out] OPTIONAL. The extension part of the
// *ppszActualSectionName. This includes "."
//
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 27 Mar 1997
//
// Notes: See SetupDiGetActualSectionToInstall in SetupApi documention
// for more info
//
HRESULT HrSetupDiGetActualSectionToInstallWithAlloc( IN HINF hinf, IN PWSTR pszSection, OUT PWSTR* ppszActualSection, OUT PWSTR* ppszExtension OPTIONAL) { Assert(IsValidHandle(hinf)); Assert(pszSection); Assert(ppszActualSection);
// pszSectionName might need to be decorated with OS
// and Platform specific suffixes. The next call will return the actual
// decorated section name or our current section name if the decorated
// one does not exist.
//
HRESULT hr = S_OK; BOOL fSuccess = TRUE; DWORD cchRequiredSize;
*ppszActualSection = NULL; if (ppszExtension) { *ppszExtension = NULL; }
// Get the buffer length required
if (fSuccess = SetupDiGetActualSectionToInstallW(hinf, pszSection, NULL, 0, &cchRequiredSize, NULL)) { // We are assuming the section is not changing. If cchRequired is
// larger than the current section name buffer than we will allocate
// and fill the out param.
//
// If the section name is teh same, then we will not allocate. But
// if ppszExtension is specified then we need to send in the original
// section name buffer since ppszExtension will point to a location
// within it.
//
PWSTR pszBuffer = pszSection; if ((wcslen(pszSection) + 1) < cchRequiredSize) { hr = E_OUTOFMEMORY; *ppszActualSection = new WCHAR[cchRequiredSize * sizeof(WCHAR)]; pszBuffer = *ppszActualSection; }
// if the section name is different (we allocated) or the
// extension out param was specified, then we need to call the fcn.
if (pszBuffer && ((pszBuffer != pszSection) || ppszExtension)) { // Now fill the temporary and assign it to the OUT parameter
if (!(fSuccess = SetupDiGetActualSectionToInstallW(hinf, pszSection, pszBuffer, cchRequiredSize, NULL, ppszExtension))) { // initialize out params on failure
delete [] *ppszActualSection; *ppszActualSection = NULL;
if (ppszExtension) { *ppszExtension = NULL; } } } }
// We used SetupApi so errors have to be converted
if (SUCCEEDED(hr) && !fSuccess) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiGetActualSectionToInstallWithAlloc", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiGetActualSectionToInstallWithBuffer
//
// Purpose: The sections in an inf file may have OS and platform suffixes
// appended to them. This function searches for a section that
// has pszSectionName as its base and has a certain suffix.
// For example on an x86 NT machine, given a section name of
// INSTALL, the search would start with INSTALL.NTx86, if that
// is not found, then INSTALL.NT is searched for.
// If that is not found INSTALL is returned.
//
// Arguments:
// hinf [in] SetupApi inf file handle.
// pszSection [in] The section name to base the search on.
// pszActualSection [out] The actual section name with extension
// Buffer must be LINE_LEN characters.
// cchActualSection [in] Size of pszActualSection in characters.
// pcchRequired [out] OPTIONAL. Reuqired size of buffer in
// characters.
// ppszExtension [out] OPTIONAL. The extension part of the
// pszActualSection. This includes "."
//
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 27 Mar 1997
//
// Notes: See SetupDiGetActualSectionToInstall in SetupApi documention
// for more info
//
HRESULT HrSetupDiGetActualSectionToInstallWithBuffer( IN HINF hinf, IN PCWSTR pszSection, OUT PWSTR pszActualSection, IN DWORD cchActualSection, OUT DWORD* pcchRequired, OUT PWSTR* ppszExtension OPTIONAL) { Assert(IsValidHandle(hinf)); Assert(pszSection); Assert(pszActualSection);
// pszSectionName might need to be decorated with OS
// and Platform specific suffixes. The next call will return the actual
// decorated section name or our current section name if the decorated
// one does not exist.
//
BOOL fSuccess = TRUE; DWORD cchRequiredSize; *pszActualSection = 0; if (ppszExtension) { *ppszExtension = NULL; }
// Get the buffer length required
if (fSuccess = SetupDiGetActualSectionToInstallW(hinf, pszSection, NULL, 0, &cchRequiredSize, NULL)) { if (pcchRequired) { *pcchRequired = cchRequiredSize; }
// If the buffer sent in is large enough, get the section name.
if (cchActualSection >= cchRequiredSize) { if (!(fSuccess = SetupDiGetActualSectionToInstallW(hinf, pszSection, pszActualSection, cchActualSection, NULL, ppszExtension))) { // cleanup on failure.
*pszActualSection = 0; } } }
// We used SetupApi so errors have to be converted
HRESULT hr = S_OK; if (!fSuccess) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiGetActualSectionToInstallWithBuffer", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiGetDeviceInstallParams
//
// Purpose: Returns the device install params header of a
// device info set/data. Set SetupDiGetDeviceInstallParams
// in the SetupApi for more info.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in] See SetupApi for more info
// pdeip [out] See SetupApi for more info
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 26 May 1997
//
// Notes: This function will clear the variable pdeip and set its
// cbSize field.
//
HRESULT HrSetupDiGetDeviceInstallParams ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, OPTIONAL OUT PSP_DEVINSTALL_PARAMS pdeip) { Assert(IsValidHandle(hdi)); Assert(pdeip);
HRESULT hr = S_OK;
// initialize out parameter and set its cbSize field
//
ZeroMemory(pdeip, sizeof(SP_DEVINSTALL_PARAMS)); pdeip->cbSize = sizeof(SP_DEVINSTALL_PARAMS);
// get the header
if (!SetupDiGetDeviceInstallParams(hdi, pdeid, pdeip)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiGetDeviceInstallParams", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiGetDriverInstallParams
//
// Purpose: Retrieves install parameters for the specified driver.
// See SetupApi for more info.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in]
// pdrid [in]
// pdrip [out]
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 26 June 1997
//
// Notes: This function will clear the variable pdrip and set its
// cbSize field.
//
HRESULT HrSetupDiGetDriverInstallParams ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, OPTIONAL IN PSP_DRVINFO_DATA pdrid, OUT PSP_DRVINSTALL_PARAMS pdrip) { Assert(IsValidHandle(hdi)); Assert(pdrid); Assert(pdrip);
HRESULT hr = S_OK;
// initialize out parameter and set its cbSize field
//
ZeroMemory(pdrip, sizeof(SP_DRVINSTALL_PARAMS)); pdrip->cbSize = sizeof(SP_DRVINSTALL_PARAMS);
// get the header
if (!SetupDiGetDriverInstallParams(hdi, pdeid, pdrid, pdrip)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiGetDriverInstallParams", hr); return hr; }
VOID SetupDiSetConfigFlags ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, IN DWORD dwFlags, IN SD_FLAGS_BINARY_OP eOp) { DWORD dwConfigFlags = 0;
// Get the current config flags
(VOID) HrSetupDiGetDeviceRegistryProperty(hdi, pdeid, SPDRP_CONFIGFLAGS, NULL, (BYTE*)&dwConfigFlags, sizeof(dwConfigFlags), NULL);
// Perform the requested operation
switch (eOp) { case SDFBO_AND: dwConfigFlags &= dwFlags; break; case SDFBO_OR: dwConfigFlags |= dwFlags; break; case SDFBO_XOR: dwConfigFlags ^= dwFlags; break; default: AssertSz(FALSE, "Invalid binary op in HrSetupDiSetConfigFlags"); }
(VOID) HrSetupDiSetDeviceRegistryProperty(hdi, pdeid, SPDRP_CONFIGFLAGS, (BYTE*)&dwConfigFlags, sizeof(dwConfigFlags)); }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiSetDeviceInstallParams
//
// Purpose: Sets the device install params header of a
// device info set/data. Set SetupDiSetDeviceInstallParams
// in the SetupApi for more info.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in] See SetupApi for more info
// pdeip [in] See SetupApi for more info
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 26 May 1997
//
// Notes:
//
HRESULT HrSetupDiSetDeviceInstallParams ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, OPTIONAL IN PSP_DEVINSTALL_PARAMS pdeip) { Assert(IsValidHandle(hdi)); Assert(pdeip); Assert(pdeip->cbSize == sizeof(SP_DEVINSTALL_PARAMS));
HRESULT hr = S_OK;
// set the header
if (!SetupDiSetDeviceInstallParams(hdi, pdeid, pdeip)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiSetDeviceInstallParams", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiSetDriverInstallParams
//
// Purpose: Establishes install parameters for the specified driver.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in]
// pdrid [in]
// pdrip [in]
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 26 June 1997
//
// Notes:
//
HRESULT HrSetupDiSetDriverInstallParams ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, OPTIONAL IN PSP_DRVINFO_DATA pdrid, IN PSP_DRVINSTALL_PARAMS pdrip) { Assert(IsValidHandle(hdi)); Assert(pdrid); Assert(pdrip); Assert(pdrip->cbSize == sizeof(SP_DRVINSTALL_PARAMS));
HRESULT hr = S_OK;
// set the header
if (!SetupDiSetDriverInstallParams(hdi, pdeid, pdrid, pdrip)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiSetDriverInstallParams", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiSetDeipFlags
//
// Purpose: This sets given flags in a dev info data
//
// Arguments:
// hdi [in] See Device Installer Api for more info
// pdeid [in] See Device Installer Api for more info
// dwFlags [in] Flags to set
// eFlagType [in] Which flags field to set with dwFlags
// eClobber [in] Whether to add to existing flags or relace them
//
// Returns: HRESULT. S_OK if successful,
// a Win32 converted error otherwise
//
//
// Author: billbe 3 Feb 1998
//
// Notes:
//
HRESULT HrSetupDiSetDeipFlags ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, IN DWORD dwFlags, SD_DEID_FLAG_TYPE eFlagType, IN SD_FLAGS_BINARY_OP eOp) { Assert(IsValidHandle(hdi));
SP_DEVINSTALL_PARAMS deip; // Get the install params
HRESULT hr = HrSetupDiGetDeviceInstallParams (hdi, pdeid, &deip);
if (S_OK == hr) { DWORD* pFlags;
// Set our pointer to the right flag type
switch (eFlagType) { case SDDFT_FLAGS: pFlags = &deip.Flags; break; case SDDFT_FLAGSEX: pFlags = &deip.FlagsEx; break; default: AssertSz(FALSE, "Invalid Flag type in HrSetupDiSetDeipFlags"); break; }
// Perform the requested operation
switch (eOp) { case SDFBO_AND: *pFlags &= dwFlags; break; case SDFBO_OR: *pFlags |= dwFlags; break; case SDFBO_XOR: *pFlags ^= dwFlags; break; default: AssertSz(FALSE, "Invalid binary op in HrSetupDiSetDeipFlags"); }
// update the params
hr = HrSetupDiSetDeviceInstallParams (hdi, pdeid, &deip); }
TraceError ("HrSetupDiSetDeipFlags", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiRemoveDevice
//
// Purpose: Calls SetupApi to remove a device. See
// SetupDiRemoveDevice for more info.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in] See SetupApi for more info
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 27 May 1997
//
// Notes: This is used for enumerated Net class components
//
HRESULT HrSetupDiRemoveDevice( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid) { Assert(IsValidHandle(hdi)); Assert(pdeid);
HRESULT hr = S_OK;
if (!SetupDiRemoveDevice(hdi,pdeid)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiRemoveDevice", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiOpenDeviceInfo
//
// Purpose: Retrieves information about an existing device instance and
// adds it to the specified device information set
//
// Arguments:
// hdi [in] See SetupApi for more info
// pszPnpInstanceId [in] See SetupApi for more info
// hwndParent [in] See SetupApi for more info
// dwOpenFlags [in] See SetupApi for more info
// pdeid [out] See SetupApi for more info OPTIONAL
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 27 May 1997
//
// Notes: This is used for enumerated Net class components
//
HRESULT HrSetupDiOpenDeviceInfo( IN const HDEVINFO hdi, IN PCWSTR pszPnpInstanceId, IN HWND hwndParent, IN DWORD dwOpenFlags, OUT PSP_DEVINFO_DATA pdeid OPTIONAL) { Assert(IsValidHandle(hdi)); Assert(pszPnpInstanceId);
// If the out param was specified, clear it and set its cbSize field
//
if (pdeid) { ZeroMemory(pdeid, sizeof(*pdeid)); pdeid->cbSize = sizeof(*pdeid); }
HRESULT hr = S_OK;
if (!SetupDiOpenDeviceInfo(hdi, pszPnpInstanceId, hwndParent, dwOpenFlags, pdeid)) { hr = HrFromLastWin32Error(); }
TraceHr (ttidError, FAL, hr, SPAPI_E_NO_SUCH_DEVINST == hr, "HrSetupDiOpenDeviceInfo"); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiCreateDeviceInfoList
//
// Purpose: Creates an empty device information set.
//
// Arguments:
// pguidClass [in] See SetupApi for more info
// hwndParent [in] See SetupApi for more info
// phdi [out] See SetupApi for more info
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 27 May 1997
//
// Notes:
//
HRESULT HrSetupDiCreateDeviceInfoList ( IN const GUID* pguidClass, IN HWND hwndParent, OUT HDEVINFO* phdi) { Assert(phdi);
HRESULT hr;
// Try to create the info set
//
HDEVINFO hdi = SetupDiCreateDeviceInfoList (pguidClass, hwndParent);
if (INVALID_HANDLE_VALUE != hdi) { hr = S_OK; *phdi = hdi; } else { hr = HrFromLastWin32Error(); *phdi = NULL; }
TraceError("HrSetupDiCreateDeviceInfoList", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiGetDeviceRegistryPropertyWithAlloc
//
// Purpose: Returns the requested property of a device
// See SetupApi for more info.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in]
// dwProperty [in]
// pdwRegType [out]
// ppbBuffer [out]
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 1 June 1997
//
// Notes:
//
HRESULT HrSetupDiGetDeviceRegistryPropertyWithAlloc( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, IN DWORD dwProperty, OUT DWORD* pdwRegType, OPTIONAL OUT BYTE** ppbBuffer) { Assert(IsValidHandle(hdi)); Assert(pdeid); Assert(ppbBuffer);
*ppbBuffer = NULL;
DWORD cbReqSize; HRESULT hr = S_OK;
// Get the size needed for the buffer
BOOL fWin32Success = SetupDiGetDeviceRegistryPropertyW(hdi, pdeid, dwProperty, NULL, NULL, 0, &cbReqSize);
// We expect failure since we want the buffer size and sent in no buffer
if (!fWin32Success) { if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) { // Not really an error
fWin32Success = TRUE; }
if (fWin32Success) { *ppbBuffer = (BYTE*) MemAlloc (cbReqSize);
if (*ppbBuffer) { // Now get the actual information
fWin32Success = SetupDiGetDeviceRegistryPropertyW(hdi, pdeid, dwProperty, pdwRegType, *ppbBuffer, cbReqSize, NULL); } else { hr = E_OUTOFMEMORY; } } } else { AssertSz(FALSE, "SetupDiGetDeviceRegistryPropertyW should have failed!"); hr = E_FAIL; }
// All failures are converted to HRESULTS
if (SUCCEEDED(hr) && !fWin32Success) { MemFree (*ppbBuffer); *ppbBuffer = NULL; hr = HrFromLastWin32Error(); }
TraceHr (ttidError, FAL, hr , (HRESULT_FROM_WIN32(ERROR_INVALID_DATA) == hr) || (SPAPI_E_NO_SUCH_DEVINST == hr), "HrSetupDiGetDeviceRegistryPropertyWithAlloc"); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiGetDeviceRegistryProperty
//
// Purpose: Returns the requested property of a device
// See SetupApi for more info.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in]
// dwProperty [in]
// pdwRegType [out]
// ppbBuffer [out]
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 1 June 1997
//
// Notes:
//
HRESULT HrSetupDiGetDeviceRegistryProperty( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, IN DWORD dwProperty, OUT DWORD* pdwRegType, OPTIONAL OUT BYTE* pbBuffer, IN DWORD cbBufferSize, OUT DWORD* pcbRequiredSize OPTIONAL) { Assert(IsValidHandle(hdi)); Assert(pdeid);
// Get the size needed for the buffer
BOOL fWin32Success = SetupDiGetDeviceRegistryPropertyW(hdi, pdeid, dwProperty, pdwRegType, pbBuffer, cbBufferSize, pcbRequiredSize);
HRESULT hr = S_OK;
// All failures are converted to HRESULTS
if (!fWin32Success) { if (pbBuffer) { *pbBuffer = 0; } hr = HrFromLastWin32Error(); }
TraceHr (ttidError, FAL, hr , (HRESULT_FROM_WIN32(ERROR_INVALID_DATA) == hr) || (SPAPI_E_NO_SUCH_DEVINST == hr), "HrSetupDiGetDeviceRegistryProperty"); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupDiGetDeviceName
//
// Purpose: Helper function to get the name of the device specified in
// hdi and pdeid. Trys the friendly name first and if not there
// falls back to driver name which must be there.
//
// Arguments:
// hdi [in]
// pdeid [in] See SetupApi for more info
// ppszName [out]
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: danielwe 11 Feb 1998
//
// Notes:
//
HRESULT HrSetupDiGetDeviceName ( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, OUT PWSTR* ppszName) {
Assert(IsValidHandle(hdi)); Assert(pdeid); Assert(ppszName);
DWORD dwType; HRESULT hr = S_OK;
hr = HrSetupDiGetDeviceRegistryPropertyWithAlloc( hdi, pdeid, SPDRP_FRIENDLYNAME, &dwType, (BYTE**)ppszName); if (FAILED(hr)) { // Try again with the device desc which MUST be there.
hr = HrSetupDiGetDeviceRegistryPropertyWithAlloc( hdi, pdeid, SPDRP_DEVICEDESC, &dwType, (BYTE**)ppszName); } AssertSz(FImplies(SUCCEEDED(hr), (dwType == REG_SZ)), "Not a string?!");
TraceError("HrSetupDiGetDeviceName", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrSetupDiSetDeviceName
//
// Purpose: Helper function to set the name of the device specified in
// hdi and pdeid.
//
// Arguments:
// hdi [in]
// pdeid [in] See SetupApi for more info
// ppbBuffer [out]
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: sumitc 23 apr 1998
//
// Notes:
//
HRESULT HrSetupDiSetDeviceName( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, IN PCWSTR pszDeviceName) {
Assert(IsValidHandle(hdi)); Assert(pszDeviceName);
HRESULT hr = S_OK;
hr = HrSetupDiSetDeviceRegistryProperty(hdi, pdeid, SPDRP_FRIENDLYNAME, (const BYTE*)pszDeviceName, sizeof(WCHAR) * (wcslen(pszDeviceName) + 1)); TraceError("HrSetupDiSetDeviceName", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiSetDeviceRegistryProperty
//
// Purpose: Sets the specified Plug and Play device registry property.
// See SetupApi for more info.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in]
// dwProperty [in]
// pbBuffer [in]
// cbSize [in]
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 26 June 1997
//
// Notes:
//
HRESULT HrSetupDiSetDeviceRegistryProperty(IN HDEVINFO hdi, IN OUT PSP_DEVINFO_DATA pdeid, IN DWORD dwProperty, IN const BYTE* pbBuffer, IN DWORD cbSize) { Assert(IsValidHandle(hdi)); Assert(pdeid); Assert(pbBuffer);
HRESULT hr = S_OK;
// Set the property
if (!SetupDiSetDeviceRegistryProperty(hdi, pdeid, dwProperty, pbBuffer, cbSize)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiSetDeviceRegistryProperty", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiSendPropertyChangeNotification
//
// Purpose: This sends a DIF_PROPERTCHANGE notification to the
// class installer
//
// Arguments:
// hdi [in] See Device Isntaller Api
// pdeid [in]
// dwStateChange [in]
// dwScope [in]
// dwProfileId [in]
//
// Returns: HRESULT. S_OK if no error, a Win32 error converted
// code otherwise
//
// Author: billbe 4 Nov 1997
//
// Notes:
//
HRESULT HrSetupDiSendPropertyChangeNotification(HDEVINFO hdi, PSP_DEVINFO_DATA pdeid, DWORD dwStateChange, DWORD dwScope, DWORD dwProfileId) { Assert(IsValidHandle(hdi)); Assert(pdeid);
// First we create the property change structure and fill out its fields
//
SP_PROPCHANGE_PARAMS pcp; ZeroMemory(&pcp, sizeof(pcp)); pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; pcp.StateChange = dwStateChange; pcp.Scope = dwScope; pcp.HwProfile = dwProfileId;
// Now we set the structure as the device info data's
// class install params
HRESULT hr = HrSetupDiSetClassInstallParams(hdi, pdeid, reinterpret_cast<SP_CLASSINSTALL_HEADER*>(&pcp), sizeof(pcp));
if (SUCCEEDED(hr)) { // Now we need to set the "we have a class install params" flag
// in the device install params
//
SP_DEVINSTALL_PARAMS deip; hr = HrSetupDiGetDeviceInstallParams(hdi, pdeid, &deip); if (SUCCEEDED(hr)) { deip.Flags |= DI_CLASSINSTALLPARAMS; hr = HrSetupDiSetDeviceInstallParams(hdi, pdeid, &deip);
if (SUCCEEDED(hr)) { // Notify the driver that the state has changed
hr = HrSetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hdi, pdeid);
if (SUCCEEDED(hr)) { // Set the properties change flag in the device info to
// let anyone who cares know that their ui might need
// updating to reflect any change in the device's status
// We can't let any failures here stop us so we ignore
// return values
//
(void) HrSetupDiGetDeviceInstallParams(hdi, pdeid, &deip); deip.Flags |= DI_PROPERTIES_CHANGE; (void) HrSetupDiSetDeviceInstallParams(hdi, pdeid, &deip); } } } }
TraceError("HrSetupDiSendPropertyChangeNotification", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: FSetupDiCheckIfRestartNeeded
//
// Purpose: Checks the hdi and pdeid for the presence of the
// restart flag in the install params structure.
// See Device Installer Api for more info.
//
// Arguments:
// hdi [in] See Device Installer Api
// pdeid [in]
//
// Returns: BOOL. TRUE if a restart is required, FALSE otherwise
//
// Author: billbe 28 Apr 1997
//
// Notes:
//
BOOL FSetupDiCheckIfRestartNeeded(HDEVINFO hdi, PSP_DEVINFO_DATA pdeid) { Assert(IsValidHandle(hdi)); Assert(pdeid);
SP_DEVINSTALL_PARAMS deip; BOOL fRestart = FALSE;
// Get the install params for the device pdeid.
HRESULT hr = HrSetupDiGetDeviceInstallParams(hdi, pdeid, &deip); if (SUCCEEDED(hr)) { // Check for the presence of the flag
if ((deip.Flags & DI_NEEDRESTART) || (deip.Flags & DI_NEEDREBOOT)) { fRestart = TRUE; } }
// We don't return any failures from this function since it is just
// a check but we should trace them
TraceError("FSetupDiCheckIfRestartNeeded", hr); return fRestart; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiGetClassImageList
//
// Purpose: Builds an image list that contains bitmaps for every
// installed class and returns the list in a data structure
//
// Arguments:
// pcild [out] See Device Installer Api for more info
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 26 Nov 1997
//
// Notes: The image list will be in the ImageList field of the pcild
// structure
//
HRESULT HrSetupDiGetClassImageList(PSP_CLASSIMAGELIST_DATA pcild) { Assert(pcild);
HRESULT hr = S_OK;
ZeroMemory(pcild, sizeof(*pcild)); pcild->cbSize = sizeof(*pcild);
if (!SetupDiGetClassImageList(pcild)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiGetClassImageList", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiDestroyClassImageList
//
// Purpose: Destroys a class image list that was built with
// (Hr)SetupDiGetClassImageList
//
// Arguments:
// pcild [in] See Device Installer Api for more info
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 26 Nov 1997
//
// Notes:
//
HRESULT HrSetupDiDestroyClassImageList(PSP_CLASSIMAGELIST_DATA pcild) { Assert(pcild);
HRESULT hr = S_OK;
if (!SetupDiDestroyClassImageList(pcild)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiDestroyClassImageList", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiGetClassImageIndex
//
// Purpose: Retrieves the index within the class image list of a
// specified class
//
// Arguments:
// pcild [in] See Device Installer Api for more info
// guidClass [in]
// pnIndex [out]
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 26 Nov 1997
//
// Notes:
//
HRESULT HrSetupDiGetClassImageIndex(PSP_CLASSIMAGELIST_DATA pcild, const GUID* pguidClass, INT* pnIndex) { Assert(pcild); Assert(pguidClass); Assert(pnIndex);
HRESULT hr = S_OK;
if (!SetupDiGetClassImageIndex(pcild, pguidClass, pnIndex)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupDiGetClassImageIndex", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupDiGetParentWindow
//
// Purpose: Returns the window handle found in the install params of a
// device info set/data. Set SP_DEVINSTALL_PARAMS in the
// SetupApi for more info.
//
// Arguments:
// hdi [in] See SetupApi for more info
// pdeid [in] See SetupApi for more info
// phwndParent [out] Pointer to the parent window handle
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 12 May 1997
//
// Notes:
//
HRESULT HrSetupDiGetParentWindow (HDEVINFO hdi, PSP_DEVINFO_DATA pdeid, OPTIONAL HWND* phwndParent) { Assert(IsValidHandle(hdi)); Assert(phwndParent);
// Initialize the output parameter.
*phwndParent = NULL;
// Get the install params of the device
SP_DEVINSTALL_PARAMS deip; HRESULT hr = HrSetupDiGetDeviceInstallParams(hdi, pdeid, &deip); if (SUCCEEDED(hr)) { // Only assign the output if we have a valid window handle
if (IsWindow(deip.hwndParent)) { *phwndParent = deip.hwndParent; } }
TraceError("HrSetupDiGetParentWindow", hr); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupInstallFilesFromInfSection
//
// Purpose: Queues all the files specified in the Copy Files sections
// listed by an Install section for installation.
//
// Arguments:
// hinf [in] See SetupApi for more info
// hinfLayout [in] Optional
// hfq [in]
// pszSection [in]
// pszSourcePath [in] Optional
// ulFlags [in] Optional
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 21 July 1997
//
// Notes:
//
HRESULT HrSetupInstallFilesFromInfSection ( IN HINF hinf, IN HINF hinfLayout, IN HSPFILEQ hfq, IN PCWSTR pszSection, IN PCWSTR pszSourcePath, IN UINT ulFlags) { Assert(IsValidHandle(hinf)); Assert(FImplies(hinfLayout, INVALID_HANDLE_VALUE != hinfLayout)); Assert(pszSection);
HRESULT hr = S_OK;
if (!SetupInstallFilesFromInfSection(hinf, hinfLayout, hfq, pszSection, pszSourcePath, ulFlags)) { hr = HrFromLastWin32Error(); }
TraceError("HrSetupInstallFilesFromInfSection", hr); return hr;
}
//+--------------------------------------------------------------------------
//
// Function: HrSetupInstallFromInfSection
//
// Purpose: Carries out all the directives in an INF file Install section.
//
// Arguments:
// hwnd [in] See SetupApi for more info
// hinf [in]
// pszSection [in]
// ulFlags [in]
// hkey [in]
// pszSource [in]
// ulCopyFlags [in]
// pfc [in]
// pvCtx [in]
// hdi [in]
// pdeid [in]
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 5 July 1997
//
// Notes:
//
HRESULT HrSetupInstallFromInfSection ( IN HWND hwnd, IN HINF hinf, IN PCWSTR pszSection, IN UINT ulFlags, IN HKEY hkey, IN PCWSTR pszSource, IN UINT ulCopyFlags, IN PSP_FILE_CALLBACK pfc, IN PVOID pvCtx, IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid) { Assert(IsValidHandle(hinf)); Assert(pszSection);
HRESULT hr = S_OK;
if (!SetupInstallFromInfSection(hwnd, hinf, pszSection, ulFlags, hkey, pszSource, ulCopyFlags, pfc, pvCtx, hdi, pdeid)) { hr = HrFromLastWin32Error(); }
TraceHr (ttidError, FAL, hr, FALSE, "HrSetupInstallFromInfSection (%S)", pszSection); return hr; }
//+--------------------------------------------------------------------------
//
// Function: HrSetupInstallServicesFromInfSection
//
// Purpose: Carries out all the service directives in an INF file Install
// section.
//
// Arguments:
// hinf [in] See SetupApi for more info
// pszSection [in]
// dwFlags [in]
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 19 Feb 1998
//
// Notes:
//
HRESULT HrSetupInstallServicesFromInfSection ( IN HINF hinf, IN PCWSTR pszSection, IN DWORD dwFlags) { Assert(IsValidHandle(hinf)); Assert(pszSection);
HRESULT hr = S_OK;
if (!SetupInstallServicesFromInfSection(hinf, pszSection, dwFlags)) { hr = HrFromLastWin32Error(); }
TraceHr (ttidError, FAL, hr, (SPAPI_E_SECTION_NOT_FOUND == hr), "HrSetupInstallServicesFromInfSection (%S)", pszSection); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrOpenSoftwareDeviceEnumerator
//
// Purpose: Opens the swenum device driver used to install software-
// enumerated device drivers.
//
// Arguments:
// dwFlagsAndAttributes [in] See CreateFile.
// phFile [out] The returned handle to the swenum device.
//
// Returns: S_OK or an error code.
//
// Author: shaunco 30 Mar 1998
//
// Notes:
//
HRESULT HrOpenSoftwareDeviceEnumerator ( DWORD dwFlagsAndAttributes, HANDLE* phFile) { Assert (phFile);
// Initialize the output parameter.
//
*phFile = INVALID_HANDLE_VALUE;
// Get the devices in software device enumerator class. There should
// only be one. (Or rather, we're only interested in the first one.)
//
HDEVINFO hdi; HRESULT hr = HrSetupDiGetClassDevs (&BUSID_SoftwareDeviceEnumerator, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE, &hdi); if (S_OK == hr) { // Enumerate the first device in this class. This will
// initialize did.
//
SP_DEVICE_INTERFACE_DATA did; ZeroMemory (&did, sizeof(did)); did.cbSize = sizeof(did);
if (SetupDiEnumDeviceInterfaces (hdi, NULL, const_cast<LPGUID>(&BUSID_SoftwareDeviceEnumerator), 0, &did)) { // Now get the details so we can open the device.
//
const ULONG cbDetail = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + (MAX_PATH * sizeof(WCHAR)); PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;
hr = HrMalloc (cbDetail, (PVOID*)&pDetail); if (S_OK == hr) { pDetail->cbSize = sizeof(*pDetail);
if (SetupDiGetDeviceInterfaceDetail (hdi, &did, pDetail, cbDetail, NULL, NULL)) { // Now open the device (swenum).
//
HANDLE hFile = CreateFile (pDetail->DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL); if (hFile && (INVALID_HANDLE_VALUE != hFile)) { *phFile = hFile; } else { hr = HrFromLastWin32Error (); } } else { hr = HrFromLastWin32Error (); }
MemFree (pDetail); } } else { hr = HrFromLastWin32Error (); }
SetupDiDestroyDeviceInfoList (hdi); } TraceHr (ttidError, FAL, hr, FALSE, "HrOpenSoftwareDeviceEnumerator"); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrFindDeviceOnInterface
//
// Purpose: Searches for a specific device on a given interface.
// It does this by using setup api to return all of the
// devices in the class given by pguidInterfaceId. It then
// gets device path for each of these device interfaces and
// looks for pguidDeviceId and pszReferenceString as substrings.
//
// Arguments:
// pguidDeviceId [in] The device id to find.
// pguidInterfaceId [in] The interface on which to look.
// pszReferenceString [in] Optional. Further match on this ref string.
// dwFlagsAndAttributes [in] See CreateFile. This is how the device is
// opened if it is found.
// phFile [out] The returned device handle.
//
// Returns: S_OK if found and opened, S_FALSE if not found, or an error.
//
// Author: shaunco 30 Mar 1998
//
// Notes:
//
HRESULT HrFindDeviceOnInterface ( IN const GUID* pguidDeviceId, IN const GUID* pguidInterfaceId, IN PCWSTR pszReferenceString, IN DWORD dwFlagsAndAttributes, OUT HANDLE* phFile) { Assert (pguidDeviceId); Assert (pguidInterfaceId); Assert (phFile);
// Initialize the output parameter.
//
*phFile = INVALID_HANDLE_VALUE;
WCHAR szDeviceId [c_cchGuidWithTerm]; INT cch = StringFromGUID2 (*pguidDeviceId, szDeviceId, c_cchGuidWithTerm); Assert (c_cchGuidWithTerm == cch); CharLower (szDeviceId);
// Get the devices in this class.
//
HDEVINFO hdi; HRESULT hr = HrSetupDiGetClassDevs (pguidInterfaceId, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE, &hdi); if (S_OK == hr) { BOOL fFound = FALSE;
// abBuffer is a buffer used to get device interface detail for each
// device interface enumerated below.
//
const ULONG cbDetail = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + (MAX_PATH * sizeof(WCHAR)); PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;
hr = HrMalloc (cbDetail, (PVOID*)&pDetail); if (S_OK == hr) { // Enumerate the device interfaces looking for the one specified.
//
SP_DEVICE_INTERFACE_DATA did; ZeroMemory (&did, sizeof(did));
for (DWORD i = 0; did.cbSize = sizeof(did), SetupDiEnumDeviceInterfaces (hdi, NULL, const_cast<LPGUID>(pguidInterfaceId), i, &did); i++) { // Now get the details so we can compare the device path.
//
pDetail->cbSize = sizeof(*pDetail); if (SetupDiGetDeviceInterfaceDetailW (hdi, &did, pDetail, cbDetail, NULL, NULL)) { CharLower (pDetail->DevicePath);
// Look for a substring containing szDeviceId. Also
// look for a substring containing pszReferenceString if
// it is specified.
//
if (wcsstr (pDetail->DevicePath, szDeviceId) && (!pszReferenceString || !*pszReferenceString || wcsstr (pDetail->DevicePath, pszReferenceString))) { // We found it, so open the device and return it.
//
HANDLE hFile = CreateFile (pDetail->DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL); if (hFile && (INVALID_HANDLE_VALUE != hFile)) { TraceTag (ttidNetcfgBase, "Found device id '%S'", szDeviceId);
TraceTag (ttidNetcfgBase, "Opening device '%S'", pDetail->DevicePath);
*phFile = hFile; fFound = TRUE; } else { hr = HrFromLastWin32Error (); }
// Now that we've found it, break out of the loop.
//
break; } } else { hr = HrFromLastWin32Error (); } }
MemFree (pDetail); }
SetupDiDestroyDeviceInfoList (hdi);
if (SUCCEEDED(hr) && !fFound) { hr = S_FALSE; } }
TraceHr(ttidError, FAL, hr, S_FALSE == hr, "HrFindDeviceOnInterface (device=%S)", szDeviceId); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrInstallSoftwareDeviceOnInterface
//
// Purpose: Install a software-enumerated device on the given interface.
//
// Arguments:
// pguidDeviceId [in] The device id to install.
// pguidInterfaceId [in] The interface to install it on.
// pszReferenceString [in] The reference string.
// fForceInstall [in] Usually specify FALSE. Specify TRUE to
// force installation of the device using
// pguidClass and pszHardwareId.
// Typically this is used during GUI mode setup
// where swenum won't be able to fully install
// the device.
//
// Returns: S_OK or an error code.
//
// Author: shaunco 30 Mar 1998
//
// Notes:
//
HRESULT HrInstallSoftwareDeviceOnInterface ( const GUID* pguidDeviceId, const GUID* pguidInterfaceId, PCWSTR pszReferenceString, BOOL fForceInstall, PCWSTR pszInfFilename, HWND hwndParent) { Assert (pguidDeviceId); Assert (pguidInterfaceId); Assert (pszReferenceString && *pszReferenceString);
// Open the software device enumerator.
//
HANDLE hSwenum; HRESULT hr = HrOpenSoftwareDeviceEnumerator ( FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, &hSwenum); if (S_OK == hr) { Assert (INVALID_HANDLE_VALUE != hSwenum);
// Enable the SE_LOAD_DRIVER_NAME privilege, required by swenum for
// installation of new devices.
//
if (S_OK == (hr = HrEnablePrivilege(SE_LOAD_DRIVER_NAME))) {
// Allocate and build the buffer used as the IOCTL parameter.
//
const ULONG cbBuf = (ULONG)FIELD_OFFSET (SWENUM_INSTALL_INTERFACE, ReferenceString) + CbOfSzAndTerm (pszReferenceString); SWENUM_INSTALL_INTERFACE* pBuf;
hr = HrMalloc (cbBuf, (PVOID*)&pBuf); if (S_OK == hr) { ZeroMemory (pBuf, cbBuf); pBuf->DeviceId = *pguidDeviceId; pBuf->InterfaceId = *pguidInterfaceId; lstrcpyW (pBuf->ReferenceString, pszReferenceString);
// Create an event to be used for the overlapped IO we are about
// to issue.
//
OVERLAPPED ovl; ZeroMemory (&ovl, sizeof(ovl)); ovl.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL); if (ovl.hEvent) { #ifdef ENABLETRACE
WCHAR szDeviceId [c_cchGuidWithTerm]; INT cch = StringFromGUID2 (pBuf->DeviceId, szDeviceId, c_cchGuidWithTerm); Assert (c_cchGuidWithTerm == cch);
WCHAR szInterfaceId [c_cchGuidWithTerm]; cch = StringFromGUID2 (pBuf->InterfaceId, szInterfaceId, c_cchGuidWithTerm); Assert (c_cchGuidWithTerm == cch);
TraceTag (ttidNetcfgBase, "Installing software enumerated " "device '%S' on interface '%S'", szDeviceId, szInterfaceId); #endif
// Issue the install interface IOCTL.
//
DWORD cbReturned; BOOL fIoResult = DeviceIoControl (hSwenum, IOCTL_SWENUM_INSTALL_INTERFACE, pBuf, cbBuf, NULL, 0, &cbReturned, &ovl); if (!fIoResult) { hr = HrFromLastWin32Error (); if (HRESULT_FROM_WIN32 (ERROR_IO_PENDING) == hr) { // Wait for the IO to complete if it was returned as
// pending.
//
fIoResult = GetOverlappedResult (hSwenum, &ovl, &cbReturned, TRUE); if (!fIoResult) { hr = HrFromLastWin32Error (); } } }
CloseHandle (ovl.hEvent); }
MemFree (pBuf); } }
CloseHandle (hSwenum); }
// Force the device to be installed by enumerating it.
//
if ((S_OK == hr) && fForceInstall) { HANDLE hDevice;
hr = HrFindDeviceOnInterface ( pguidDeviceId, pguidInterfaceId, pszReferenceString, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, &hDevice);
if (S_OK == hr) { CloseHandle (hDevice); } else if (S_FALSE == hr) { // We just installed this device, why wasn't it found?
//
hr = E_UNEXPECTED; } }
TraceHr (ttidError, FAL, hr, FALSE, "HrInstallSoftwareDeviceOnInterface"); return hr; }
// ----------------------------------------------------------------------
//
// Function: HrInstallFromInfSectionInFile
//
// Purpose: Open the given INF file and call Setup API to install
// from the specified section.
//
// Arguments:
// hwndParent [in] handle of parent window
// szInfName [in] name of INF
// szSection [in] section name
// hkeyRelative [in] handle of reg-key to use
// fQuietInstall [in] TRUE if we shouldn't show UI and use
// default values, FALSE if we can bother
// the user with questions and UI
//
// Returns: S_OK on success, otherwise an error code
//
// Author: kumarp 23-December-97
//
// Notes:
//
HRESULT HrInstallFromInfSectionInFile ( IN HWND hwndParent, IN PCWSTR pszInfName, IN PCWSTR pszSection, IN HKEY hkeyRelative, IN BOOL fQuietInstall) { AssertValidReadPtr(pszInfName); AssertValidReadPtr(pszSection);
HRESULT hr; HINF hinf;
hr = HrSetupOpenInfFile(pszInfName, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL, &hinf); if (S_OK == hr) { hr = HrSetupInstallFromInfSection (hwndParent, hinf, pszSection, SPINST_REGISTRY, hkeyRelative, NULL, 0, NULL, NULL, NULL, NULL); }
TraceError("HrInstallInfSectionInfFile", hr); return hr; }
#if defined(REMOTE_BOOT)
//+--------------------------------------------------------------------------
//
// Function: HrIsRemoteBootAdapter
//
// Purpose: This determines whether the adapter is a remote boot adapter
//
// Arguments:
// hdi [in] See Device Installer Api for more info
// pdeid [in] See Device Installer Api for more info
//
// Returns: HRESULT. S_OK if adapter is a remote boot adapter
// S_FALSE if adapter is not a remote boot adapter
// a Win32 converted error otherwise
//
//
// Author: billbe 31 Jan 1998
//
// Notes:
//
HRESULT HrIsRemoteBootAdapter(HDEVINFO hdi, PSP_DEVINFO_DATA pdeid) { Assert(IsValidHandle(hdi)); Assert(pdeid);
DWORD dwConfigFlags;
// Get the current config flags
HRESULT hr = HrSetupDiGetDeviceRegistryProperty(hdi, pdeid, SPDRP_CONFIGFLAGS, NULL, (BYTE*)&dwConfigFlags, sizeof(dwConfigFlags), NULL);
if (SUCCEEDED(hr)) { if (dwConfigFlags & CONFIGFLAG_NETBOOT_CARD) { hr = S_OK; } else { hr = S_FALSE; } } else if (HRESULT_FROM_WIN32(ERROR_INVALID_DATA) == hr) { // The device had no config flags, so it isn't a remote boot adapter
hr = S_FALSE; }
TraceError("HrIsRemoteBootAdapter", (hr == S_FALSE) ? S_OK : hr); return hr; } #endif // defined(REMOTE_BOOT)
VOID SetupDiDestroyDeviceInfoListSafe(HDEVINFO hdi) { if (IsValidHandle(hdi)) { SetupDiDestroyDeviceInfoList(hdi); } }
VOID SetupCloseInfFileSafe(HINF hinf) { if (IsValidHandle(hinf)) { SetupCloseInfFile(hinf); } }
|