diff options
Diffstat (limited to 'private/windows/prsinf')
-rw-r--r-- | private/windows/prsinf/makefile | 6 | ||||
-rw-r--r-- | private/windows/prsinf/prsinf.c | 953 | ||||
-rw-r--r-- | private/windows/prsinf/prsinf.h | 347 | ||||
-rw-r--r-- | private/windows/prsinf/sources | 43 | ||||
-rw-r--r-- | private/windows/prsinf/spinf.c | 1760 | ||||
-rw-r--r-- | private/windows/prsinf/spinf.h | 104 | ||||
-rw-r--r-- | private/windows/prsinf/test.c | 125 |
7 files changed, 3338 insertions, 0 deletions
diff --git a/private/windows/prsinf/makefile b/private/windows/prsinf/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/windows/prsinf/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/windows/prsinf/prsinf.c b/private/windows/prsinf/prsinf.c new file mode 100644 index 000000000..5dfe1ad03 --- /dev/null +++ b/private/windows/prsinf/prsinf.c @@ -0,0 +1,953 @@ + +// +// changes some definitions in spinf +// + +#include <windows.h> +#include <string.h> +#include "prsinf.h" +#include "spinf.h" +#include <stdio.h> + +#define CBMAXSECTION 256 +#define SZLANGSECTION "OptionsText" + +// +// BUGBUG I don't know what is supposed to happen with this. +// +#define DWLANGMAX 4 +PCHAR rgszLangs[DWLANGMAX] = {"ENG", "GER", "FREN", "SPAN"}; + +#define ENGLISH 0 +#define GERMAN 1 +#define FRENCH 2 +#define SPANISH 3 + +PCHAR GetKeyOrValue( HANDLE, PCHAR, ULONG ); + +// +// Device Type to INF filename mapping in the system directory +// + +typedef struct _DeviceTypeToInf { + PCHAR szDeviceType; + PCHAR szSystemInf; + PCHAR szOemInfPrefix; + } DEVICETYPETOINF, *pDEVICETYPETOINF; + +DEVICETYPETOINF DeviceTypeToInfList[] = { + { "Computer" , "COMPUTER.INF" , "OEMCPT" }, + { "Video" , "VIDEO.INF" , "OEMVIO" }, + { "Pointer" , "POINTER.INF" , "OEMPTR" }, + { "Keyboard" , "KEYBOARD.INF" , "OEMKBD" }, + { "Layout" , "LAYOUT.INF" , "OEMLAY" }, + { "Language" , "LANGUAGE.INF" , "OEMLNG" }, + { "Printer" , "PRINTER.INF" , "OEMPRN" }, + { "Scsi" , "SCSI.INF" , "OEMSCS" }, + { "Tape" , "TAPE.INF" , "OEMTAP" }, + { "Sound" , "SOUND.INF" , "OEMSND" }, + { "Driver" , "DRIVER.INF" , "OEMDRV" }, + { NULL , NULL , NULL } + }; + +BOOLEAN +GetFullInfName( + + IN PCHAR szInfName, + IN ULONG cb, + OUT PCHAR pszFullInfName + ) + +/*++ + +Routine Description: + + This routine takes non-qualified inf file name and inserts + the directory where inf files are kept in front. + +Arguments: + + + szInfName - Unqualified inf file name + cb - number of bytes in Full Inf name buffer + pszFullInfName - Pointer to buffer to hold name + +Return Value: + + True of name could fit and there is a location for inf files + +--*/ + +{ + ULONG cbFullName; + + // + // Currently all inf's are stored in system directory + // + cbFullName = GetSystemDirectory(pszFullInfName, cb); + if (cbFullName == 0) { + + return( FALSE ); + } + + if ((cbFullName + strlen( szInfName) + 0) > cb) { + + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return( FALSE ); + } + strcat(pszFullInfName, szInfName); + return( TRUE ); + +} + +PCHAR +GetInfFileList ( ) + +/*++ + +Routine Description: + + Locates all OEM INF files in the system directory. + + This function fills a string buffer with a double 0 terminated + list of filenames. Each filename in the buffer is separated from + the next by a single 0 termination char. Each filename is relative + to the directory where OEM inf files are stored. + +Arguments: + + szInfType - String to match in Identification section. + +Return Value: + + A NULL is returned on error or no files found. Use GetLastError to + determine exact error. + + NOTE: The returned buffer is allocated with LocalAlloc. It MUST be + freed with LocalFree by the caller. + +--*/ + +{ + + PCHAR psz, pszT; + ULONG obBuff, cbBuffMax; + ULONG cbPath; + HANDLE hndFind; + CHAR szSearchPath[MAX_PATH]; + WIN32_FIND_DATA ffd; + + // + // Fully Qualify the file masm first. + // + if (!GetFullInfName( "\\*.inf",MAX_PATH, szSearchPath)) { + + return( NULL ); + } + + hndFind = FindFirstFile(szSearchPath, &ffd); + if (hndFind == BADHANDLE) { + + return( NULL ); + + } + + // + // Use an initial guess to start out buffer + // + cbBuffMax = 12 * MAX_PATH; + if ((psz = LocalAlloc(LPTR, cbBuffMax)) == NULL) { + + return( NULL ); + + } + + strcpy(psz, ffd.cFileName); + obBuff = strlen(psz) + 1; + // + // Locate all inf files and see if they are of the correct type. + // + // + while ( FindNextFile(hndFind, &ffd) ) { + + cbPath = strlen( ffd.cFileName ); + // + // compute spaced needed plus 2 for string and buffer terminatation + // + if (cbBuffMax <= (cbPath + obBuff + 2)) { + + cbBuffMax += cbPath + MAX_PATH; + pszT = LocalReAlloc(psz, cbBuffMax, LMEM_ZEROINIT | LMEM_MOVEABLE); + if (pszT == NULL) { + + LocalFree( psz ); + return( NULL ); + + } + + psz = pszT; + + } + + strcpy(psz + obBuff, ffd.cFileName); + obBuff += cbPath + 1; + } + + // + // Terminate buffer + // + psz[obBuff] = 0; + + // + // realloc down to exact size. plus buffer for terminator + // + LocalReAlloc(psz, obBuff + 1, LMEM_ZEROINIT); + return( psz ); +} + +HANDLE +OpenInfFile ( + + IN PCHAR szFileName, + IN PCHAR szInfType + ) + +/*++ + +Routine Description: + + Opens an INF file of the specified type and returns an open handle + to it. + + szInfType should match the string in the OptionType value in the + Identification section of the INF file. + + if szFileName is a simple filename with no path information the directory + where all OEM files are kept is prepended. If szFileName contains any + path information it should contain a full path. + +Arguments: + + szFileName - File name to locate. + szInfType - String to match in Identification section. + +Return Value: + + Returns a Bad handle (-1) if szInfType does not match or the file could + not be opened. + +--*/ + +{ + + CHAR szPath[MAX_PATH]; + PCHAR szTypeCur; + ULONG cbPath; + HANDLE hndInf; + + + // + // Check to see if file name has any path characters. + // If not then get the standard location for all OEM + // files. If it does then assume a full path name. + // + szPath[0] = 0; + cbPath = 0; + + if (!strpbrk( szFileName, "\\:") ) { + + // + // This can only fail if buffer too small, but a path cannot + // be greater then MAX_PATH. + // + cbPath = GetSystemDirectory(szPath, MAX_PATH); + strcat(szPath, "\\"); + } + + if ((cbPath + strlen(szFileName)) < MAX_PATH - 2) { + + strcat(szPath, szFileName); + + } else { + + SetLastError( ERROR_INVALID_PARAMETER ); + return( BADHANDLE ); + } + // + // Open the file, load and parse it + // + hndInf = SpInitINFBuffer(szPath); + if (hndInf == BADHANDLE) { + + return( BADHANDLE); + + } + + // + // [Identification] + // OptionType = <option text> (i.e. match szTypeCur) + // + szTypeCur = SpGetSectionKeyIndex(hndInf,"Identification","OptionType", 0); + + if (szTypeCur == NULL) { + + // + // Could not find Identification section + // + CloseInfFile( hndInf ); + SetLastError( ERROR_INF_TYPE_MISMATCH ); + return( BADHANDLE ); + + } + + if (_strcmpi(szTypeCur, szInfType)) { + + // + // File is not correct type + // + // LocalFree( szTypeCur ); + CloseInfFile( hndInf ); + SetLastError( ERROR_INF_TYPE_MISMATCH ); + return( BADHANDLE ); + + } + + + // LocalFree( szTypeCur ); + return(hndInf); + +} + + + +VOID +CloseInfFile ( + + IN HANDLE hInf + ) + +/*++ + +Routine Description: + + Free Resources + +Arguments: + + hInf - Handle to OEM INF file. + +Return Value: + +--*/ + +{ + + SpFreeINFBuffer( hInf ); + + +} + +PCHAR +GetTokenElementList ( + + IN HANDLE hndInf, + IN PCHAR szSectionName, + IN PCHAR szKey + ) +/*++ + +Routine Description: + + This routine returns a buffer of tokens seperated by comma + found in the specificied section with the specified key. + +Arguments: + + +Return Value: + + *psz - Pointer to array of elements + +--*/ + +{ + ULONG irgsz; + PCHAR psz; + PCHAR szTokenCur; + ULONG obBuff, cbBuffMax; + ULONG cbToken; + + + if (!SpGetSectionKeyExists(hndInf, szSectionName, szKey)) { + + SetLastError(ERROR_SECTION_NOT_FOUND); + return( NULL ); + + } + + // + // Allocate space to hold elements from the inf file + // Use an initial guess of 256 to start out buffer + // + cbBuffMax = 256; + obBuff = 0; + if ((psz = LocalAlloc(LPTR, cbBuffMax)) == NULL) { + + return( NULL ); + + } + + // + // Loop through inf key value reading in elements + // Stop when run out of lines. + // + for (irgsz = 0; + szTokenCur = SpGetSectionKeyIndex(hndInf, szSectionName, szKey, irgsz); + irgsz++) { + + cbToken = strlen( szTokenCur ); + if (cbBuffMax <= (cbToken + obBuff + 2)) { + + cbBuffMax += cbToken + 256; + psz = LocalReAlloc(psz, cbBuffMax ,LMEM_ZEROINIT | LMEM_MOVEABLE); + if (psz == NULL) { + + LocalFree( psz ); + // LocalFree(szTokenCur); + return( NULL ); + + } + } + + strcpy(psz + obBuff, szTokenCur); + obBuff += cbToken ; + psz[obBuff++] = ','; + // LocalFree(szTokenCur); + + } + + // + // realloc down to exact size plus buffer terminator + // + LocalReAlloc(psz, obBuff + 1, LMEM_ZEROINIT); + // + // remove the comma for the last element and terminate buffer + // + psz[--obBuff] = 0; + psz[obBuff] = 0; + + return( psz ); + +} + + +PCHAR +GetSectionElementList ( + + IN HANDLE hndInf, + IN PCHAR szSectionName + ) +/*++ + +Routine Description: + + This routine build buffer of zero terminated strings out of the elements + in the specified section of the specified inf file. + +Arguments: + + hndInf - Path to OS NAMES file. + szSectionName - Section name for to search. + idxElement - index within a line to element + +Return Value: + + *psz - Pointer to array of elements + +--*/ + +{ + ULONG irgsz; + PCHAR psz; + PCHAR szElementCur; + ULONG obBuff, cbBuffMax; + ULONG cbElement; + + + if (!SpSearchINFSection(hndInf, szSectionName)) { + + SetLastError( ERROR_SECTION_NOT_FOUND ); + return( NULL ); + + } + + // + // Allocate space to hold elements from the inf file + // Use an initial guess of 256 to start out buffer + // + cbBuffMax = 256; + obBuff = 0; + if ((psz = LocalAlloc(LPTR, cbBuffMax)) == NULL) { + + return( NULL ); + + } + + // + // Loop through inf section reading in elements + // Stop when run out of lines. + // + + for (irgsz = 0; + szElementCur = GetKeyOrValue(hndInf, szSectionName, irgsz); + irgsz++ ) { + + cbElement = strlen( szElementCur ); + if (cbBuffMax <= (cbElement + obBuff + 2)) { + + cbBuffMax += cbElement + 256; + psz = LocalReAlloc(psz, cbBuffMax ,LMEM_ZEROINIT | LMEM_MOVEABLE); + if (psz == NULL) { + + LocalFree( psz ); + // LocalFree(szElementCur); + return( NULL ); + + } + } + + strcpy(psz + obBuff, szElementCur); + obBuff += cbElement + 1; + // LocalFree(szElementCur); + + } + + // + // realloc down to exact size plus buffer terminator + // + LocalReAlloc(psz, obBuff + 1, LMEM_ZEROINIT); + + // + // Terminate entire buffer + // + psz[obBuff] = 0; + return( psz ); + +} + +PCHAR +GetKeyOrValue( + + IN HANDLE hndInf, + IN PCHAR szSectionName, + IN ULONG idxLine + ) + +{ + + PCHAR szElementCur; + + szElementCur = SpGetKeyName(hndInf, szSectionName, idxLine); + if (szElementCur == NULL) { + + szElementCur = SpGetSectionLineIndex(hndInf, + szSectionName, + idxLine, + 0); + + } + + return( szElementCur ); + +} + +PCHAR +GetOptionList ( + + IN HANDLE hndInf, + IN PCHAR szOptionSection + + ) + +/*++ + +Routine Description: + + This function fills a string buffer with a double 0 terminated + list of options from the specified options section. Each option + in the buffer is separated from the next option by a single 0 + termination char. CharNext() and CharPrev() apis should be used + to move thru the buffer. + + A NULL szOptionSection will use the default option section name. + +Arguments: + + hndInf - Handle to open INF file + szOptionSection - section name containing options + +Return Value: + + A NULL is returned on failure to allocate. A pointer to an empty + buffer (buffer with 2 0's) is returned for empty option list. + + HANDLE is allocated as fixed memory and can be referenced directory after + a cast. The buffer should be freed with LocalFree + + Error return codes returned GetLastError() + + ERROR_INVALID_PARAMETER + ERROR_NOT_ENOUGH_MEMORY + ERROR_FILE_NOT_FOUND + + +--*/ + +{ + + return( GetSectionElementList(hndInf,szOptionSection) ); + +} + + +PCHAR +GetOptionText ( + + HANDLE hndInf, + PCHAR szOption, + DWORD dwLang + + ) + +/*++ + +Routine Description: + + Returns the UserInterface display string associated with + the option in the desired language. + + Every INF file will have at least one language for option + text display. If the desired language is not present then + the first listed language text should be returned. + + If the option does not exist or the language does not exist then a + pointer to a NULL is returned. + + dwLang should be one of the already defined NLS values + +Arguments: + + hInf - Handle to open INF file + szOption - Option to match + language - Language to match + +Return Value: + + A NULL is returned on failure to allocate. A pointer to an empty + buffer (buffer with 2 0's) is returned for empty option list. + + PCHAR is allocated as fixed memory and can be referenced directory after + a cast. The buffer should be freed with LocalFree + + Error return codes returned GetLastError() + + ERROR_INVALID_PARAMETER + ERROR_NOT_ENOUGH_MEMORY + +--*/ + +{ + + CHAR szLangSection[CBMAXSECTION]; + PCHAR pszOptionText; + + if (dwLang >= DWLANGMAX) { + SetLastError( ERROR_INVALID_PARAMETER ); + return( NULL ); + + } + + strcpy( szLangSection, SZLANGSECTION ); + strcat(szLangSection, rgszLangs[dwLang]); + pszOptionText = GetTokenElementList(hndInf, szLangSection, szOption); + return( pszOptionText ); +} + + +PCHAR +GetAllOptionsText( + IN PCHAR szInfType, + IN DWORD dwLang + ) + +/*++ + +Routine Description: + + Fills the string buffer szBuffer with a set of triplets + consisting of File Name, Option, Option Text. All 0 terminated + with a double 0 termination for buffer. This used where infType + is to span multiple inf files. + + dwLang should be one of the already defined NLS values + +Arguments: + + szInfFile - Identificaton section to match + szLang - Language to match + +Return Value: + + A NULL is returned on failure to allocate. A pointer to an empty + buffer (buffer with 2 0's) is returned for empty option list. + + PCHAR is allocated as fixed memory and can be referenced directory after + a cast. The buffer should be freed with LocalFree + + Error return codes returned GetLastError() + + ERROR_INVALID_PARAMETER + ERROR_NOT_ENOUGH_MEMORY + + +--*/ + +{ + + + HANDLE hndInf; + PCHAR pszOptions, pszOptionsOrg; + PCHAR pszOptionText; + PCHAR pszFiles, pszFilesOrg; + PCHAR pszBuff; + ULONG cbBuff, cbBuffMax; + ULONG obBuff; + + pDEVICETYPETOINF pDeviceTypeToInf = DeviceTypeToInfList; + PCHAR szSystemInf = NULL; + PCHAR szOemInfPrefix = NULL; + ULONG cbOemInfPrefix = 0; + + // + // Get the list of all infs in the system directory + // + + pszFilesOrg = pszFiles = GetInfFileList( ); + if (pszFiles == NULL) { + + return( NULL ); + + } + + // + // Find out the infs we will look for in this list + // + while( pDeviceTypeToInf->szDeviceType != NULL ) { + if( !_strcmpi(pDeviceTypeToInf->szDeviceType, szInfType)) { + szSystemInf = pDeviceTypeToInf->szSystemInf; + szOemInfPrefix = pDeviceTypeToInf->szOemInfPrefix; + cbOemInfPrefix = lstrlen( szOemInfPrefix ); + break; + } + pDeviceTypeToInf++; + } + + if( szSystemInf == NULL || szOemInfPrefix == NULL ) { + return( NULL ); + } + + // + // Allocate space to hold elements from the inf file + // Use an initial guess to start out buffer + // + cbBuffMax = 1024; + obBuff = 0; + if ((pszBuff = LocalAlloc(LPTR, cbBuffMax)) == NULL) { + + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + LocalFree( pszFiles ); + return( NULL ); + + } + + // + // Loop through the inf files looking for one that + // matches the szInfType. Once found fetch the correct + // text section based upon language id. + // + for( ; *pszFiles; pszFiles += strlen(pszFiles) + 1) { + + if ( _strcmpi(pszFiles, szSystemInf) && + _strnicmp(pszFiles, szOemInfPrefix, cbOemInfPrefix)) { + + continue; + } + + hndInf = OpenInfFile( pszFiles, szInfType ); + + if (hndInf == BADHANDLE) { + + // + // Check if the problem was just the wrong type of + // inf file. + // + if (GetLastError() != ERROR_INF_TYPE_MISMATCH) { + + return( NULL ); + + } else { + + continue; + + } + + } + + // + // Get the list of options and fetch the correct text + // + pszOptionsOrg = pszOptions = GetOptionList(hndInf, "OPTIONS"); + if (pszOptions == NULL) { + + CloseInfFile( hndInf ); + LocalFree( pszFilesOrg ); + return( NULL ); + + } + + while (*pszOptions) { + + pszOptionText = GetOptionText(hndInf, pszOptions, dwLang); + if (pszOptionText == NULL) { + + CloseInfFile( hndInf ); + LocalFree( pszFilesOrg ); + LocalFree( pszOptionsOrg ); + return( NULL ); + } + + // + // Compute buffer size and add in enough 0's and 1 for termination + // + cbBuff = strlen(pszOptions) + strlen(pszOptionText) + strlen(pszFiles); + + if (cbBuffMax <= (cbBuff + obBuff + 4)) { + + cbBuffMax += cbBuff + 1024; + pszBuff = LocalReAlloc(pszBuff, cbBuffMax ,LMEM_ZEROINIT | LMEM_MOVEABLE); + if (pszBuff == NULL) { + + LocalFree( pszBuff ); + CloseInfFile( hndInf ); + LocalFree( pszFilesOrg ); + LocalFree( pszOptionsOrg ); + return( NULL ); + + } + } + + strcpy(pszBuff + obBuff, pszOptions); + obBuff += strlen(pszOptions) + 1; + strcpy(pszBuff + obBuff, pszOptionText); + obBuff += strlen(pszOptionText) + 1; + strcpy(pszBuff + obBuff, pszFiles); + obBuff += strlen(pszFiles) + 1; + + // LocalFree( pszOptionText ); + pszOptions += strlen(pszOptions) + 1; + + } + + LocalFree( pszOptionsOrg ); + + CloseInfFile( hndInf ); + // + // terminate entire buffer + // + pszBuff[obBuff] = 0; + } + + LocalFree( pszFilesOrg ); + + // + // realloc down to exact size. plus buffer terminator + // + LocalReAlloc(pszBuff, obBuff + 1, LMEM_ZEROINIT); + + return( pszBuff ); + +} + +#if 0 +BOOLEAN +GetOemInfFile ( + + IN PCHAR szInfType + + ) + +/*++ + +Routine Description: + + Prompts user to provide a path to or insert a disk with new + options. This routine reads and copies the .INF file to + the local system directory using whatever naming convention + we think up. + +Arguments: + + szInfType - Identification to match + +Return Value: + + Returns TRUE if new .INF file chosen by user has options of + type szInfType. + +--*/ + +{ + UNREFERENCED_PARAMETER( szInfType ); + + return( FALSE ); + +} + + +BOOLEAN +InstallInfOption ( + + IN PCHAR szInfFile, + IN PCHAR szOption, + IN PCHAR szAction + ) + +/*++ + +Routine Description: + + Invokes SETUP with proper set of command line arguments, waits for + process completion and returns status to calling application. + +Arguments: + + szInfType - Identification to match + szOption - Option to Install. + szAction - Section to execute (usually this is "Install") + +Return Value: + + Returns TRUE on successful option installation, FALSE otherwise. + +--*/ + + +{ + UNREFERENCED_PARAMETER( szInfFile ); + UNREFERENCED_PARAMETER( szOption ); + UNREFERENCED_PARAMETER( szAction ); + return( FALSE ); + +} + +#endif diff --git a/private/windows/prsinf/prsinf.h b/private/windows/prsinf/prsinf.h new file mode 100644 index 000000000..92fce6ab8 --- /dev/null +++ b/private/windows/prsinf/prsinf.h @@ -0,0 +1,347 @@ +typedef ULONG ARC_STATUS; +#define BADHANDLE (HANDLE)-1 + +// +// Define Error codes +// +#define ERROR_PRSINF_FIRST 0xFF00 +#define ERROR_INF_TYPE_MISMATCH ERROR_PRSINF_FIRST + 0 +#define ERROR_EXPECTED_LBRACE ERROR_PRSINF_FIRST + 1 +#define ERROR_EXPECTED_STRING ERROR_PRSINF_FIRST + 2 +#define ERROR_EXPECTED_RBRACE ERROR_PRSINF_FIRST + 3 +#define ERROR_EXPECTED_EOL ERROR_PRSINF_FIRST + 4 +#define ERROR_EXPECTED_SECTION_LINE ERROR_PRSINF_FIRST + 5 +#define ERROR_EXPECTED_BAD_LINE ERROR_PRSINF_FIRST + 6 +#define ERROR_EXPECTED_COMMA_ANOTHER_STRING ERROR_PRSINF_FIRST + 7 +#define ERROR_EXPECTED_EQUAL_ANOTHER_STRING ERROR_PRSINF_FIRST + 8 +#define ERROR_EXPECTED_EQUAL_STRING_COMMA ERROR_PRSINF_FIRST + 9 +#define ERROR_EXPECTED_EQUAL_VALUE_RECIEVED ERROR_PRSINF_FIRST + 10 +#define ERROR_BAD_ID_SECTION ERROR_PRSINF_FIRST + 11 +#define ERROR_UNKOWN_STATE ERROR_PRSINF_FIRST + 12 +#define ERROR_SECTION_NOT_FOUND ERROR_PRSINF_FIRST + 13 + +/* + + This module support access to a subset of the GUI Toolkit INF + file language. The intent of the module is to return the list of + options, options text and associated file names for OEM inf files + of a particular type. + + The OEM INF file must have the following sections in the following + format. (items within <> are optional or change with the INF file, + they are not part of the + + [Identification] + + OptionType = <option type desired> + + [OPTIONS] + + <option1> + <option2> + ... + + [OptionText<lang>] + + <option1> = <"option1 text"> + <option2> = <"option2 text"> + + +*/ + + +BOOLEAN +GetFullInfName( + IN PCHAR szInfName, + IN ULONG cb, + IN PCHAR pszFullInfName + ); + +/*++ + +Routine Description: + + This routine takes non-qualified inf file name and inserts + the directory where inf files are kept in front. + +Arguments: + + + szInfName - Unqualified inf file name + cb - number of bytes in Full Inf name buffer + pszFullInfName - Pointer to buffer to hold name + +Return Value: + + True of name could fit and there is a location for inf files + +--*/ + + +PCHAR +GetInfFileList ( ); + +/*++ + +Routine Description: + + Locates all OEM INF files in the system directory. + + This function fills a string buffer with a double 0 terminated + list of filenames. Each filename in the buffer is separated from + the next by a single 0 termination char. Each filename is relative + to the directory where OEM inf files are stored. + +Arguments: + + szInfType - String to match in Identification section. + +Return Value: + + A NULL is returned on error or no files found. Use GetLastError to + determine exact error. + + NOTE: The returned buffer is allocated with LocalAlloc. It MUST be + freed with LocalFree by the caller. + +--*/ + + +HANDLE +OpenInfFile ( + + IN PCHAR szFileName, + IN PCHAR szInfType + ); + +/*++ + +Routine Description: + + Opens an INF file of the specified type and returns an open handle + to it. + + szInfType should match the string in the OptionType value in the + Identification section of the INF file. + + if szFileName is a simple filename with no path information the directory + where all OEM files are kept is prepended. If szFileName contains any + path information it should contain a full path. + +Arguments: + + szFileName - File name to locate. + szInfType - String to match in Identification section. + +Return Value: + + Returns a Bad handle (-1) if szInfType does not match or the file could + not be opened. + +--*/ + + + + +VOID +CloseInfFile ( + + IN HANDLE hInf + ); + +/*++ + +Routine Description: + + Free Resources + +Arguments: + + hInf - Handle to OEM INF file. + +Return Value: + +--*/ + + +PCHAR +GetTokenElementList ( + + IN HANDLE hndInf, + IN PCHAR szSectionName, + IN PCHAR szKey + ); +/*++ + +Routine Description: + + This routine returns a buffer of tokens seperated by comma + found in the specificied section with the specified key. + +Arguments: + + +Return Value: + + *psz - Pointer to array of elements + +--*/ + + + + +PCHAR +GetSectionElementList ( + + IN HANDLE hndInf, + IN PCHAR szSectionName + ); +/*++ + +Routine Description: + + This routine build buffer of zero terminated strings out of the elements + in the specified section of the specified inf file. + +Arguments: + + hndInf - Path to OS NAMES file. + szSectionName - Section name for to search. + idxElement - index within a line to element + +Return Value: + + *psz - Pointer to array of elements + +--*/ + + +PCHAR +GetOptionList ( + + IN HANDLE hndInf, + IN PCHAR szOptionSection + + ); + +/*++ + +Routine Description: + + This function fills a string buffer with a double 0 terminated + list of options from the specified options section. Each option + in the buffer is separated from the next option by a single 0 + termination char. CharNext() and CharPrev() apis should be used + to move thru the buffer. + + A NULL szOptionSection will use the default option section name. + +Arguments: + + hndInf - Handle to open INF file + szOptionSection - section name containing options + +Return Value: + + A NULL is returned on failure to allocate. A pointer to an empty + buffer (buffer with 2 0's) is returned for empty option list. + + HANDLE is allocated as fixed memory and can be referenced directory after + a cast. The buffer should be freed with LocalFree + + Error return codes returned GetLastError() + + ERROR_INVALID_PARAMETER + ERROR_NOT_ENOUGH_MEMORY + ERROR_FILE_NOT_FOUND + + +--*/ + + + + +PCHAR +GetOptionText ( + + HANDLE hndInf, + PCHAR szOption, + DWORD dwLang + + ); + +/*++ + +Routine Description: + + Returns the UserInterface display string associated with + the option in the desired language. + + Every INF file will have at least one language for option + text display. If the desired language is not present then + the first listed language text should be returned. + + If the option does not exist or the language does not exist then a + pointer to a NULL is returned. + + dwLang should be one of the already defined NLS values + +Arguments: + + hInf - Handle to open INF file + szOption - Option to match + language - Language to match + +Return Value: + + A NULL is returned on failure to allocate. A pointer to an empty + buffer (buffer with 2 0's) is returned for empty option list. + + PCHAR is allocated as fixed memory and can be referenced directory after + a cast. The buffer should be freed with LocalFree + + Error return codes returned GetLastError() + + ERROR_INVALID_PARAMETER + ERROR_NOT_ENOUGH_MEMORY + +--*/ + + +PCHAR +GetAllOptionsText( + IN PCHAR szInfType, + IN DWORD dwLang + ); + +/*++ + +Routine Description: + + Fills the string buffer szBuffer with a set of triplets + consisting of Option, Option Text. File Name. All 0 terminated + with a double 0 termination for buffer. This used where infType + is to span multiple inf files. + + dwLang should be one of the already defined NLS values + +Arguments: + + szInfFile - Identificaton section to match + szLang - Language to match + +Return Value: + + A NULL is returned on failure to allocate. A pointer to an empty + buffer (buffer with 2 0's) is returned for empty option list. + + PCHAR is allocated as fixed memory and can be referenced directory after + a cast. The buffer should be freed with LocalFree + + Error return codes returned GetLastError() + + ERROR_INVALID_PARAMETER + ERROR_NOT_ENOUGH_MEMORY + + +--*/ diff --git a/private/windows/prsinf/sources b/private/windows/prsinf/sources new file mode 100644 index 000000000..20f3e261b --- /dev/null +++ b/private/windows/prsinf/sources @@ -0,0 +1,43 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=windows +MINORCOMP=prsinf + +NTPROFILEINPUT=yes + + +TARGETNAME=prsinf +TARGETPATH=obj +TARGETTYPE=LIBRARY + +INCLUDES=..\inc; + +SOURCES=prsinf.c \ + spinf.c \ + test.c + +UMTYPE=console +UMTEST=test +UMLIBS=obj\*\prsinf.lib diff --git a/private/windows/prsinf/spinf.c b/private/windows/prsinf/spinf.c new file mode 100644 index 000000000..bed58562d --- /dev/null +++ b/private/windows/prsinf/spinf.c @@ -0,0 +1,1760 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + alinf.c + +Abstract: + + This module implements functions to _access the parsed INF. + +Author: + + Sunil Pai (sunilp) 13-Nov-1991 + +Revision History: + +--*/ + +// +// changes some definitions in spinf +// + +#define _CTYPE_DISABLE_MACROS +#include <windows.h> +#include "prsinf.h" +#include "spinf.h" +#include <stdio.h> + +#define SpFree(x) LocalFree(x);(x)=NULL +#define SpMalloc(x) LocalAlloc(LPTR,x) +#define SetMemoryError() GetLastError() +#define SpSetLastError( x ) SetLastError( x ) + +// #define DEBUG 1 + +#include <string.h> +#include <ctype.h> + + + +// what follows was alpar.h + +// +// EXPORTED BY THE PARSER AND USED BY BOTH THE PARSER AND +// THE INF HANDLING COMPONENTS +// + +// typedefs exported +// + +typedef struct _value { + struct _value *pNext; + PCHAR pName; + } INFVALUE, *PINFVALUE; + +typedef struct _line { + struct _line *pNext; + PCHAR pName; + PINFVALUE pValue; + } LINE, *PLINE; + +typedef struct _section { + struct _section *pNext; + PCHAR pName; + PLINE pLine; + } SECTION, *PSECTION; + +typedef struct _inf { + PSECTION pSection; + } INF, *PINF; + +// +// Routines exported +// + +PVOID +ParseInfBuffer( + PCHAR Buffer, + ULONG Size + ); + + +// +// DEFINES USED FOR THE PARSER INTERNALLY +// +// +// typedefs used +// + +typedef enum _tokentype { + TOK_EOF, + TOK_EOL, + TOK_LBRACE, + TOK_RBRACE, + TOK_STRING, + TOK_EQUAL, + TOK_COMMA, + TOK_ERRPARSE, + TOK_ERRNOMEM + } TOKENTYPE, *PTOKENTTYPE; + + +typedef struct _token { + TOKENTYPE Type; + PCHAR pValue; + } TOKEN, *PTOKEN; + + +// +// Routine defines +// + +ARC_STATUS +SpAppendSection( + IN PCHAR pSectionName + ); + +ARC_STATUS +SpAppendLine( + IN PCHAR pLineKey + ); + +ARC_STATUS +SpAppendValue( + IN PCHAR pValueString + ); + +TOKEN +SpGetToken( + IN OUT PCHAR *Stream, + IN PCHAR MaxStream, + IN PCHAR pszStrTerms, + IN PCHAR pszQStrTerms, + IN PCHAR pszCBrStrTerms + ); + +BOOLEAN +IsStringTerminator( + IN CHAR ch, + IN PCHAR pszStrTerm + ); + +BOOLEAN +IsQStringTerminator( + IN CHAR ch, + IN PCHAR pszStrTerm + ); + +// what follows was alinf.c + +// +// Internal Routine Declarations for freeing inf structure members +// + +VOID +FreeSectionList ( + IN PSECTION pSection + ); + +VOID +FreeLineList ( + IN PLINE pLine + ); + +VOID +FreeValueList ( + IN PINFVALUE pValue + ); + + +// +// Internal Routine declarations for searching in the INF structures +// + + +PINFVALUE +SearchValueInLine( + IN PLINE pLine, + IN ULONG ValueIndex + ); + +PLINE +SearchLineInSectionByKey( + IN PSECTION pSection, + IN PCHAR Key + ); + +PLINE +SearchLineInSectionByIndex( + IN PSECTION pSection, + IN ULONG LineIndex + ); + +PSECTION +SearchSectionByName( + IN PINF pINF, + IN PCHAR SectionName + ); + +// +// ROUTINE DEFINITIONS +// + +// +// returns a handle to use for further inf parsing +// + +HANDLE +SpInitINFBuffer ( + IN PCHAR szInfFile + ) + +/*++ + +Routine Description: + + +Arguments: + + +Return Value: + + +--*/ + +{ + ARC_STATUS Status; + OFSTRUCT ofFile; + PCHAR szBuffer; + HANDLE hndFile; + HANDLE hndMappedFile; + ULONG cbFile; + HANDLE hndInf; + + + // + // Open the file + // + hndFile = (HANDLE)OpenFile( szInfFile, &ofFile, OF_READ ); + if (hndFile == BADHANDLE) { + + return( BADHANDLE ); + + } + + + // + // Map the file + // + hndMappedFile = CreateFileMapping( hndFile, NULL, PAGE_READONLY, 0, 0, NULL ); + if (hndMappedFile == BADHANDLE) { + + CloseHandle(hndFile); + return( BADHANDLE ); + } + szBuffer = MapViewOfFile( hndMappedFile, FILE_MAP_READ,0,0,0); + if (szBuffer == NULL) { + Status = GetLastError(); + CloseHandle(hndFile); + SpSetLastError(Status); + return( BADHANDLE ); + + } + + cbFile = GetFileSize(hndFile, NULL); + + // + // Get the size of the file + // + hndInf = (HANDLE) ParseInfBuffer(szBuffer, cbFile); + + // + // Clean up and return + // + CloseHandle(hndFile); + return( hndInf ); + +} + + +VOID +SpFreeINFBuffer ( + IN PVOID INFHandle + ) +{ + if(INFHandle) { + FreeSectionList(((PINF)INFHandle)->pSection); + SpFree(INFHandle); + } +} + + +VOID +FreeSectionList ( + IN PSECTION pSection + ) +{ + PSECTION pNext; + + while(pSection) { + + pNext = pSection->pNext; + + FreeLineList(pSection->pLine); + SpFree(pSection->pName); + SpFree(pSection); + + pSection = pNext; + } +} + + +VOID +FreeLineList ( + IN PLINE pLine + ) +{ + PLINE pNext; + + while(pLine) { + + pNext = pLine->pNext; + + FreeValueList(pLine->pValue); + if(pLine->pName) { + SpFree(pLine->pName); + } + SpFree(pLine); + + pLine = pNext; + } +} + +VOID +FreeValueList ( + IN PINFVALUE pValue + ) +{ + PINFVALUE pNext; + + while(pValue) { + + pNext = pValue->pNext; + + if(pValue->pName) { + SpFree(pValue->pName); + } + SpFree(pValue); + + pValue = pNext; + } +} + + +// +// searches for the existance of a particular section +// +BOOLEAN +SpSearchINFSection ( + IN PVOID INFHandle, + IN PCHAR SectionName + ) + +/*++ + +Routine Description: + + +Arguments: + + +Return Value: + + +--*/ + +{ + PSECTION pSection; + + // + // if search for section fails return false + // + + if ((pSection = SearchSectionByName( + (PINF)INFHandle, + SectionName + )) == (PSECTION)NULL) { + return( FALSE ); + } + + // + // else return true + // + return( TRUE ); + +} + + + + +// +// given section name, line number and index return the value. +// +PCHAR +SpGetSectionLineIndex ( + IN PVOID INFHandle, + IN PCHAR SectionName, + IN ULONG LineIndex, + IN ULONG ValueIndex + ) + +/*++ + +Routine Description: + + +Arguments: + + +Return Value: + + +--*/ + +{ + PSECTION pSection; + PLINE pLine; + PINFVALUE pValue; + + if((pSection = SearchSectionByName( + (PINF)INFHandle, + SectionName + )) + == (PSECTION)NULL) + return((PCHAR)NULL); + + if((pLine = SearchLineInSectionByIndex( + pSection, + LineIndex + )) + == (PLINE)NULL) + return((PCHAR)NULL); + + if((pValue = SearchValueInLine( + pLine, + ValueIndex + )) + == (PINFVALUE)NULL) + return((PCHAR)NULL); + + return (pValue->pName); + +} + + +BOOLEAN +SpGetSectionKeyExists ( + IN PVOID INFHandle, + IN PCHAR SectionName, + IN PCHAR Key + ) + +/*++ + +Routine Description: + + +Arguments: + + +Return Value: + + +--*/ + +{ + PSECTION pSection; + + if((pSection = SearchSectionByName( + (PINF)INFHandle, + SectionName + )) + == (PSECTION)NULL) { + return( FALSE ); + } + + if (SearchLineInSectionByKey(pSection, Key) == (PLINE)NULL) { + return( FALSE ); + } + + return( TRUE ); +} + + +PCHAR +SpGetKeyName( + IN PVOID INFHandle, + IN PCHAR SectionName, + IN ULONG LineIndex + ) +{ + PSECTION pSection; + PLINE pLine; + + pSection = SearchSectionByName((PINF)INFHandle,SectionName); + if(pSection == NULL) { + return(NULL); + } + + pLine = SearchLineInSectionByIndex(pSection,LineIndex); + if(pLine == NULL) { + return(NULL); + } + + return(pLine->pName); +} + + + +// +// given section name, key and index return the value +// +PCHAR +SpGetSectionKeyIndex ( + IN PVOID INFHandle, + IN PCHAR SectionName, + IN PCHAR Key, + IN ULONG ValueIndex + ) + +/*++ + +Routine Description: + + +Arguments: + + +Return Value: + + +--*/ + +{ + PSECTION pSection; + PLINE pLine; + PINFVALUE pValue; + + if((pSection = SearchSectionByName( + (PINF)INFHandle, + SectionName + )) + == (PSECTION)NULL) + return((PCHAR)NULL); + + if((pLine = SearchLineInSectionByKey( + pSection, + Key + )) + == (PLINE)NULL) + return((PCHAR)NULL); + + if((pValue = SearchValueInLine( + pLine, + ValueIndex + )) + == (PINFVALUE)NULL) + return((PCHAR)NULL); + + return (pValue->pName); + +} + + + + +PINFVALUE +SearchValueInLine( + IN PLINE pLine, + IN ULONG ValueIndex + ) + +/*++ + +Routine Description: + + +Arguments: + + +Return Value: + + +--*/ + +{ + PINFVALUE pValue; + ULONG i; + + if (pLine == (PLINE)NULL) + return ((PINFVALUE)NULL); + + pValue = pLine->pValue; + for (i = 0; i < ValueIndex && ((pValue = pValue->pNext) != (PINFVALUE)NULL); i++) + ; + + return pValue; + +} + +PLINE +SearchLineInSectionByKey( + IN PSECTION pSection, + IN PCHAR Key + ) + +/*++ + +Routine Description: + + +Arguments: + + +Return Value: + + +--*/ + +{ + PLINE pLine; + + if (pSection == (PSECTION)NULL || Key == (PCHAR)NULL) { + return ((PLINE)NULL); + } + + pLine = pSection->pLine; + while ((pLine != (PLINE)NULL) && (pLine->pName == NULL || _strcmpi(pLine->pName, Key))) { + pLine = pLine->pNext; + } + + return pLine; + +} + + +PLINE +SearchLineInSectionByIndex( + IN PSECTION pSection, + IN ULONG LineIndex + ) + +/*++ + +Routine Description: + + +Arguments: + + +Return Value: + + +--*/ + +{ + PLINE pLine; + ULONG i; + + // + // Validate the parameters passed in + // + + if (pSection == (PSECTION)NULL) { + return ((PLINE)NULL); + } + + // + // find the start of the line list in the section passed in + // + + pLine = pSection->pLine; + + // + // traverse down the current line list to the LineIndex th line + // + + for (i = 0; i < LineIndex && ((pLine = pLine->pNext) != (PLINE)NULL); i++) { + ; + } + + // + // return the Line found + // + + return pLine; + +} + + +PSECTION +SearchSectionByName( + IN PINF pINF, + IN PCHAR SectionName + ) + +/*++ + +Routine Description: + + +Arguments: + + +Return Value: + + +--*/ + +{ + PSECTION pSection; + + // + // validate the parameters passed in + // + + if (pINF == (PINF)NULL || SectionName == (PCHAR)NULL) { + return ((PSECTION)NULL); + } + + // + // find the section list + // + pSection = pINF->pSection; + + // + // traverse down the section list searching each section for the section + // name mentioned + // + + while ((pSection != (PSECTION)NULL) && _strcmpi(pSection->pName, SectionName)) { + pSection = pSection->pNext; + } + + // + // return the section at which we stopped (either NULL or the section + // which was found + // + + return pSection; + +} + + +// what follows was alparse.c + + +// +// Globals used to make building the lists easier +// + +PINF pINF; +PSECTION pSectionRecord; +PLINE pLineRecord; +PINFVALUE pValueRecord; + + +// +// Globals used by the token parser +// + +// string terminators are the whitespace characters (isspace: space, tab, +// linefeed, formfeed, vertical tab, carriage return) or the chars given below + +PCHAR szStrTerms = "[]=,\" \t\n\f\v\r"; +PCHAR szBrcStrTerms = "[]=,\"\t\n\f\v\r"; + +// +// quoted string terminators allow some of the regular terminators to +// appear as characters + +PCHAR szQStrTerms = "\"\n\f\v\r"; + +// +// curly brace string terminators are given below +// + +PCHAR szCBrStrTerms = "}\n\f\v\r"; + +// +// Main parser routine +// + +PVOID +ParseInfBuffer( + PCHAR Buffer, + ULONG Size + ) + +/*++ + +Routine Description: + + Given a character buffer containing the INF file, this routine parses + the INF into an internal form with Section records, Line records and + Value records. + +Arguments: + + Buffer - contains to ptr to a buffer containing the INF file + + Size - contains the size of the buffer. + +Return Value: + + PVOID - INF handle ptr to be used in subsequent INF calls. + +--*/ + +{ + PCHAR Stream, MaxStream, pchSectionName, pchValue; + ULONG State, InfLine; + ULONG LastState; + TOKEN Token; + BOOLEAN Done; + BOOLEAN Error; + PCHAR pszStrTermsCur = szStrTerms; + PCHAR pszQStrTermsCur = szQStrTerms; + PCHAR pszCBrStrTermsCur = szCBrStrTerms; + + ARC_STATUS ErrorCode; + + // + // Initialise the globals + // + pINF = (PINF)NULL; + pSectionRecord = (PSECTION)NULL; + pLineRecord = (PLINE)NULL; + pValueRecord = (PINFVALUE)NULL; + + // + // Get INF record + // + if ((pINF = (PINF)SpMalloc(sizeof(INF))) == NULL) { + + return ( NULL ); + } + + pINF->pSection = NULL; + + // + // Set initial state + // + State = 1; + LastState = State; + InfLine = 1; + Stream = Buffer; + MaxStream = Buffer + Size; + Done = FALSE; + Error = FALSE; + + pchSectionName = NULL; + pchValue = NULL; + + // + // Enter token processing loop + // + + while (!Done) { + + Token = SpGetToken(&Stream, MaxStream, pszStrTermsCur, pszQStrTermsCur, pszCBrStrTermsCur); + + switch (State) { + // + // STATE1: Start of file, this state remains till first + // section is found + // Valid Tokens: TOK_EOL, TOK_EOF, TOK_LBRACE + case 1: + switch (Token.Type) { + case TOK_EOL: + break; + case TOK_EOF: + Done = TRUE; + break; + case TOK_LBRACE: +#ifdef DEBUG + printf("LBrace seen\n"); +#endif + pszStrTermsCur = szBrcStrTerms; + State = 2; + break; + default: + Error = Done = TRUE; + ErrorCode = EINVAL; + SpSetLastError( ERROR_EXPECTED_LBRACE ); + break; + } + break; + + // + // STATE 2: Section LBRACE has been received, expecting STRING + // + // Valid Tokens: TOK_STRING + // + case 2: + + // + // allow spaces in section names + // + switch (Token.Type) { + case TOK_STRING: +#ifdef DEBUG + printf("Section Started for %s\n", Token.pValue); +#endif + State = 3; + + // + // restore term. string with space + // + pszStrTermsCur = szStrTerms; + pchSectionName = Token.pValue; + break; + + default: + + // + // restore term. string with space + // + pszStrTermsCur = szStrTerms; + Error = Done = TRUE; + ErrorCode = EINVAL; + SpSetLastError( ERROR_EXPECTED_STRING ); + break; + + } + break; + + // + // STATE 3: Section Name received, expecting RBRACE + // + // Valid Tokens: TOK_RBRACE + // + case 3: + switch (Token.Type) { + case TOK_RBRACE: +#ifdef DEBUG + printf("RBrace Seen \n"); +#endif + State = 4; + break; + + default: + Error = Done = TRUE; + ErrorCode = EINVAL; + SpSetLastError( ERROR_EXPECTED_RBRACE ); + break; + } + break; + // + // STATE 4: Section Definition Complete, expecting EOL + // + // Valid Tokens: TOK_EOL, TOK_EOF + // + case 4: + switch (Token.Type) { + case TOK_EOL: +#ifdef DEBUG + printf("Section Definition Complete for %s\n", pchSectionName); +#endif + if ((ErrorCode = SpAppendSection(pchSectionName)) != ESUCCESS) + Error = Done = TRUE; + else { + pchSectionName = NULL; + State = 5; + } + break; + + case TOK_EOF: +#ifdef DEBUG + printf("Section Definition Complete for %s\n", pchSectionName); +#endif + + if ((ErrorCode = SpAppendSection(pchSectionName)) != ESUCCESS) + Error = Done = TRUE; + else { + pchSectionName = NULL; + Done = TRUE; + } + break; + + default: + Error = Done = TRUE; + ErrorCode = EINVAL; + SpSetLastError( ERROR_EXPECTED_EOL ); + break; + } + break; + + // + // STATE 5: Expecting Section Lines + // + // Valid Tokens: TOK_EOL, TOK_EOF, TOK_STRING, TOK_LBRACE + // + case 5: + switch (Token.Type) { + case TOK_EOL: + break; + case TOK_EOF: + Done = TRUE; + break; + case TOK_STRING: +#ifdef DEBUG + printf("Section Line value %s\n", Token.pValue); +#endif + pchValue = Token.pValue; + State = 6; + break; + case TOK_LBRACE: + pszStrTermsCur = szBrcStrTerms; + State = 2; + break; + default: + // Error = Done = TRUE; + // ErrorCode = EINVAL; + // SpSetLastError( ERROR_EXPECTED_SECTION_LINE ); + State = 20; + LastState = 6; + break; + } + break; + + // + // STATE 6: String returned, not sure whether it is key or value + // + // Valid Tokens: TOK_EOL, TOK_EOF, TOK_COMMA, TOK_EQUAL + // + case 6: + switch (Token.Type) { + +#ifdef DEBUG + printf("Working determining type of string String %s\n", pchValue); +#endif + case TOK_EOL: + if ( (ErrorCode = SpAppendLine(NULL)) != ESUCCESS || + (ErrorCode = SpAppendValue(pchValue)) !=ESUCCESS ) + Error = Done = TRUE; + else { + pchValue = NULL; + State = 5; + } + break; + + case TOK_EOF: + if ( (ErrorCode = SpAppendLine(NULL)) != ESUCCESS || + (ErrorCode = SpAppendValue(pchValue)) !=ESUCCESS ) + Error = Done = TRUE; + else { + pchValue = NULL; + Done = TRUE; + } + break; + + case TOK_COMMA: + if ( (ErrorCode = SpAppendLine(NULL)) != ESUCCESS || + (ErrorCode = SpAppendValue(pchValue)) !=ESUCCESS ) + Error = Done = TRUE; + else { + pchValue = NULL; + State = 7; + } + break; + + case TOK_EQUAL: + if ( (ErrorCode = SpAppendLine(pchValue)) !=ESUCCESS) + Error = Done = TRUE; + else { + pchValue = NULL; + State = 8; + } + break; + + case TOK_STRING: + SpFree(Token.pValue); + // fall through + default: + // Error = Done = TRUE; + // ErrorCode = EINVAL; + if(pchValue) { + SpFree(pchValue); + } + State = 20; + LastState = 5; + SpSetLastError( ERROR_EXPECTED_BAD_LINE ); + break; + } + break; + + // + // STATE 7: Comma received, Expecting another string + // + // Valid Tokens: TOK_STRING + // + case 7: + switch (Token.Type) { + case TOK_STRING: +#ifdef DEBUG + printf("Comma recieved, looking for string got %s\n", Token.pValue); +#endif + if ((ErrorCode = SpAppendValue(Token.pValue)) != ESUCCESS) + Error = Done = TRUE; + else + State = 9; + + break; + default: + // Error = Done = TRUE; + // ErrorCode = EINVAL; + // SpSetLastError( ERROR_EXPECTED_COMMA_ANOTHER_STRING ); + State = 20; + LastState = 7; + break; + } + break; + // + // STATE 8: Equal received, Expecting another string + // + // Valid Tokens: TOK_STRING + // + case 8: + switch (Token.Type) { + case TOK_STRING: +#ifdef DEBUG + printf("Equal recieved, looking for string got %s\n", Token.pValue); +#endif + + if ((ErrorCode = SpAppendValue(Token.pValue)) != ESUCCESS) + Error = Done = TRUE; + else + State = 9; + + break; + + default: + + // Error = Done = TRUE; + // ErrorCode = EINVAL; + // SpSetLastError( ERROR_EXPECTED_EQUAL_ANOTHER_STRING ); + State = 20; + LastState = 8; + break; + } + break; + // + // STATE 9: String received after equal, value string + // + // Valid Tokens: TOK_EOL, TOK_EOF, TOK_COMMA + // + case 9: + switch (Token.Type) { + case TOK_EOL: + State = 5; + break; + + case TOK_EOF: + Done = TRUE; + break; + + case TOK_COMMA: + State = 7; + break; + + case TOK_STRING: + SpFree(Token.pValue); + // fall through + default: + // Error = Done = TRUE; + // ErrorCode = EINVAL; + // SpSetLastError( ERROR_EXPECTED_EQUAL_STRING_COMMA ); + State = 20; + LastState = 5; + break; + } + break; + // + // STATE 10: Value string definitely received + // + // Valid Tokens: TOK_EOL, TOK_EOF, TOK_COMMA + // + case 10: + switch (Token.Type) { + case TOK_EOL: + State =5; + break; + + case TOK_EOF: + Done = TRUE; + break; + + case TOK_COMMA: + State = 7; + break; + + case TOK_STRING: + SpFree(Token.pValue); + // fall through + default: + // Error = Done = TRUE; + // ErrorCode = EINVAL; + // SpSetLastError( ERROR_EXPECTED_EQUAL_VALUE_RECIEVED ); + State = 20; + LastState = 10; + break; + } + break; + + // + // STATE 20: Eat a line of INF + // + // Valid Tokens: TOK_EOL, TOK_EOF + // + case 20: + switch (Token.Type) { + case TOK_EOL: + State = LastState; + break; + + case TOK_EOF: + Done = TRUE; + break; + + case TOK_STRING: + SpFree(Token.pValue); + // fall through + default: + + break; + } + break; + + + + default: + Error = Done = TRUE; + ErrorCode = EINVAL; + SpSetLastError( ERROR_UNKOWN_STATE ); + break; + + } // end switch(State) + + + if (Error) { + + SpFreeINFBuffer((PVOID)pINF); + if (pchSectionName != (PCHAR)NULL) { + SpFree(pchSectionName); + } + + if (pchValue != (PCHAR)NULL) { + SpFree(pchValue); + } + + pINF = (PINF)NULL; + } + else { + + // + // Keep track of line numbers so that we can display Errors + // + + if (Token.Type == TOK_EOL) + InfLine++; + } + + } // End while + + + return((PVOID)pINF); +} + + + +ARC_STATUS +SpAppendSection( + IN PCHAR pSectionName + ) + +/*++ + +Routine Description: + + This appends a new section to the section list in the current INF. + All further lines and values pertain to this new section, so it resets + the line list and value lists too. + +Arguments: + + pSectionName - Name of the new section. ( [SectionName] ) + +Return Value: + + ESUCCESS - if successful. + ENOMEM - if memory allocation failed. + EINVAL - if invalid parameters passed in or the INF buffer not + initialised + +--*/ + +{ + PSECTION pNewSection; + + // + // Check to see if INF initialised and the parameter passed in is valid + // + + if (pINF == (PINF)NULL || pSectionName == (PCHAR)NULL) { + return EINVAL; + } + + + // + // Allocate memory for the new section + // + + if ((pNewSection = (PSECTION)SpMalloc(sizeof(SECTION))) == (PSECTION)NULL) { + + SetMemoryError(); + return ENOMEM; + } + + // + // initialise the new section + // + pNewSection->pNext = (PSECTION)NULL; + pNewSection->pLine = (PLINE)NULL; + pNewSection->pName = pSectionName; + + // + // link it in + // + + if (pSectionRecord == (PSECTION)NULL) { + pINF->pSection = pNewSection; + } + else { + pSectionRecord->pNext = pNewSection; + } + + pSectionRecord = pNewSection; + + // + // reset the current line record and current value record field + // + + pLineRecord = (PLINE)NULL; + pValueRecord = (PINFVALUE)NULL; + + return ESUCCESS; + +} + + +ARC_STATUS +SpAppendLine( + IN PCHAR pLineKey + ) + +/*++ + +Routine Description: + + This appends a new line to the line list in the current section. + All further values pertain to this new line, so it resets + the value list too. + +Arguments: + + pLineKey - Key to be used for the current line, this could be NULL. + +Return Value: + + ESUCCESS - if successful. + ENOMEM - if memory allocation failed. + EINVAL - if invalid parameters passed in or current section not + initialised + + +--*/ + + +{ + PLINE pNewLine; + + // + // Check to see if current section initialised + // + + if (pSectionRecord == (PSECTION)NULL) { + return EINVAL; + } + + // + // Allocate memory for the new Line + // + + if ((pNewLine = (PLINE)SpMalloc(sizeof(LINE))) == (PLINE)NULL) { + SetMemoryError(); + return ENOMEM; + } + + // + // Link it in + // + pNewLine->pNext = (PLINE)NULL; + pNewLine->pValue = (PINFVALUE)NULL; + pNewLine->pName = pLineKey; + + if (pLineRecord == (PLINE)NULL) { + pSectionRecord->pLine = pNewLine; + } + else { + pLineRecord->pNext = pNewLine; + } + + pLineRecord = pNewLine; + + // + // Reset the current value record + // + + pValueRecord = (PINFVALUE)NULL; + + return ESUCCESS; +} + + + +ARC_STATUS +SpAppendValue( + IN PCHAR pValueString + ) + +/*++ + +Routine Description: + + This appends a new value to the value list in the current line. + +Arguments: + + pValueString - The value string to be added. + +Return Value: + + ESUCCESS - if successful. + ENOMEM - if memory allocation failed. + EINVAL - if invalid parameters passed in or current line not + initialised. + +--*/ + +{ + PINFVALUE pNewValue; + + // + // Check to see if current line record has been initialised and + // the parameter passed in is valid + // + + if (pLineRecord == (PLINE)NULL || pValueString == (PCHAR)NULL) { + return EINVAL; + } + + // + // Allocate memory for the new value record + // + + if ((pNewValue = (PINFVALUE)SpMalloc(sizeof(INFVALUE))) == (PINFVALUE)NULL) { + SetMemoryError(); + return ENOMEM; + } + + // + // Link it in. + // + + pNewValue->pNext = (PINFVALUE)NULL; + pNewValue->pName = pValueString; + + if (pValueRecord == (PINFVALUE)NULL) + pLineRecord->pValue = pNewValue; + else + pValueRecord->pNext = pNewValue; + + pValueRecord = pNewValue; + return ESUCCESS; +} + +TOKEN +SpGetToken( + IN OUT PCHAR *Stream, + IN PCHAR MaxStream, + IN PCHAR pszStrTerms, + IN PCHAR pszQStrTerms, + IN PCHAR pszCBrStrTerms + ) + +/*++ + +Routine Description: + + This function returns the Next token from the configuration stream. + +Arguments: + + Stream - Supplies the address of the configuration stream. Returns + the address of where to start looking for tokens within the + stream. + + MaxStream - Supplies the address of the last character in the stream. + + +Return Value: + + TOKEN - Returns the next token + +--*/ + +{ + + PCHAR pch, pchStart, pchNew; + ULONG Length; + TOKEN Token; + + // + // Skip whitespace (except for eol) + // + + pch = *Stream; + while (pch < MaxStream && *pch != '\n' && isspace(*pch)) + pch++; + + + // + // Check for comments and remove them + // + + if (pch < MaxStream && + ((*pch == ';') || (*pch == '#') || (*pch == '/' && pch+1 < MaxStream && *(pch+1) =='/'))) + while (pch < MaxStream && *pch != '\n') + pch++; + + // + // Check to see if EOF has been reached, set the token to the right + // value + // + + if ( pch >= MaxStream ) { + *Stream = pch; + Token.Type = TOK_EOF; + Token.pValue = NULL; + return Token; + } + + + switch (*pch) { + + case '[' : + pch++; + Token.Type = TOK_LBRACE; + Token.pValue = NULL; + break; + + case ']' : + pch++; + Token.Type = TOK_RBRACE; + Token.pValue = NULL; + break; + + case '=' : + pch++; + Token.Type = TOK_EQUAL; + Token.pValue = NULL; + break; + + case ',' : + pch++; + Token.Type = TOK_COMMA; + Token.pValue = NULL; + break; + + case '\n' : + pch++; + Token.Type = TOK_EOL; + Token.pValue = NULL; + break; + + case '\"': + pch++; + // + // determine quoted string + // + pchStart = pch; + while (pch < MaxStream && !IsQStringTerminator(*pch, pszQStrTerms)) { + pch++; + } + + if (pch >=MaxStream || *pch != '\"') { + Token.Type = TOK_ERRPARSE; + Token.pValue = NULL; + } + else { + Length = pch - pchStart; + if ((pchNew = (PCHAR)SpMalloc(Length + 1)) == NULL) { + SetMemoryError(); + Token.Type = TOK_ERRNOMEM; + Token.pValue = NULL; + } else { + if (Length != 0) { // Null quoted strings are allowed + strncpy(pchNew, pchStart, Length); + } + pchNew[Length] = 0; + Token.Type = TOK_STRING; + Token.pValue = pchNew; + } + pch++; // advance past the quote + } + break; + + case '{': + // + // determine quoted string + // + pchStart = pch; + while (pch < MaxStream && !IsStringTerminator(*pch, pszCBrStrTerms)) { + pch++; + } + + if (pch >=MaxStream || *pch != '}') { + Token.Type = TOK_ERRPARSE; + Token.pValue = NULL; + } + else { + Length = pch - pchStart + 1; + if ((pchNew = (PCHAR)SpMalloc(Length + 1)) == NULL) { + SetMemoryError(); + Token.Type = TOK_ERRNOMEM; + Token.pValue = NULL; + } else { + if (Length != 0) { // Null quoted strings are allowed + strncpy(pchNew, pchStart, Length); + } + pchNew[Length] = 0; + Token.Type = TOK_STRING; + Token.pValue = pchNew; + } + pch++; // advance past the brace + } + break; + + + default: + // + // determine regular string + // + pchStart = pch; + while (pch < MaxStream && !IsStringTerminator(*pch, pszStrTerms)) + pch++; + + if (pch == pchStart) { + pch++; + Token.Type = TOK_ERRPARSE; + Token.pValue = NULL; + } + else { + Length = pch - pchStart; + if ((pchNew = (PCHAR)SpMalloc(Length + 1)) == NULL) { + SetMemoryError(); + Token.Type = TOK_ERRNOMEM; + Token.pValue = NULL; + } + else { + strncpy(pchNew, pchStart, Length); + pchNew[Length] = 0; + Token.Type = TOK_STRING; + Token.pValue = pchNew; + } + } + break; + } + + *Stream = pch; + return (Token); +} + + + +BOOLEAN +IsStringTerminator( + CHAR ch, + PCHAR szStrTerms + ) +/*++ + +Routine Description: + + This routine tests whether the given character terminates a quoted + string. + +Arguments: + + ch - The current character. + +Return Value: + + TRUE if the character is a quoted string terminator, FALSE otherwise. + +--*/ + +{ + + return(strchr(szStrTerms, ch) != NULL); + +} + + + +BOOLEAN +IsQStringTerminator( + CHAR ch, + PCHAR szQStrTerms + ) + +/*++ + +Routine Description: + + This routine tests whether the given character terminates a quoted + string. + +Arguments: + + ch - The current character. + + +Return Value: + + TRUE if the character is a quoted string terminator, FALSE otherwise. + + +--*/ + + +{ + + + return(strchr(szQStrTerms, ch ) != NULL); + +} diff --git a/private/windows/prsinf/spinf.h b/private/windows/prsinf/spinf.h new file mode 100644 index 000000000..3a1207380 --- /dev/null +++ b/private/windows/prsinf/spinf.h @@ -0,0 +1,104 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + alinfexp.h + +Abstract: + + This module contains the inf handling routine exports. + +Author: + + Sunil Pai (sunilp) 07-Nov-1991 + +Revision History: + + Ted Miller (tedm) 30-Jan-1992 + port to setupprp use +--*/ + +#ifndef _ALINF_ +#define _ALINF_ + +#define ESUCCESS 1 +#define EINVAL 2 +#define ENOMEM 3 + +// +// returns a handle to use for further inf parsing +// + +HANDLE +SpInitINFBuffer ( + IN PCHAR szInfFile + ); + +// +// frees an INF Buffer +// +VOID +SpFreeINFBuffer ( + IN PVOID INFHandle + ); + + +// +// searches for the existance of a particular section +// +BOOLEAN +SpSearchINFSection ( + IN PVOID INFHandle, + IN PCHAR SectionName + ); + + +// +// given section name, line number and index return the value. +// +PCHAR +SpGetSectionLineIndex ( + IN PVOID INFHandle, + IN PCHAR SectionName, + IN ULONG LineIndex, + IN ULONG ValueIndex + ); + + +// +// given section name, key searches existance +// +BOOLEAN +SpGetSectionKeyExists ( + IN PVOID INFBufferHandle, + IN PCHAR SectionName, + IN PCHAR Key + ); + + +// +// given section name, key and index return the value +// +PCHAR +SpGetSectionKeyIndex ( + IN PVOID INFBufferHandle, + IN PCHAR Section, + IN PCHAR Key, + IN ULONG ValueIndex + ); + + +// +// given section name and line index, return key +// +PCHAR +SpGetKeyName( + IN PVOID INFHandle, + IN PCHAR SectionName, + IN ULONG LineIndex + ); + +#endif // _ALINF_ + diff --git a/private/windows/prsinf/test.c b/private/windows/prsinf/test.c new file mode 100644 index 000000000..6930ce64f --- /dev/null +++ b/private/windows/prsinf/test.c @@ -0,0 +1,125 @@ +#include <windows.h> +#include <string.h> +#include "prsinf.h" +#include "spinf.h" +#include <stdio.h> + +#define ENGLISH 0 +#define GERMAN 1 +#define FRENCH 2 +#define SPANISH 3 + +void +main () { + + HANDLE hndInf; + PCHAR pszOptions, pszOptionsT; + PCHAR pszOptionText; + PCHAR pszFiles, pszFilesT; + PCHAR pszAll; + + pszFilesT = pszFiles = GetInfFileList( ); + printf("\r\n"); + if (pszFiles == NULL) { + + printf("GetInifFileList: Failed %d", GetLastError()); + return; + + } else { + + for (; *pszFiles; pszFiles += strlen(pszFiles) + 1 ) { + + printf("File list: \t %s\n", pszFiles); + + } + + printf("GetInifFileList: succeeded"); + + } + printf("\r\n"); + for (pszFiles = pszFilesT; *pszFiles; pszFiles += strlen(pszFiles) + 1 ) { + + hndInf = OpenInfFile( pszFiles, "locale" ); + + if (hndInf == BADHANDLE) { + + if (GetLastError() == ERROR_INF_TYPE_MISMATCH) { + + printf("\r\n Wrong type on %s\r\n", pszFiles); + continue; + + } else { + + printf("\r\nOpen on %s failed error %d", pszFiles, GetLastError()); + continue; + + } + + } else { + + printf("\n Open success for %s", pszFiles); + + } + + printf("\r\n"); + pszOptionsT = pszOptions = GetOptionList(hndInf, "OPTIONS"); + if (pszOptions == NULL) { + + printf("GetOptionList failed"); + return; + + } else { + + printf("GetOptionList success"); + + } + + + printf("\r\n"); + while (*pszOptions) { + + printf("\r\n"); + pszOptionText = GetOptionText(hndInf, pszOptions, ENGLISH); + if (pszOptionText == NULL) { + + printf("No Option text for %s in ENGLISH\r\n", pszOptions); + continue; + + } + + printf("In File %s Option %s with Text %s ",pszFiles, pszOptions, pszOptionText); + // LocalFree( pszOptionText ); + pszOptions += strlen(pszOptions) + 1; + + } + + LocalFree( pszOptionsT ); + + CloseInfFile( hndInf ); + } + + LocalFree( pszFilesT ); + + printf("\r\n Doing it all at once \r\n"); + + pszAll = GetAllOptionsText( "Computer", ENGLISH ); + + if (pszAll == NULL) { + + printf("GetAllOptionsText failed with error %d", GetLastError()); + return; + } + + while( *pszAll ) { + + printf("Option %s ",pszAll ); + pszAll += strlen(pszAll) + 1; + printf(" Text %s ", pszAll ); + pszAll += strlen(pszAll) + 1; + printf("In File %s ", pszAll); + pszAll += strlen(pszAll) + 1; + printf("\r\n"); + + } + +} |