[SETUPAPI] Fix broken control definition.
[reactos.git] / dll / win32 / setupapi / parser.c
index 68b9ab9..d5e83a4 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+/* Partially synced with Wine Staging 2.2 */
+
 #include "setupapi_private.h"
 
-WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
+#include <ndk/obfuncs.h>
 
 /* Unicode constants */
 static const WCHAR BackSlash[] = {'\\',0};
@@ -101,6 +103,7 @@ struct parser
     int               cur_section;  /* index of section being parsed*/
     struct line      *line;         /* current line */
     unsigned int      line_pos;     /* current line position in file */
+    unsigned int      broken_line;  /* first line containing invalid data (if any) */
     unsigned int      error;        /* error code */
     unsigned int      token_len;    /* current token len */
     WCHAR token[MAX_FIELD_LEN+1];   /* current token */
@@ -149,9 +152,9 @@ static void *grow_array( void *array, unsigned int *count, size_t elem )
     if (new_count < 32) new_count = 32;
 
     if (array)
-        new_array = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, array, new_count * elem );
+       new_array = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, array, new_count * elem );
     else
-        new_array = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * elem );
+       new_array = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * elem );
 
     if (new_array)
         *count = new_count;
@@ -186,7 +189,7 @@ static struct line *find_line( struct inf_file *file, int section_index, const W
 {
     struct section *section;
     struct line *line;
-    int i;
+    unsigned int i;
 
     if (section_index < 0 || section_index >= file->nb_sections) return NULL;
     section = file->sections[section_index];
@@ -311,7 +314,7 @@ static const WCHAR *get_string_subst( const struct inf_file *file, const WCHAR *
     struct section *strings_section;
     struct line *line;
     struct field *field;
-    unsigned int i,j;
+    unsigned int i, j;
     int dirid;
     WCHAR *dirid_str, *end;
     const WCHAR *ret = NULL;
@@ -334,7 +337,28 @@ static const WCHAR *get_string_subst( const struct inf_file *file, const WCHAR *
     if (j == strings_section->nb_lines || !line->nb_fields) goto not_found;
     field = &file->fields[line->first_field];
     GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_ILANGUAGE, Lang, sizeof(Lang)/sizeof(TCHAR)); // get the current system locale for translated strings
-    strcatW(StringLangId, Lang); // append the Language identifier from GetLocaleInfo
+
+    strcpyW(StringLangId + 8, Lang + 2);
+    // now you have e.g. Strings.07 for german neutral translations
+    for (i = 0; i < file->nb_sections; i++) // search in all sections
+    {
+        if (!strcmpiW(file->sections[i]->name,StringLangId)) // if the section is a Strings.* section
+        {
+            strings_section = file->sections[i]; // select this section for further use
+            for (j = 0, line = strings_section->lines; j < strings_section->nb_lines; j++, line++) // process all lines in this section
+            {
+                if (line->key_field == -1) continue; // if no key then skip
+                if (strncmpiW( str, file->fields[line->key_field].text, *len )) continue; // if wrong key name, then skip
+                if (!file->fields[line->key_field].text[*len]) // if value exist
+                {
+                    field = &file->fields[line->first_field]; // then extract value and
+                    break; // no more search necessary
+                }
+            }
+        }
+    }
+
+    strcpyW(StringLangId + 8, Lang); // append the Language identifier from GetLocaleInfo
     // now you have e.g. Strings.0407 for german translations
     for (i = 0; i < file->nb_sections; i++) // search in all sections
     {
@@ -376,12 +400,12 @@ static const WCHAR *get_string_subst( const struct inf_file *file, const WCHAR *
 /* do string substitutions on the specified text */
 /* the buffer is assumed to be large enough */
 /* returns necessary length not including terminating null */
-unsigned int PARSER_string_substW( const struct inf_file *file, const WCHAR *text, WCHAR *buffer,
-                                   unsigned int size )
+static unsigned int PARSER_string_substW( const struct inf_file *file, const WCHAR *text,
+                                          WCHAR *buffer, unsigned int size )
 {
     const WCHAR *start, *subst, *p;
     unsigned int len, total = 0;
-    int inside = 0;
+    BOOL inside = FALSE;
 
     if (!buffer) size = MAX_STRING_LEN + 1;
     for (p = start = text; *p; p++)
@@ -429,8 +453,8 @@ unsigned int PARSER_string_substW( const struct inf_file *file, const WCHAR *tex
 /* do string substitutions on the specified text */
 /* the buffer is assumed to be large enough */
 /* returns necessary length not including terminating null */
-unsigned int PARSER_string_substA( const struct inf_file *file, const WCHAR *text, char *buffer,
-                                   unsigned int size )
+static unsigned int PARSER_string_substA( const struct inf_file *file, const WCHAR *text,
+                                          char *buffer, unsigned int size )
 {
     WCHAR buffW[MAX_STRING_LEN+1];
     DWORD ret;
@@ -482,14 +506,14 @@ static inline enum parser_state set_state( struct parser *parser, enum parser_st
 
 
 /* check if the pointer points to an end of file */
-static inline int is_eof( const struct parser *parser, const WCHAR *ptr )
+static inline BOOL is_eof( const struct parser *parser, const WCHAR *ptr )
 {
     return (ptr >= parser->end || *ptr == CONTROL_Z);
 }
 
 
 /* check if the pointer points to an end of line */
-static inline int is_eol( const struct parser *parser, const WCHAR *ptr )
+static inline BOOL is_eol( const struct parser *parser, const WCHAR *ptr )
 {
     return (ptr >= parser->end || *ptr == CONTROL_Z || *ptr == '\n');
 }
@@ -539,7 +563,7 @@ static int add_section_from_token( struct parser *parser )
 
 
 /* add a field containing the current token to the current line */
-static struct field *add_field_from_token( struct parser *parser, int is_key )
+static struct field *add_field_from_token( struct parser *parser, BOOL is_key )
 {
     struct field *field;
     WCHAR *text;
@@ -611,12 +635,15 @@ static const WCHAR *line_start_state( struct parser *parser, const WCHAR *pos )
             set_state( parser, SECTION_NAME );
             return p + 1;
         default:
-            if (!isspaceW(*p))
+            if (isspaceW(*p)) break;
+            if (parser->cur_section != -1)
             {
                 parser->start = p;
                 set_state( parser, KEY_NAME );
                 return p;
             }
+            if (!parser->broken_line)
+                parser->broken_line = parser->line_pos;
             break;
         }
     }
@@ -659,14 +686,14 @@ static const WCHAR *key_name_state( struct parser *parser, const WCHAR *pos )
 
          case '=':
             push_token( parser, token_end );
-            if (!add_field_from_token( parser, 1 )) return NULL;
+            if (!add_field_from_token( parser, TRUE )) return NULL;
             parser->start = p + 1;
             push_state( parser, VALUE_NAME );
             set_state( parser, LEADING_SPACES );
             return p + 1;
         case ';':
             push_token( parser, token_end );
-            if (!add_field_from_token( parser, 0 )) return NULL;
+            if (!add_field_from_token( parser, FALSE )) return NULL;
             push_state( parser, LINE_START );
             set_state( parser, COMMENT );
             return p + 1;
@@ -711,13 +738,13 @@ static const WCHAR *value_name_state( struct parser *parser, const WCHAR *pos )
         {
         case ';':
             push_token( parser, token_end );
-            if (!add_field_from_token( parser, 0 )) return NULL;
+            if (!add_field_from_token( parser, FALSE )) return NULL;
             push_state( parser, LINE_START );
             set_state( parser, COMMENT );
             return p + 1;
         case ',':
             push_token( parser, token_end );
-            if (!add_field_from_token( parser, 0 )) return NULL;
+            if (!add_field_from_token( parser, FALSE )) return NULL;
             parser->start = p + 1;
             push_state( parser, VALUE_NAME );
             set_state( parser, LEADING_SPACES );
@@ -747,7 +774,7 @@ static const WCHAR *value_name_state( struct parser *parser, const WCHAR *pos )
         }
     }
     push_token( parser, token_end );
-    if (!add_field_from_token( parser, 0 )) return NULL;
+    if (!add_field_from_token( parser, FALSE )) return NULL;
     set_state( parser, LINE_START );
     return p;
 }
@@ -789,7 +816,7 @@ static const WCHAR *eol_backslash_state( struct parser *parser, const WCHAR *pos
 /* handler for parser QUOTES state */
 static const WCHAR *quotes_state( struct parser *parser, const WCHAR *pos )
 {
-    const WCHAR *p, *token_end = parser->start;
+    const WCHAR *p;
 
     for (p = pos; !is_eol( parser, p ); p++)
     {
@@ -798,7 +825,7 @@ static const WCHAR *quotes_state( struct parser *parser, const WCHAR *pos )
             if (p+1 < parser->end && p[1] == '"')  /* double quotes */
             {
                 push_token( parser, p + 1 );
-                parser->start = token_end = p + 2;
+                parser->start = p + 2;
                 p++;
             }
             else  /* end of quotes */
@@ -867,6 +894,19 @@ static const WCHAR *comment_state( struct parser *parser, const WCHAR *pos )
 }
 
 
+static void free_inf_file( struct inf_file *file )
+{
+    unsigned int i;
+
+    for (i = 0; i < file->nb_sections; i++) HeapFree( GetProcessHeap(), 0, file->sections[i] );
+    HeapFree( GetProcessHeap(), 0, file->filename );
+    HeapFree( GetProcessHeap(), 0, file->sections );
+    HeapFree( GetProcessHeap(), 0, file->fields );
+    HeapFree( GetProcessHeap(), 0, file->strings );
+    HeapFree( GetProcessHeap(), 0, file );
+}
+
+
 /* parse a complete buffer */
 static DWORD parse_buffer( struct inf_file *file, const WCHAR *buffer, const WCHAR *end,
                            UINT *error_line )
@@ -884,6 +924,7 @@ static DWORD parse_buffer( struct inf_file *file, const WCHAR *buffer, const WCH
     parser.stack_pos   = 0;
     parser.cur_section = -1;
     parser.line_pos    = 1;
+    parser.broken_line = 0;
     parser.error       = 0;
     parser.token_len   = 0;
 
@@ -914,6 +955,13 @@ static DWORD parse_buffer( struct inf_file *file, const WCHAR *buffer, const WCH
 
     /* find the [strings] section */
     file->strings_section = find_section( file, Strings );
+
+    if (file->strings_section == -1 && parser.broken_line)
+    {
+        if (error_line) *error_line = parser.broken_line;
+        return ERROR_EXPECTED_SECTION_NAME;
+    }
+
     return 0;
 }
 
@@ -991,7 +1039,7 @@ static struct inf_file *parse_file( HANDLE handle, UINT *error_line, DWORD style
     }
     else
     {
-        WCHAR *new_buff = (WCHAR *)buffer;
+        WCHAR *new_buff = buffer;
         /* UCS-16 files should start with the Unicode BOM; we should skip it */
         if (*new_buff == 0xfeff)
             new_buff++;
@@ -1020,7 +1068,7 @@ static struct inf_file *parse_file( HANDLE handle, UINT *error_line, DWORD style
     UnmapViewOfFile( buffer );
     if (err)
     {
-        HeapFree( GetProcessHeap(), 0, file );
+        if (file) free_inf_file( file );
         SetLastError( err );
         file = NULL;
     }
@@ -1230,7 +1278,7 @@ HINF WINAPI SetupOpenInfFileW( PCWSTR name, PCWSTR class, DWORD style, UINT *err
 
     if (handle != INVALID_HANDLE_VALUE)
     {
-        file = parse_file( handle, error, style );
+        file = parse_file( handle, error, style);
         CloseHandle( handle );
     }
     if (!file)
@@ -1272,7 +1320,7 @@ HINF WINAPI SetupOpenInfFileW( PCWSTR name, PCWSTR class, DWORD style, UINT *err
     }
 
     SetLastError( 0 );
-    return (HINF)file;
+    return file;
 }
 
 
@@ -1345,16 +1393,10 @@ HINF WINAPI SetupOpenMasterInf( VOID )
 void WINAPI SetupCloseInfFile( HINF hinf )
 {
     struct inf_file *file = hinf;
-    unsigned int i;
 
     if (!hinf || (hinf == INVALID_HANDLE_VALUE)) return;
 
-    for (i = 0; i < file->nb_sections; i++) HeapFree( GetProcessHeap(), 0, file->sections[i] );
-    HeapFree( GetProcessHeap(), 0, file->filename );
-    HeapFree( GetProcessHeap(), 0, file->sections );
-    HeapFree( GetProcessHeap(), 0, file->fields );
-    HeapFree( GetProcessHeap(), 0, file->strings );
-    HeapFree( GetProcessHeap(), 0, file );
+    free_inf_file( file );
 }
 
 
@@ -2194,7 +2236,7 @@ SetupGetInfFileListW(
         }
 
         len = strlenW(wfdFileInfo.cFileName) + 1;
-        requiredSize += (DWORD)(len * sizeof(WCHAR));
+        requiredSize += (DWORD)len;
         if (requiredSize <= ReturnBufferSize)
         {
             strcpyW(pBuffer, wfdFileInfo.cFileName);
@@ -2204,7 +2246,7 @@ SetupGetInfFileListW(
     } while (FindNextFileW(hSearch, &wfdFileInfo));
     FindClose(hSearch);
 
-    requiredSize += sizeof(WCHAR); /* Final NULL char */
+    requiredSize += 1; /* Final NULL char */
     if (requiredSize <= ReturnBufferSize)
     {
         *pBuffer = '\0';
@@ -2353,10 +2395,12 @@ BOOL EnumerateSectionsStartingWith(
     unsigned int i;
 
     for (i = 0; i < file->nb_sections; i++)
+    {
         if (strncmpiW(pStr, file->sections[i]->name, len) == 0)
         {
             if (!Callback(file->sections[i]->name, Context))
                 return FALSE;
         }
+    }
     return TRUE;
 }