regapi fixes

François Gouget fgouget at codeweavers.com
Fri Nov 9 06:31:42 CST 2001


   This patch adds support for str(x) and fixes a serious bug in the way
regapi handles strings for setValue.
   The previous code was removing the quotes before trying to decode the
format of the value (in getDataType). So "Setting"="Some String" would
give 'value=Some String'. That's fine usually but what happens for:

   "Setting"="hex(2):Some String"
    -> type=2
       expected_format=binary
       value=Some String -> to be interpreted as a binary value...
somehow

   "Setting"=str(2):"Some String"
   -> type=2 (once I added support for str(x))
      expected_format=string
      value="Some String   -> notice the extra "

   The conclusion is that quote removal must not be done before
getDataType is called.


Changelog:

   François Gouget <fgouget at codeweavers.com>

 * programs/regapi/regapi.c

   Correct handling of strings in setValue
   Better handling of str(x) and hex(x) in setValue
   Misc typos

-- 
François Gouget
fgouget at codeweavers.com
-------------- next part --------------
Index: programs/regapi/regapi.c
===================================================================
RCS file: /home/wine/wine/programs/regapi/regapi.c,v
retrieving revision 1.16
diff -u -r1.16 regapi.c
--- programs/regapi/regapi.c	2001/11/06 22:24:40	1.16
+++ programs/regapi/regapi.c	2001/11/09 09:59:12
@@ -46,46 +46,10 @@
 /* Delimiters used to parse the "value" to query queryValue*/
 #define QUERY_VALUE_MAX_ARGS  1 
 
-static const char *setValueDelim[SET_VALUE_MAX_ARGS]   = {"=", ""};  
-static const char *queryValueDelim[QUERY_VALUE_MAX_ARGS]   = {""};  
+static const char *setValueDelim[SET_VALUE_MAX_ARGS]   = {"=", ""};
+static const char *queryValueDelim[QUERY_VALUE_MAX_ARGS]   = {""};
 
-/* Array used to extract the data type from a string in getDataType. */
-typedef struct tagDataTypeMap
-{
-  char  mask[15];
-  DWORD dataType;
-} dataTypeMap; 
-  
-static const dataTypeMap typeMap[] = 
-{
-  {"hex:",            REG_BINARY},/* could be REG_NONE (?) */
-  {"dword:",          REG_DWORD},
-  {"hex(0):",         REG_NONE},
-  {"hex(1):",         REG_SZ},
-  {"hex(2):",         REG_EXPAND_SZ},
-  {"hex(3):",         REG_BINARY},
-  {"hex(4):",         REG_DWORD},
-  {"hex(5):",         REG_DWORD_BIG_ENDIAN},
-  {"hex(6):",         REG_LINK},
-  {"hex(7):",         REG_MULTI_SZ},
-  {"hex(8):",         REG_RESOURCE_LIST},
-  {"hex(9):",         REG_FULL_RESOURCE_DESCRIPTOR},
-  {"hex(10):",        REG_RESOURCE_REQUIREMENTS_LIST},
-  {"hex(80000000):",  0x80000000},
-  {"hex(80000001):",  0x80000001},
-  {"hex(80000002):",  0x80000002},
-  {"hex(80000003):",  0x80000003},
-  {"hex(80000004):",  0x80000004},
-  {"hex(80000005):",  0x80000005},
-  {"hex(80000006):",  0x80000006},
-  {"hex(80000007):",  0x80000007},
-  {"hex(80000008):",  0x80000008},
-  {"hex(80000009):",  0x80000000},
-  {"hex(8000000a):",  0x8000000A}
-};
-const static int LAST_TYPE_MAP = sizeof(typeMap)/sizeof(dataTypeMap);
 
-
 /* 
  * Forward declaration 
  */
@@ -141,7 +105,7 @@
 /* 
  * Generic prototypes
  */
-static DWORD   getDataType(LPSTR *lpValue);
+static DWORD   getDataType(LPSTR *lpValue, DWORD* parse_type);
 static LPSTR   getRegKeyName(LPSTR lpLine);
 static HKEY    getRegClass(LPSTR lpLine);
 static LPSTR   getArg(LPSTR arg);
@@ -227,35 +191,59 @@
 "               The input file format is a list of DLLs to unregister\n"
 "                                February 1999.\n"
 ;
-              
+
 
 /******************************************************************************
  * This function returns the HKEY associated with the data type encoded in the 
  * value.  It modifies the input parameter (key value) in order to skip this 
  * "now useless" data type information.
+ *
+ * Note: Updated based on the algorithm used in 'server/registry.c'
  */
-DWORD getDataType(LPSTR *lpValue) 
+DWORD getDataType(LPSTR *lpValue, DWORD* parse_type)
 {
-  INT   counter  = 0;
-  DWORD dwReturn = REG_SZ;
+    struct data_type { const char *tag; int len; int type; int parse_type; };
 
-  for (; counter < LAST_TYPE_MAP; counter++)
-  {
-    LONG len = strlen(typeMap[counter].mask);
-    if ( strncasecmp( *lpValue, typeMap[counter].mask, len) == IDENTICAL)
+    static const struct data_type data_types[] =
+    {                   /* actual type */  /* type to assume for parsing */
+        { "\"",        1,   REG_SZ,              REG_SZ },
+        { "str:\"",    5,   REG_SZ,              REG_SZ },
+        { "str(2):\"", 8,   REG_EXPAND_SZ,       REG_SZ },
+        { "str(7):\"", 8,   REG_MULTI_SZ,        REG_SZ },
+        { "hex:",      4,   REG_BINARY,          REG_BINARY },
+        { "dword:",    6,   REG_DWORD,           REG_DWORD },
+        { "hex(",      4,   -1,                  REG_BINARY },
+        { NULL,        0,    0,                  0 }
+    };
+
+    const struct data_type *ptr;
+    int type;
+
+    for (ptr = data_types; ptr->tag; ptr++)
     {
-      /*
-       * We found it, modify the value's pointer in order to skip the data 
-       * type identifier, set the return value and exit the loop.
-       */
-      (*lpValue) += len;
-      dwReturn    = typeMap[counter].dataType;
-      break; 
-    }
-  }
+        if (memcmp( ptr->tag, *lpValue, ptr->len ))
+            continue;
 
-  return dwReturn;
+        /* Found! */
+        *parse_type = ptr->parse_type;
+        type=ptr->type;
+        *lpValue+=ptr->len;
+        if (type == -1) {
+            char* end;
+            /* "hex(xx):" is special */
+            *lpValue += 4;
+            type = (int)strtoul( *lpValue , &end, 16 );
+            if (**lpValue=='\0' || *end!=')' || *(end+1)!=':') {
+                type=REG_NONE;
+            } else {
+                *lpValue=end+2;
+            }
+        }
+        return type;
+    }
+    return (**lpValue=='\0'?REG_SZ:REG_NONE);
 }
+
 /******************************************************************************
  * Extracts from a [HKEY\some\key\path] type of line the key name (what starts 
  * after the first '\' and end before the ']'
@@ -495,11 +483,11 @@
   HRESULT hRes;
   DWORD   dwSize          = KEY_MAX_LEN;
   DWORD   dwType          = 0;
-  DWORD   dwDataType;
+  DWORD   dwDataType,dwParseType;
 
   LPSTR   lpsCurrentValue;
 
-  LPSTR   keyValue = argv[0];
+  LPSTR   keyValue = getArg(argv[0]);
   LPSTR   keyData  = argv[1];
 
   /* Make some checks */
@@ -515,8 +503,8 @@
     keyValue[0] = '\0';
 
   /* Get the data type stored into the value field */
-  dwDataType = getDataType(&keyData);
-    
+  dwDataType = getDataType(&keyData,&dwParseType);
+
   memset(lpsCurrentValue, 0, KEY_MAX_LEN);
   hRes = RegQueryValueExA(
           currentKeyHandle, 
@@ -539,12 +527,17 @@
     BYTE   convert[KEY_MAX_LEN];
     DWORD  dwLen;
 
-    if ( dwDataType == REG_SZ )        /* no convertion for string */
+    if ( dwParseType == REG_SZ)        /* no conversion for string */
     {
       dwLen   = strlen(keyData);
+      if (dwLen>0 && keyData[dwLen-1]=='"')
+      {
+        dwLen--;
+        keyData[dwLen]='\0';
+      }
       lpbData = keyData;
     } 
-    else if (dwDataType == REG_DWORD)  /* Convert the dword types */
+    else if (dwParseType == REG_DWORD)  /* Convert the dword types */
     {
       dwLen   = convertHexToDWord(keyData, convert);
       lpbData = convert;
@@ -574,11 +567,13 @@
       if ( argv[1] != NULL ) {
         strncpy(argv[1], lpsCurrentValue, dwSize);
         argv[1][dwSize]='\0';
-    }
+      }
     }
 
-    return KEY_VALUE_ALREADY_SET;
+    hRes=KEY_VALUE_ALREADY_SET;
   }
+  if (keyValue != NULL)
+      HeapFree(GetProcessHeap(), 0, keyValue);
   return hRes;
 }
 
@@ -644,7 +639,7 @@
 
   while( (token = getToken(&cmdline, setValueDelim[argCounter])) != NULL ) 
   {
-    argv[argCounter++] = getArg(token);
+    argv[argCounter++] = token;
 
     if (argCounter == SET_VALUE_MAX_ARGS)
       break;  /* Stop processing args no matter what */
@@ -664,19 +659,12 @@
       argv[0], 
       argv[1], 
       currentKeyName);
-  
+
   else
     printf("regapi: ERROR Key %s not created. Value: %s, Data: %s\n",
       currentKeyName,
       argv[0], 
       argv[1]);
-    
-  /*
-   * Do some cleanup
-   */
-  for (counter=0; counter<argCounter; counter++)
-    if (argv[counter] != NULL)
-      HeapFree(GetProcessHeap(), 0, argv[counter]);
 }
 
 /******************************************************************************
@@ -709,7 +697,7 @@
 
   /* The value we look for is the first token on the line */
   if ( argv[0] == NULL )
-    return; /* SHOULD NOT OCCURS */
+    return; /* SHOULD NOT HAPPEN */
   else
     keyValue = argv[0]; 
 
@@ -1003,7 +991,7 @@
 
 /******************************************************************************
  * MAIN - WinMain simply validates the first parameter (command to perform)
- *        It then reads the STDIN lines by lines forwarding their processing
+ *        It then reads the STDIN line by line forwarding their processing
  *        to the appropriate method.
  */
 int PASCAL WinMain (HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
@@ -1043,8 +1031,8 @@
   }
 
   /* 
-   * check to see weather we force the action 
-   * (meaning differ depending on the command performed)
+   * check to see wether we force the action 
+   * (meaning differs depending on the command performed)
    */
   if ( cmdline != NULL ) /* will be NULL if '-force' is not provided */
     if ( strstr(cmdline, "-force") != NULL )


More information about the wine-patches mailing list