462 lines
13 KiB
C
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);
|
|
}
|