/*++ 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); }