/*++ Copyright (c) 1993-1998 Microsoft Corporation Module Name: mru.c Abstract: Implementation of source list handling routines. Author: Ted Miller (tedm) 30-Aug-1995 Revision History: --*/ #include "precomp.h" #pragma hdrstop // // Location in registry where per-system MRU list is stored // (relative to HKEY_LOCAL_MACHINE). // PCTSTR pszPerSystemKey = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup"); PCTSTR pszPerSystemVal = TEXT("Installation Sources"); // // Location in registry where per-user MRU list is stored. // (relative to HKEY_CURRENT_USER). // PCTSTR pszPerUserKey = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup"); PCTSTR pszPerUserVal = TEXT("Installation Sources"); typedef PTSTR *APTSTR; // // Platform strings we recognize. // PCTSTR PlatformPathComponents[] = { TEXT("\\alpha"), TEXT("\\nec98"), //NEC98 TEXT("\\i386"), TEXT("\\x86"), TEXT("\\mips"), TEXT("\\ppc"), TEXT("\\axp64"), TEXT("\\ia64"), NULL }; // // These are guarded by MruCritSect. // PTSTR *TemporarySourceList; UINT TemporarySourceCount; BOOL MruNoBrowse; VOID pSetupStripTrailingPlatformComponent( IN OUT PTSTR *Paths, IN OUT PDWORD NumPaths ); BOOL LockMruCritSect() { BOOL locked = FALSE; try { EnterCriticalSection(&MruCritSect); locked = TRUE; } except (EXCEPTION_EXECUTE_HANDLER) { } if(!locked) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); } return locked; } BOOL _SetupSetSourceList( IN DWORD Flags, IN PCTSTR *SourceList, IN UINT SourceCount ) /*++ Routine Description: This routine allows the caller to set the list of installation sources for either the current user or the system (common to all users). Arguments: Flags - a combination of the following values: SRCLIST_SYSTEM - specify that the list is to become the per-system list. The caller must be administrator. SRCLIST_USER - specify that the list is to become the per-user list. SRCLIST_TEMPORARY - specify that the list is to become the entire list for the duration of the current process, or until this routine is called again to change the behavior. Exactly one of SRCLIST_SYSTEM, SRCLIST_USER, and SRCLIST_TEMPORARY must be specified. SRCLIST_NOBROWSE - specify that the user is not allowed to add or change sources when the SetupPromptForDisk API is used. Typically used in combination with SRCLIST_TEMPORARY. SourceList - supplies array of strings that are to become the source list, as described by the Flags parameter. SourceCount - specifies number of elements in the SourceList array. Return Value: --*/ { DWORD flags; DWORD d; UINT u,v; // // Check flags. Only one of system, user, or temporary may be set. // flags = Flags & (SRCLIST_SYSTEM | SRCLIST_USER | SRCLIST_TEMPORARY); if((flags != SRCLIST_SYSTEM) && (flags != SRCLIST_USER) && (flags != SRCLIST_TEMPORARY)) { SetLastError(ERROR_INVALID_PARAMETER); return(FALSE); } // // User must be admin for system flag to work. // if((flags == SRCLIST_SYSTEM) && !pSetupIsUserAdmin()) { SetLastError(ERROR_ACCESS_DENIED); return(FALSE); } // // Only allow one thread at a time in this process to access // the temporary source list. // if(!LockMruCritSect()) { return FALSE; } if(Flags & SRCLIST_NOBROWSE) { MruNoBrowse = TRUE; } d = NO_ERROR; if(flags == SRCLIST_TEMPORARY) { if(TemporarySourceList) { SetupFreeSourceList(&TemporarySourceList,TemporarySourceCount); } // // Duplicate the list the caller passed in. // if(TemporarySourceList = MyMalloc(SourceCount * sizeof(PTSTR))) { TemporarySourceCount = SourceCount; for(u=0; uInfSourcePath) { InfSourcePath = DuplicateString(((PLOADED_INF)InfHandle)->InfSourcePath); if(!InfSourcePath) { Err = ERROR_NOT_ENOUGH_MEMORY; goto clean0; } } *InfSourceMediaType = ((PLOADED_INF)InfHandle)->InfSourceMediaType; if(Flags & SRCPATH_USEINFLOCATION) { // // Caller has requested that we default to the INF's source // location when there's no SPOST_PATH info. // if(*InfSourceMediaType != SPOST_PATH) { if(InfSourcePath) { MyFree(InfSourcePath); InfSourcePath = NULL; } *InfSourceMediaType = SPOST_PATH; } if(!InfSourcePath) { // // Don't have an INF source path--use the INF's present // location. // InfSourcePath = DuplicateString(((PLOADED_INF)InfHandle)->VersionBlock.Filename); if(InfSourcePath) { // // OK, we duplicated the INF's full pathname, now // truncate it to just the path part. // p = (PTSTR)pSetupGetFileTitle(InfSourcePath); *p = TEXT('\0'); if(((p - InfSourcePath) != 3) || lstrcmp(CharNext(InfSourcePath), TEXT(":\\"))) { // // The path is not an "A:\" type path, so truncate // p = CharPrev(InfSourcePath, p); MYASSERT(*p == TEXT('\\')); if(p > InfSourcePath) { *p = TEXT('\0'); } } } else { Err = ERROR_NOT_ENOUGH_MEMORY; goto clean0; } } } clean0: ; // nothing to do. } except(EXCEPTION_EXECUTE_HANDLER) { if(InfSourcePath) { MyFree(InfSourcePath); InfSourcePath = NULL; } Err = ERROR_INVALID_PARAMETER; } UnlockInf((PLOADED_INF)InfHandle); } if((Flags & SRCPATH_USEINFLOCATION) && !InfSourcePath) { // // We either hit out of memory or an exception--make sure media type // specifies SPOST_PATH before returning failure. // *InfSourceMediaType = SPOST_PATH; MYASSERT(Err != NO_ERROR); SetLastError(Err); return NULL; } if(!InfSourcePath && (*InfSourceMediaType == SPOST_PATH) && (Flags & SRCPATH_USEPNFINFORMATION)) { // // There's not an oem location associated with this INF, so use our default // source path. // InfSourcePath = DuplicateString(SystemSourcePath); if(!InfSourcePath) { Err = ERROR_NOT_ENOUGH_MEMORY; } } SetLastError(Err); return InfSourcePath; } VOID pSetupStripTrailingPlatformComponent( IN OUT PTSTR *Paths, IN OUT PDWORD NumPaths ) { PTSTR Path; DWORD PathCount; DWORD NewPathCount; DWORD PathIndex; DWORD DupIndex; DWORD FirstIndex; DWORD HoleCount; PCTSTR Component; UINT ComponentLength; UINT PathLength; int ComponentOffset; UINT ComponentIndex; // // Do this for all paths in the array passed in by the caller. // PathCount = *NumPaths; for(PathIndex=0; PathIndex 0) && (lstrcmpi(Path+ComponentOffset,Component)==0)) { // // Got a match. Strip off the final component. // Leave a trailing backslash if we're dealing with the root. // Path[ComponentOffset] = TEXT('\0'); if((Path[1] == TEXT(':')) && !Path[2]) { Path[2] = TEXT('\\'); Path[3] = 0; } // // Remove duplicate, preserving the first instance // for(FirstIndex=0 ; FirstIndex