Implement SetupGetInfFileListW and SetupGetInfInformationW Inf file parser now accept UNICODE files with FF FE header Return required buffer size when buffer is too small in SetupGetLineTextA/W, SetupGetStringFieldA/W Modified: trunk/reactos/lib/setupapi/parser.c Modified: trunk/reactos/lib/setupapi/setupapi.spec _____
Modified: trunk/reactos/lib/setupapi/parser.c --- trunk/reactos/lib/setupapi/parser.c 2005-08-07 11:52:27 UTC (rev 17161) +++ trunk/reactos/lib/setupapi/parser.c 2005-08-07 11:59:43 UTC (rev 17162) @@ -43,6 +43,11 @@
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
+/* Unicode constants */ +static const WCHAR BackSlash[] = {'\',0}; +static const WCHAR InfDirectory[] = {'i','n','f','\',0}; +static const WCHAR InfFileSpecification[] = {'*','.','i','n','f',0}; + #define CONTROL_Z '\x1a' #define MAX_SECTION_NAME_LEN 255 #define MAX_FIELD_LEN 511 /* larger fields get silently truncated */ @@ -957,7 +962,14 @@ HeapFree( GetProcessHeap(), 0, new_buff ); } } - else err = parse_buffer( file, buffer, (WCHAR *)((char *)buffer + size), error_line ); + else + { + WCHAR *new_buff = (WCHAR *)buffer; + /* Some UNICODE files may start with the UNICODE marker */ + if (*new_buff == 0xfeff) + new_buff++; + err = parse_buffer( file, new_buff, (WCHAR *)((char *)new_buff + size), error_line ); + }
if (!err) /* now check signature */ { @@ -1060,6 +1072,8 @@ WCHAR *path, *p; UINT len;
+ TRACE("%S %S %lx %p\n", name, class, style, error); + if (strchrW( name, '\' ) || strchrW( name, '/' )) { if (!(len = GetFullPathNameW( name, 0, NULL, NULL ))) return (HINF)INVALID_HANDLE_VALUE; @@ -1509,13 +1523,13 @@ total += PARSER_string_substW( file, field->text, NULL, 0 ) + 1;
if (required) *required = total; + if (total > size) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } if (buffer) { - if (total > size) - { - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - return FALSE; - } for (i = 0, field = &file->fields[line->first_field]; i < line->nb_fields; i++, field++) { unsigned int len = PARSER_string_substW( file, field->text, buffer, size ); @@ -1560,13 +1574,13 @@ total += PARSER_string_substA( file, field->text, NULL, 0 ) + 1;
if (required) *required = total; + if (total > size) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } if (buffer) { - if (total > size) - { - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - return FALSE; - } for (i = 0, field = &file->fields[line->first_field]; i < line->nb_fields; i++, field++) { unsigned int len = PARSER_string_substA( file, field->text, buffer, size ); @@ -1605,13 +1619,13 @@ if (!field) return FALSE; len = PARSER_string_substA( file, field->text, NULL, 0 ); if (required) *required = len + 1; + if (size <= len) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } if (buffer) { - if (size <= len) - { - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - return FALSE; - } PARSER_string_substA( file, field->text, buffer, size );
TRACE( "context %p/%p/%d/%d index %ld returning %s\n", @@ -1636,13 +1650,13 @@ if (!field) return FALSE; len = PARSER_string_substW( file, field->text, NULL, 0 ); if (required) *required = len + 1; + if (size <= len) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } if (buffer) { - if (size <= len) - { - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - return FALSE; - } PARSER_string_substW( file, field->text, buffer, size );
TRACE( "context %p/%p/%d/%d index %ld returning %s\n", @@ -1837,3 +1851,224 @@ *buffer = 0; /* add final null */ return TRUE; } + +/********************************************************************** * + * SetupGetInfInformationW (SETUPAPI.@) + */ +BOOL WINAPI +SetupGetInfInformationW( + IN LPCVOID InfSpec, + IN DWORD SearchControl, + IN PSP_INF_INFORMATION ReturnBuffer, + IN DWORD ReturnBufferSize, + IN PDWORD RequiredSize) +{ + HINF hInf; + DWORD requiredSize; + BOOL Ret = FALSE; + + TRACE("%p %lx %p %ld %p\n", InfSpec, SearchControl, ReturnBuffer, + ReturnBufferSize, RequiredSize); + + if (SearchControl != INFINFO_INF_SPEC_IS_HINF + && SearchControl != INFINFO_INF_NAME_IS_ABSOLUTE + && SearchControl != INFINFO_DEFAULT_SEARCH + && SearchControl != INFINFO_REVERSE_DEFAULT_SEARCH + && SearchControl != INFINFO_INF_PATH_LIST_SEARCH) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (SearchControl == INFINFO_INF_SPEC_IS_HINF) + hInf = (HINF)InfSpec; + else + { + /* open .inf file and put its handle to hInf */ + FIXME("SearchControl 0x%lx not implemented\n", SearchControl); + SetLastError(ERROR_GEN_FAILURE); + return FALSE; + } + + /* FIXME: add size of [Version] section */ + requiredSize = sizeof(SP_INF_INFORMATION); + + if (requiredSize <= ReturnBufferSize) + { + ReturnBuffer->InfStyle = INF_STYLE_WIN4; /* FIXME */ + ReturnBuffer->InfCount = 1; /* FIXME */ + /* FIXME: memcpy(ReturnBuffer->VersionData, ...); */ + Ret = TRUE; + } + else + SetLastError(ERROR_INSUFFICIENT_BUFFER); + + if (RequiredSize) + *RequiredSize = requiredSize; + + if (SearchControl != INFINFO_INF_SPEC_IS_HINF) + SetupCloseInfFile(hInf); + return Ret; +} + +/********************************************************************** * + * SetupGetInfFileListW (SETUPAPI.@) + */ +BOOL WINAPI +SetupGetInfFileListW( + IN PCWSTR DirectoryPath OPTIONAL, + IN DWORD InfStyle, + IN OUT PWSTR ReturnBuffer OPTIONAL, + IN DWORD ReturnBufferSize OPTIONAL, + OUT PDWORD RequiredSize OPTIONAL) +{ + HANDLE hSearch; + LPWSTR pFileSpecification, pFileName; + LPWSTR pBuffer = ReturnBuffer; + WIN32_FIND_DATAW wfdFileInfo; + PVOID Buffer = NULL; + size_t len; + DWORD requiredSizeInfo; + DWORD requiredSize = 0; + BOOL ret = FALSE; + + TRACE("%S %lx %p %ld %p\n", DirectoryPath, InfStyle, + ReturnBuffer, ReturnBufferSize, RequiredSize); + + if (InfStyle & ~(INF_STYLE_OLDNT | INF_STYLE_WIN4)) + { + TRACE("Unknown flags: 0x%08lx\n", InfStyle & ~(INF_STYLE_OLDNT | INF_STYLE_WIN4)); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (DirectoryPath) + { + len = wcslen(DirectoryPath); + pFileSpecification = HeapAlloc( + GetProcessHeap(), 0, + (len + MAX_PATH + 2) * sizeof(WCHAR)); + if (!pFileSpecification) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + wcscpy(pFileSpecification, DirectoryPath); + if (DirectoryPath[len] == '\') + { + pFileName = &pFileSpecification[len]; + } + else + { + wcscat(pFileSpecification, BackSlash); + pFileName = &pFileSpecification[len + 1]; + } + } + else + { + WCHAR windir[MAX_PATH]; + if (GetSystemWindowsDirectoryW(windir, MAX_PATH) == 0) + return FALSE; + len = wcslen(windir); + pFileSpecification = HeapAlloc( + GetProcessHeap(), 0, + (len + MAX_PATH + 6) * sizeof(WCHAR)); + if (!pFileSpecification) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + wcscpy(pFileSpecification, windir); + if (windir[len] != '\') + wcscat(pFileSpecification, BackSlash); + wcscat(pFileSpecification, InfDirectory); + pFileName = &pFileSpecification[wcslen(pFileSpecification)]; + } + wcscpy(pFileName, InfFileSpecification); + hSearch = FindFirstFileW(pFileSpecification, &wfdFileInfo); + if (hSearch == INVALID_HANDLE_VALUE) + { + HeapFree(GetProcessHeap(), 0, pFileSpecification); + return FALSE; + } + + ret = TRUE; + do + { + HINF hInf; + + wcscpy(pFileName, wfdFileInfo.cFileName); + hInf = SetupOpenInfFileW( + pFileSpecification, + NULL, /* Inf class */ + InfStyle, + NULL /* Error line */); + if (hInf == INVALID_HANDLE_VALUE) + { + if (GetLastError() == ERROR_CLASS_MISMATCH) + { + /* InfStyle was not correct. Skip this file */ + continue; + } + TRACE("Invalid .inf file %S\n", pFileSpecification); + continue; + } + + ret = SetupGetInfInformationW( + hInf, + INFINFO_INF_SPEC_IS_HINF, + NULL, 0, + &requiredSizeInfo); + if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + break; + + if (!ret) + { + Buffer = HeapAlloc(GetProcessHeap(), 0, requiredSizeInfo); + if (!Buffer) + { + SetupCloseInfFile(hInf); + ret = FALSE; + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + break; + } + + ret = SetupGetInfInformationW( + hInf, + INFINFO_INF_SPEC_IS_HINF, + Buffer, requiredSizeInfo, + &requiredSizeInfo); + if (!ret) + break; + } + + len = wcslen(wfdFileInfo.cFileName) + 1; + requiredSize += (DWORD)(len * sizeof(WCHAR)); + if (requiredSize <= ReturnBufferSize) + { + wcscpy(pBuffer, wfdFileInfo.cFileName); + pBuffer = &pBuffer[len]; + } + HeapFree(GetProcessHeap(), 0, Buffer); + SetupCloseInfFile(hInf); + ret = TRUE; + } while (FindNextFileW(hSearch, &wfdFileInfo)); + FindClose(hSearch); + + if (ret) + { + requiredSize += sizeof(WCHAR); /* Final NULL char */ + if (requiredSize <= ReturnBufferSize) + *pBuffer = '\0'; + else + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + ret = FALSE; + } + if (RequiredSize) + *RequiredSize = requiredSize; + } + + HeapFree(GetProcessHeap(), 0, pFileSpecification); + return ret; +} _____
Modified: trunk/reactos/lib/setupapi/setupapi.spec --- trunk/reactos/lib/setupapi/setupapi.spec 2005-08-07 11:52:27 UTC (rev 17161) +++ trunk/reactos/lib/setupapi/setupapi.spec 2005-08-07 11:59:43 UTC (rev 17162) @@ -399,9 +399,9 @@
@ stdcall SetupGetFileQueueCount(long long ptr) @ stdcall SetupGetFileQueueFlags(long ptr) @ stub SetupGetInfFileListA -@ stub SetupGetInfFileListW +@ stdcall SetupGetInfFileListW(wstr long wstr long ptr) @ stdcall SetupGetInfInformationA(ptr long ptr long ptr) -@ stub SetupGetInfInformationW +@ stdcall SetupGetInfInformationW(ptr long ptr long ptr) @ stub SetupGetInfSections @ stdcall SetupGetIntField(ptr long ptr) @ stdcall SetupGetLineByIndexA(long str long ptr)