#include "winternl.h"
#include "winerror.h"
#include "setupapi.h"
+#include "setupapi_private.h"
#include "wine/unicode.h"
#include "wine/debug.h"
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 */
if (new_array)
*count = new_count;
else
- if (array)
- HeapFree( GetProcessHeap(), 0, array );
+ HeapFree( GetProcessHeap(), 0, array );
return new_array;
}
/* find a section by name */
static int find_section( struct inf_file *file, const WCHAR *name )
{
- int i;
+ unsigned int i;
for (i = 0; i < file->nb_sections; i++)
if (!strcmpiW( name, file->sections[i]->name )) return i;
struct section *strings_section;
struct line *line;
struct field *field;
- int i, dirid;
+ unsigned int i;
+ int dirid;
WCHAR *dirid_str, *end;
const WCHAR *ret = NULL;
static const WCHAR *line_start_state( struct parser *parser, const WCHAR *pos )
{
const WCHAR *p;
-
+
for (p = pos; !is_eof( parser, p ); p++)
{
switch(*p)
set_state( parser, COMMENT );
return p + 1;
case '"':
- push_token( parser, token_end );
+ push_token( parser, p );
parser->start = p + 1;
push_state( parser, KEY_NAME );
set_state( parser, QUOTES );
set_state( parser, LEADING_SPACES );
return p + 1;
case '"':
- push_token( parser, token_end );
+ push_token( parser, p );
parser->start = p + 1;
push_state( parser, VALUE_NAME );
set_state( parser, QUOTES );
static const WCHAR *leading_spaces_state( struct parser *parser, const WCHAR *pos )
{
const WCHAR *p;
-
+
for (p = pos; !is_eol( parser, p ); p++)
{
if (*p == '\\')
file->string_pos = file->strings;
file->strings_section = -1;
- if (TRUE)//(!RtlIsTextUnicode( buffer, size, NULL )) // Fireball, 07 Feb 04, temp fix
+ if (!RtlIsTextUnicode( buffer, size, NULL ))
{
WCHAR *new_buff = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) );
if (new_buff)
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 */
{
}
+/***********************************************************************
+ * PARSER_get_dest_dir
+ *
+ * retrieve a destination dir of the form "dirid,relative_path" in the given entry.
+ * returned buffer must be freed by caller.
+ */
+WCHAR *PARSER_get_dest_dir( INFCONTEXT *context )
+{
+ const WCHAR *dir;
+ WCHAR *ptr, *ret;
+ INT dirid;
+ DWORD len1, len2;
+
+ if (!SetupGetIntField( context, 1, &dirid )) return NULL;
+ if (!(dir = DIRID_get_string( context->Inf, dirid ))) return NULL;
+ len1 = strlenW(dir) + 1;
+ if (!SetupGetStringFieldW( context, 2, NULL, 0, &len2 )) len2 = 0;
+ if (!(ret = HeapAlloc( GetProcessHeap(), 0, (len1+len2) * sizeof(WCHAR) ))) return NULL;
+ strcpyW( ret, dir );
+ ptr = ret + strlenW(ret);
+ if (len2 && ptr > ret && ptr[-1] != '\\') *ptr++ = '\\';
+ if (!SetupGetStringFieldW( context, 2, ptr, len2, NULL )) *ptr = 0;
+ return ret;
+}
+
+
/***********************************************************************
* SetupOpenInfFileA (SETUPAPI.@)
*/
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;
handle = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
}
}
+
if (handle != INVALID_HANDLE_VALUE)
{
file = parse_file( handle, class, error );
}
+/***********************************************************************
+ * SetupOpenMasterInf (SETUPAPI.@)
+ */
+HINF WINAPI SetupOpenMasterInf( VOID )
+{
+ static const WCHAR Layout[] = {'\\','i','n','f','\\', 'l', 'a', 'y', 'o', 'u', 't', '.', 'i', 'n', 'f', 0};
+ WCHAR Buffer[MAX_PATH];
+
+ GetWindowsDirectoryW( Buffer, MAX_PATH );
+ strcatW( Buffer, Layout );
+ return SetupOpenInfFileW( Buffer, NULL, INF_STYLE_WIN4, NULL);
+}
+
+
+
/***********************************************************************
* SetupCloseInfFile (SETUPAPI.@)
*/
void WINAPI SetupCloseInfFile( HINF hinf )
{
struct inf_file *file = hinf;
- int i;
+ unsigned int i;
for (i = 0; i < file->nb_sections; i++) HeapFree( GetProcessHeap(), 0, file->sections[i] );
HeapFree( GetProcessHeap(), 0, file->src_root );
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 );
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 );
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",
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",
SetLastError( ERROR_LINE_NOT_FOUND );
return FALSE;
}
- if (!index || index >= line->nb_fields)
+ if (!index || index > line->nb_fields)
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
SetLastError( ERROR_LINE_NOT_FOUND );
return FALSE;
}
- if (!index || index >= line->nb_fields)
+ if (!index || index > line->nb_fields)
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
SetLastError( ERROR_LINE_NOT_FOUND );
return FALSE;
}
- if (!index || index >= line->nb_fields)
+ if (!index || index > line->nb_fields)
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
*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;
+}