windows-nt/Source/XPSP1/NT/base/pnp/setupapi/infsdisk.c
2020-09-26 16:20:57 +08:00

462 lines
13 KiB
C

/*++
Copyright (c) 1995-2000 Microsoft Corporation
Module Name:
infsdisk.c
Abstract:
Externally exposed INF routines for source disk descriptor manipulation.
Author:
Ted Miller (tedm) 9-Feb-1995
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//
// Locations of various fields in the [SourceDisksNames] section
// of an inf
//
#define DISKNAMESECT_DESCRIPTION 1
#define DISKNAMESECT_TAGFILE 2 // cabinet name in win95
#define DISKNAMESECT_OEM 3 // unused, indicates oem disk in win95
#define DISKNAMESECT_PATH 4
#define DISKNAMESECT_FLAGS 5 // indicates extra tags
#define DISKNAMESECT_TAGFILE2 6 // real tagfile if DISKNAMESECT_TAGFILE is really a cabfile
#ifdef UNICODE
//
// ANSI version
//
BOOL
SetupGetSourceInfoA(
IN HINF InfHandle,
IN UINT SourceId,
IN UINT InfoDesired,
OUT PSTR ReturnBuffer, OPTIONAL
IN DWORD ReturnBufferSize,
OUT PDWORD RequiredSize OPTIONAL
)
{
DWORD rc;
BOOL b;
PWCHAR buffer;
DWORD requiredsize;
PCSTR ansi;
buffer = MyMalloc(MAX_INF_STRING_LENGTH);
if (buffer) {
b = pSetupGetSourceInfo(
InfHandle,
NULL,
SourceId,
NULL,
InfoDesired,
buffer,
MAX_INF_STRING_LENGTH,
&requiredsize
);
rc = GetLastError();
if(b) {
rc = NO_ERROR;
if(ansi = pSetupUnicodeToAnsi(buffer)) {
requiredsize = lstrlenA(ansi)+1;
if(RequiredSize) {
try {
*RequiredSize = requiredsize;
} except(EXCEPTION_EXECUTE_HANDLER) {
rc = ERROR_INVALID_PARAMETER;
b = FALSE;
}
}
if((rc == NO_ERROR) && ReturnBuffer) {
if(!lstrcpynA(ReturnBuffer,ansi,ReturnBufferSize)) {
//
// ReturnBuffer invalid
//
rc = ERROR_INVALID_PARAMETER;
b = FALSE;
}
}
MyFree(ansi);
} else {
rc = ERROR_NOT_ENOUGH_MEMORY;
b = FALSE;
}
}
MyFree(buffer);
} else {
rc = ERROR_NOT_ENOUGH_MEMORY;
b = FALSE;
}
SetLastError(rc);
return(b);
}
#else
//
// Unicode stub
//
BOOL
SetupGetSourceInfoW(
IN HINF InfHandle,
IN UINT SourceId,
IN UINT InfoDesired,
OUT PWSTR ReturnBuffer, OPTIONAL
IN DWORD ReturnBufferSize,
OUT PDWORD RequiredSize OPTIONAL
)
{
UNREFERENCED_PARAMETER(InfHandle);
UNREFERENCED_PARAMETER(SourceId);
UNREFERENCED_PARAMETER(InfoDesired);
UNREFERENCED_PARAMETER(ReturnBuffer);
UNREFERENCED_PARAMETER(ReturnBufferSize);
UNREFERENCED_PARAMETER(RequiredSize);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return(FALSE);
}
#endif
BOOL
SetupGetSourceInfo(
IN HINF InfHandle,
IN UINT SourceId,
IN UINT InfoDesired,
OUT PTSTR ReturnBuffer, OPTIONAL
IN DWORD ReturnBufferSize,
OUT PDWORD RequiredSize OPTIONAL
)
//
// Native version
//
{
return pSetupGetSourceInfo(InfHandle,
NULL,
SourceId,
NULL,
InfoDesired,
ReturnBuffer,
ReturnBufferSize,
RequiredSize
);
}
BOOL
pSetupGetSourceInfo(
IN HINF InfHandle, OPTIONAL
IN PINFCONTEXT LayoutLineContext, OPTIONAL
IN UINT SourceId,
IN PSP_ALTPLATFORM_INFO_V2 AltPlatformInfo, OPTIONAL
IN UINT InfoDesired,
OUT PTSTR ReturnBuffer, OPTIONAL
IN DWORD ReturnBufferSize,
OUT PDWORD RequiredSize OPTIONAL
)
/*++
Routine Description:
Get information from SourceDisksNames
If InfHandle specified instead of LayoutLineContext
and the ID is specified in more than one INF
then the wrong information *MAY* be returned.
This effects callers of SetupGetSourceInfo
we need a SetupGetSourceInfoEx post 5.0
Arguments:
InfHandle - required if LayoutLineContext is not provided, else specifies a layout inf
SourceId - numerical source ID, used as search key in SourceDisksNames section
AltPlatformInfo - optionally, supplies alternate platform information used
in decorating the [SourceDisksNames] section.
InfoDesired -
SRCINFO_PATH
SRCINFO_TAGFILE
SRCINFO_DESCRIPTION
SRCINFO_FLAGS
ReturnBuffer - buffer for returned string
ReturnBufferSize - size of buffer
RequiredSize - size buffer needs to be if ReturnBufferSize too small
LayoutLineContext - if specified, used to determine correct INF to use if SourceID's conflict
Return Value:
Boolean value indicating outcome. If FALSE, GetLastError() returns
extended error information.
ReturnBuffer filled out with string
RequiredSize filled out with required size of buffer to hold string
--*/
{
PCTSTR PlatformName;
UINT ValueIndex;
BOOL Mandatory;
BOOL IsPath;
INFCONTEXT InfContext;
INFCONTEXT SelectedInfContext;
int SelectedRank;
TCHAR SourceIdString[24];
PCTSTR Value;
BOOL b;
UINT Length;
TCHAR MediaListSectionName[64];
HINF hInfPreferred = (HINF)(-1);
try {
if ((LayoutLineContext != NULL) && (LayoutLineContext != (PINFCONTEXT)(-1))) {
hInfPreferred = (HINF)LayoutLineContext->CurrentInf;
}
} except(EXCEPTION_EXECUTE_HANDLER) {
hInfPreferred = (HINF)(-1);
}
//
// Determine the index of the value that gives the caller the info he wants.
//
switch(InfoDesired) {
case SRCINFO_PATH:
ValueIndex = DISKNAMESECT_PATH;
Mandatory = FALSE;
IsPath = TRUE;
break;
case SRCINFO_TAGFILE:
ValueIndex = DISKNAMESECT_TAGFILE;
Mandatory = FALSE;
IsPath = TRUE;
break;
case SRCINFO_DESCRIPTION:
ValueIndex = DISKNAMESECT_DESCRIPTION;
Mandatory = TRUE;
IsPath = FALSE;
break;
case SRCINFO_FLAGS:
ValueIndex = DISKNAMESECT_FLAGS;
Mandatory = FALSE;
IsPath = FALSE;
break;
case SRCINFO_TAGFILE2:
ValueIndex = DISKNAMESECT_TAGFILE2;
Mandatory = FALSE;
IsPath = TRUE;
break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
wsprintf(SourceIdString,TEXT("%d"),SourceId);
if(AltPlatformInfo) {
switch(AltPlatformInfo->ProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_INTEL :
PlatformName = pszX86SrcDiskSuffix;
break;
case PROCESSOR_ARCHITECTURE_ALPHA :
PlatformName = pszAlphaSrcDiskSuffix;
break;
case PROCESSOR_ARCHITECTURE_IA64 :
PlatformName = pszIa64SrcDiskSuffix;
break;
case PROCESSOR_ARCHITECTURE_ALPHA64 :
PlatformName = pszAxp64SrcDiskSuffix;
break;
case PROCESSOR_ARCHITECTURE_AMD64 :
PlatformName = pszAmd64SrcDiskSuffix;
break;
default :
//
// unknown/unsupported processor architecture.
//
MYASSERT((AltPlatformInfo->ProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) ||
(AltPlatformInfo->ProcessorArchitecture == PROCESSOR_ARCHITECTURE_ALPHA) ||
(AltPlatformInfo->ProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) ||
(AltPlatformInfo->ProcessorArchitecture == PROCESSOR_ARCHITECTURE_ALPHA64) ||
(AltPlatformInfo->ProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
);
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
} else {
PlatformName = pszPlatformSrcDiskSuffix;
}
_sntprintf(
MediaListSectionName,
sizeof(MediaListSectionName)/sizeof(MediaListSectionName[0]),
TEXT("%s.%s"),
pszSourceDisksNames,
PlatformName
);
//
// we will prefer
// (1) an entry in hInfPreferred (Rank 11/12 decorated over undecorated)
// (2) an entry linked to hInfPreferred (Rank 21/22 decorated over undecorated)
// (3) an entry in hInfHandle (Rank 31/32 decorated over undecorated)
// (4) an entry linked to InfHandle (Rank 41/42 decorated over undecorated)
//
SelectedRank = 100; // 11-42 as above
if ((hInfPreferred != NULL) && (hInfPreferred != (HINF)(-1))) {
//
// see if we can find the SourceIdString in the INF that we found the section in
//
// rank 11 or 21 (decorated) - always try
//
if(SetupFindFirstLine(hInfPreferred,MediaListSectionName,SourceIdString,&InfContext)) {
if (InfContext.Inf == InfContext.CurrentInf) {
SelectedRank = 11;
SelectedInfContext = InfContext;
} else {
SelectedRank = 21;
SelectedInfContext = InfContext;
}
}
if (SelectedRank > 12) {
//
// rank 12 or 22 (undecorated) only try if we haven't got anything better than 12
//
if(SetupFindFirstLine(hInfPreferred,pszSourceDisksNames,SourceIdString,&InfContext)) {
if (InfContext.Inf == InfContext.CurrentInf) {
SelectedRank = 12;
SelectedInfContext = InfContext;
} else if (SelectedRank > 22) {
SelectedRank = 22;
SelectedInfContext = InfContext;
}
}
}
}
if ((InfHandle != NULL) && (InfHandle != (HINF)(-1)) && (SelectedRank > 31)) {
//
// see if we can find the SourceIdString in the supplied INF
//
// rank 31 or 41 (decorated) - only try if we haven't got anything better than 31
//
if(SetupFindFirstLine(InfHandle,MediaListSectionName,SourceIdString,&InfContext)) {
if (InfContext.Inf == InfContext.CurrentInf) {
SelectedRank = 31;
SelectedInfContext = InfContext;
} else if (SelectedRank > 41) {
SelectedRank = 41;
SelectedInfContext = InfContext;
}
}
if (SelectedRank > 32) {
//
// rank 32 or 42 (undecorated) - only try if we haven't got anything better than 32
//
if(SetupFindFirstLine(InfHandle,pszSourceDisksNames,SourceIdString,&InfContext)) {
if (InfContext.Inf == InfContext.CurrentInf) {
SelectedRank = 32;
SelectedInfContext = InfContext;
} else if (SelectedRank > 42) {
SelectedRank = 42;
SelectedInfContext = InfContext;
}
}
}
}
if(SelectedRank == 100 || (Value = pSetupGetField(&InfContext,ValueIndex))==NULL) {
if(Mandatory) {
SetLastError(ERROR_LINE_NOT_FOUND);
return(FALSE);
} else {
Value = TEXT("");
}
}
//
// Figure out how many characters are in the output.
// If the value is a path type value we want to remove
// the trailing backslash if there is one.
//
Length = lstrlen(Value);
if(IsPath && Length && (*CharPrev(Value,Value+Length) == TEXT('\\'))) {
Length--;
}
//
// Need to leave space for the trailing nul.
//
Length++;
if(RequiredSize) {
b = TRUE;
try {
*RequiredSize = Length;
} except(EXCEPTION_EXECUTE_HANDLER) {
b = FALSE;
}
if(!b) {
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
}
b = TRUE;
if(ReturnBuffer) {
if(Length <= ReturnBufferSize) {
//
// lstrcpyn is a strange API but the below is correct --
// the size parameter is actually the capacity of the
// target buffer. So to get it to put the nul in the
// right place we pass one larger than the number of chars
// we want copied.
//
if(!lstrcpyn(ReturnBuffer,Value,Length)) {
//
// ReturnBuffer invalid
//
b = FALSE;
SetLastError(ERROR_INVALID_PARAMETER);
}
} else {
b = FALSE;
SetLastError(ERROR_INSUFFICIENT_BUFFER);
}
}
return(b);
}