windows-nt/Source/XPSP1/NT/net/config/samples/muxim/setupdi.cpp
2020-09-26 16:20:57 +08:00

422 lines
11 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: S E T U P D I . C P P
//
// Contents: Code to copy Net class inf file
//
// Notes:
//
//----------------------------------------------------------------------------
#include "notify.h"
// =================================================================
// Forward declarations
HRESULT HrCopyMiniportInf (VOID);
HRESULT HrGetProtocolInf (LPWSTR lpszWindowsDir,
LPWSTR *lppszProtocolInf);
HRESULT HrGetMediaRootDir (LPWSTR lpszInfFile,
LPWSTR *lppszMediaRoot);
HRESULT HrGetPnpID (LPWSTR lpszInfFile,
LPWSTR *lppszPnpID);
HRESULT HrGetKeyValue (HINF hInf,
LPCWSTR lpszSection,
LPCWSTR lpszKey,
DWORD dwIndex,
LPWSTR *lppszValue);
const WCHAR c_szInfPath[] = L"Inf\\";
const WCHAR c_szMiniportInf[] = L"mux_mp.inf";
const WCHAR c_szInfSourcePathInfo[] = L"InfSourcePathInfo";
const WCHAR c_szOriginalInfSourcePath[] = L"OriginalInfSourcePath";
HRESULT HrCopyMiniportInf (VOID)
{
LPWSTR lpszWindowsDir;
LPWSTR lpszProtocolInf;
LPWSTR lpszMediaRoot;
LPWSTR lpszMiniportInf;
DWORD dwLen;
HRESULT hr;
//
// Get %windir% directory.
//
dwLen = GetSystemWindowsDirectoryW( NULL, 0 );
if ( dwLen == 0 )
{
return HRESULT_FROM_WIN32(GetLastError());
}
// Add 1 for NULL and 1 for "\" in case it is needed.
dwLen += wcslen(c_szInfPath) + 2;
lpszWindowsDir = (LPWSTR)CoTaskMemAlloc( dwLen * sizeof(WCHAR) );
if ( !lpszWindowsDir )
{
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
if ( GetSystemWindowsDirectoryW(lpszWindowsDir, dwLen) == 0 )
{
hr = HRESULT_FROM_WIN32( GetLastError() );
}
else
{
// Append "inf\" to %windir%.
dwLen = wcslen( lpszWindowsDir );
if ( lpszWindowsDir[dwLen-1] == L'\\' )
{
wcscat( lpszWindowsDir, c_szInfPath );
}
else
{
wcscat( lpszWindowsDir, L"\\" );
wcscat( lpszWindowsDir, c_szInfPath );
}
//
// Find the protocol inf name. Originally, it was netsf.inf but has
// been renamed to oem?.inf by SetupCopyOEMInf.
//
hr = HrGetProtocolInf( lpszWindowsDir, &lpszProtocolInf );
if ( hr == S_OK )
{
//
// Get the directory from where protocol was installed.
hr = HrGetMediaRootDir( lpszProtocolInf, &lpszMediaRoot );
if ( hr == S_OK )
{
TraceMsg(L"Media root directory is %s.\n", lpszMediaRoot);
// Add 1 for NULL and 1 for "\" in case it is needed.
lpszMiniportInf = (LPWSTR)CoTaskMemAlloc( (wcslen(lpszMediaRoot) +
wcslen(c_szMiniportInf) + 2) *
sizeof(WCHAR) );
if ( lpszMiniportInf == NULL )
{
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
else
{
//
// We know the full path from where the protocol is being installed. Our
// miniport inf is in the same location. Copy the miniport inf to
// %windir%\inf so that when we install the virtual miniport, Setup
// will find the miniport inf.
//
wcscpy( lpszMiniportInf, lpszMediaRoot );
dwLen = wcslen( lpszMiniportInf );
if ( lpszMiniportInf[dwLen-1] != L'\\' )
{
wcscat( lpszMiniportInf, L"\\" );
}
wcscat( lpszMiniportInf, c_szMiniportInf );
TraceMsg(L"Calling SetupCopyOEMInf for %s.\n", lpszMiniportInf);
if ( !SetupCopyOEMInfW(lpszMiniportInf,
lpszMediaRoot,
SPOST_PATH,
0,
NULL,
0,
NULL,
NULL) )
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
CoTaskMemFree( lpszMiniportInf );
}
CoTaskMemFree( lpszMediaRoot );
}
CoTaskMemFree( lpszProtocolInf );
}
}
CoTaskMemFree( lpszWindowsDir );
return hr;
}
//
// The function searches through all the inf files in %windir%\inf and
// returns the name of the protocol's inf.
//
HRESULT HrGetProtocolInf (LPWSTR lpszWindowsDir,
LPWSTR *lppszProtocolInf)
{
LPWSTR lpszFileList;
LPWSTR lpszFile;
LPWSTR lpszFileWithPath;
LPWSTR lpszPnpID;
DWORD dwSizeNeeded;
BOOL fTrailingSlash;
DWORD dwLen;
BYTE found;
HRESULT hr;
*lppszProtocolInf = NULL;
dwLen = wcslen( lpszWindowsDir );
fTrailingSlash = lpszWindowsDir[dwLen-1] == L'\\';
if ( SetupGetInfFileListW(lpszWindowsDir,
INF_STYLE_WIN4,
NULL,
0,
&dwSizeNeeded) == 0 )
{
return HRESULT_FROM_WIN32(GetLastError());
}
lpszFileList = (LPWSTR)CoTaskMemAlloc( sizeof(WCHAR) * dwSizeNeeded );
if ( !lpszFileList )
{
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
if ( SetupGetInfFileListW( lpszWindowsDir,
INF_STYLE_WIN4,
lpszFileList,
dwSizeNeeded,
NULL) == 0 )
{
CoTaskMemFree( lpszFileList );
return HRESULT_FROM_WIN32(GetLastError());
}
lpszFile = lpszFileList;
found = 0;
hr = S_OK;
while( (hr == S_OK) && !found && *lpszFile )
{
lpszFileWithPath = (LPWSTR)CoTaskMemAlloc( sizeof(WCHAR) *
(wcslen(lpszFile) +
dwLen + 1 +
((fTrailingSlash) ? 0 : 1)) );
if ( !lpszFileWithPath )
{
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
else
{
if ( fTrailingSlash )
{
swprintf( lpszFileWithPath, L"%s%s",
lpszWindowsDir,
lpszFile );
}
else
{
swprintf( lpszFileWithPath, L"%s\\%s",
lpszWindowsDir,
lpszFile );
}
hr = HrGetPnpID( lpszFileWithPath, &lpszPnpID );
// If the inf file installs a driver then, it will have a Model
// section with the hwid/PnpID of the driver that is installed.
//
// In case, there is an error getting the hwid, we simply ignore
// the inf file and continue with the next one.
if ( hr == S_OK )
{
if (_wcsicmp(lpszPnpID, c_szMuxProtocol) == 0 )
{
found = 1;
}
CoTaskMemFree( lpszPnpID );
}
if ( !found )
{
hr = S_OK;
CoTaskMemFree( lpszFileWithPath );
lpszFile += wcslen(lpszFile) + 1;
}
}
}
if ( found )
{
*lppszProtocolInf = lpszFileWithPath;
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
}
CoTaskMemFree( lpszFileList );
return hr;
}
HRESULT HrGetPnpID (LPWSTR lpszInfFile,
LPWSTR *lppszPnpID)
{
HINF hInf;
LPWSTR lpszModelSection;
HRESULT hr;
*lppszPnpID = NULL;
hInf = SetupOpenInfFileW( lpszInfFile,
NULL,
INF_STYLE_WIN4,
NULL );
if ( hInf == INVALID_HANDLE_VALUE )
{
return HRESULT_FROM_WIN32(GetLastError());
}
hr = HrGetKeyValue( hInf,
L"Manufacturer",
NULL,
1,
&lpszModelSection );
if ( hr == S_OK )
{
hr = HrGetKeyValue( hInf,
lpszModelSection,
NULL,
2,
lppszPnpID );
CoTaskMemFree( lpszModelSection );
}
SetupCloseInfFile( hInf );
return hr;
}
HRESULT HrGetMediaRootDir (LPWSTR lpszInfFile,
LPWSTR *lppszMediaRoot)
{
HINF hInf;
HRESULT hr;
*lppszMediaRoot = NULL;
hInf = SetupOpenInfFileW( lpszInfFile,
NULL,
INF_STYLE_WIN4,
NULL );
if ( hInf == INVALID_HANDLE_VALUE )
{
return HRESULT_FROM_WIN32(GetLastError());
}
//
// Contained within the protocol INF should be a [InfSourcePathInfo]
// section with the following entry:
//
// OriginalInfSourcePath = %1%
//
// If we retrieve the value (i.e., field 1) of this line, we'll get the
// full path where the INF originally came from.
//
hr = HrGetKeyValue( hInf,
c_szInfSourcePathInfo,
c_szOriginalInfSourcePath,
1,
lppszMediaRoot );
SetupCloseInfFile( hInf );
return hr;
}
HRESULT HrGetKeyValue (HINF hInf,
LPCWSTR lpszSection,
LPCWSTR lpszKey,
DWORD dwIndex,
LPWSTR *lppszValue)
{
INFCONTEXT infCtx;
DWORD dwSizeNeeded;
HRESULT hr;
*lppszValue = NULL;
if ( SetupFindFirstLineW(hInf,
lpszSection,
lpszKey,
&infCtx) == FALSE )
{
return HRESULT_FROM_WIN32(GetLastError());
}
SetupGetStringFieldW( &infCtx,
dwIndex,
NULL,
0,
&dwSizeNeeded );
*lppszValue = (LPWSTR)CoTaskMemAlloc( sizeof(WCHAR) * dwSizeNeeded );
if ( !*lppszValue )
{
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
if ( SetupGetStringFieldW(&infCtx,
dwIndex,
*lppszValue,
dwSizeNeeded,
NULL) == FALSE )
{
hr = HRESULT_FROM_WIN32(GetLastError());
CoTaskMemFree( *lppszValue );
*lppszValue = NULL;
}
else
{
hr = S_OK;
}
return hr;
}