From: Jonathan Vollebregt Subject: [PATCH 2/6] reg: Add path/key conversion functions Message-Id: <1414411809-1943-2-git-send-email-jnvsor@gmail.com> Date: Mon, 27 Oct 2014 13:10:05 +0100 Functions to get the relation between root key strings and root keys, as well as functions to get the root key from a path, or the full key from a path. --- programs/reg/reg.c | 130 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 76 insertions(+), 54 deletions(-) diff --git a/programs/reg/reg.c b/programs/reg/reg.c index 6ff1707..d8e1c24 100755 --- a/programs/reg/reg.c +++ b/programs/reg/reg.c @@ -20,6 +20,33 @@ #include #include "reg.h" +#define ARRAY_COUNT(A) (sizeof(A)/sizeof(*A)) + +typedef struct { + HKEY key; + const WCHAR *short_name; + const WCHAR *long_name; +} hkey_rel; + +static const WCHAR short_hklm[] = {'H','K','L','M',0}; +static const WCHAR short_hkcu[] = {'H','K','C','U',0}; +static const WCHAR short_hkcr[] = {'H','K','C','R',0}; +static const WCHAR short_hku[] = {'H','K','U',0}; +static const WCHAR short_hkcc[] = {'H','K','C','C',0}; +static const WCHAR long_hklm[] = {'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E',0}; +static const WCHAR long_hkcu[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R',0}; +static const WCHAR long_hkcr[] = {'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T',0}; +static const WCHAR long_hku[] = {'H','K','E','Y','_','U','S','E','R','S',0}; +static const WCHAR long_hkcc[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','C','O','N','F','I','G',0}; + +static const hkey_rel root_rels[] = { + {HKEY_LOCAL_MACHINE, short_hklm, long_hklm}, + {HKEY_CURRENT_USER, short_hkcu, long_hkcu}, + {HKEY_CLASSES_ROOT, short_hkcr, long_hkcr}, + {HKEY_USERS, short_hku, long_hku}, + {HKEY_CURRENT_CONFIG, short_hkcc, long_hkcc}, +}; + static int reg_printfW(const WCHAR *msg, ...) { va_list va_args; @@ -93,35 +120,50 @@ static WCHAR *sanitize_path(WCHAR *key){ return key; } -static HKEY get_rootkey(LPWSTR key) +static inline int path_rootname_cmp(const WCHAR *path, const WCHAR *name) +{ + DWORD length = strlenW(name); + + return (strncmpiW(path, name, length) == 0 && (path[length] == 0 || path[length] == '\\')); +} + +static HKEY path_get_rootkey(const WCHAR *path) +{ + DWORD i; + + for (i = 0; i < ARRAY_COUNT(root_rels); i++) + { + if (path_rootname_cmp(path, root_rels[i].short_name) || + path_rootname_cmp(path, root_rels[i].long_name)) + return root_rels[i].key; + } + + reg_message(STRING_INVALID_KEY); + return NULL; +} + +static HKEY path_get_key(const WCHAR *path) { - static const WCHAR szHKLM[] = {'H','K','L','M',0}; - static const WCHAR szHKEY_LOCAL_MACHINE[] = {'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E',0}; - static const WCHAR szHKCU[] = {'H','K','C','U',0}; - static const WCHAR szHKEY_CURRENT_USER[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R',0}; - static const WCHAR szHKCR[] = {'H','K','C','R',0}; - static const WCHAR szHKEY_CLASSES_ROOT[] = {'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T',0}; - static const WCHAR szHKU[] = {'H','K','U',0}; - static const WCHAR szHKEY_USERS[] = {'H','K','E','Y','_','U','S','E','R','S',0}; - static const WCHAR szHKCC[] = {'H','K','C','C',0}; - static const WCHAR szHKEY_CURRENT_CONFIG[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','C','O','N','F','I','G',0}; - - if (CompareStringW(CP_ACP,NORM_IGNORECASE,key,4,szHKLM,4)==CSTR_EQUAL || - CompareStringW(CP_ACP,NORM_IGNORECASE,key,18,szHKEY_LOCAL_MACHINE,18)==CSTR_EQUAL) - return HKEY_LOCAL_MACHINE; - else if (CompareStringW(CP_ACP,NORM_IGNORECASE,key,4,szHKCU,4)==CSTR_EQUAL || - CompareStringW(CP_ACP,NORM_IGNORECASE,key,17,szHKEY_CURRENT_USER,17)==CSTR_EQUAL) - return HKEY_CURRENT_USER; - else if (CompareStringW(CP_ACP,NORM_IGNORECASE,key,4,szHKCR,4)==CSTR_EQUAL || - CompareStringW(CP_ACP,NORM_IGNORECASE,key,17,szHKEY_CLASSES_ROOT,17)==CSTR_EQUAL) - return HKEY_CLASSES_ROOT; - else if (CompareStringW(CP_ACP,NORM_IGNORECASE,key,3,szHKU,3)==CSTR_EQUAL || - CompareStringW(CP_ACP,NORM_IGNORECASE,key,10,szHKEY_USERS,10)==CSTR_EQUAL) - return HKEY_USERS; - else if (CompareStringW(CP_ACP,NORM_IGNORECASE,key,4,szHKCC,4)==CSTR_EQUAL || - CompareStringW(CP_ACP,NORM_IGNORECASE,key,19,szHKEY_CURRENT_CONFIG,19)==CSTR_EQUAL) - return HKEY_CURRENT_CONFIG; - else return NULL; + HKEY k = path_get_rootkey(path); + if (!k) + return NULL; + + path = strchrW(path, '\\'); + if (!path) + return k; + /* This returns a root key ie HKEY_CURRENT_USER. + * Wine RegCloseKey takes this without complaint, + * and it looks like native RegCloseKey does too. */ + + path++; + + if (RegOpenKeyW(k, path, &k) != ERROR_SUCCESS) + { + reg_message(STRING_CANNOT_FIND); + return NULL; + } + + return k; } static DWORD get_regtype(LPWSTR type) @@ -207,12 +249,9 @@ static int reg_add(WCHAR *key_name, WCHAR *value_name, BOOL value_empty, } p++; - root = get_rootkey(key_name); + root = path_get_rootkey(key_name); if (!root) - { - reg_message(STRING_INVALID_KEY); return 1; - } if(RegCreateKeyW(root,p,&subkey)!=ERROR_SUCCESS) { @@ -258,28 +297,15 @@ static int reg_add(WCHAR *key_name, WCHAR *value_name, BOOL value_empty, static int reg_delete(WCHAR *key_name, WCHAR *value_name, BOOL value_empty, BOOL value_all, BOOL force) { - LPWSTR p; - HKEY root,subkey; + HKEY subkey = path_get_key(key_name); static const WCHAR stubW[] = {'D','E','L','E','T','E', ' ','-',' ','%','s',' ','%','s',' ','%','d',' ','%','d',' ','%','d','\n' ,0}; reg_printfW(stubW, key_name, value_name, value_empty, value_all, force); - p = strchrW(key_name,'\\'); - if (!p) - { - reg_message(STRING_INVALID_KEY); - return 1; - } - p++; - - root = get_rootkey(key_name); - if (!root) - { - reg_message(STRING_INVALID_KEY); + if (!subkey) return 1; - } if (value_name && value_empty) { @@ -301,7 +327,9 @@ static int reg_delete(WCHAR *key_name, WCHAR *value_name, BOOL value_empty, /* Delete subtree only if no /v* option is given */ if (!value_name && !value_empty && !value_all) { - if (RegDeleteTreeW(root,p)!=ERROR_SUCCESS) + HKEY root = path_get_rootkey(key_name); + + if (RegDeleteTreeW(root, strchrW(key_name,'\\')+1) != ERROR_SUCCESS) { reg_message(STRING_CANNOT_FIND); return 1; @@ -310,12 +338,6 @@ static int reg_delete(WCHAR *key_name, WCHAR *value_name, BOOL value_empty, return 0; } - if(RegOpenKeyW(root,p,&subkey)!=ERROR_SUCCESS) - { - reg_message(STRING_CANNOT_FIND); - return 1; - } - if (value_all) { LPWSTR szValue; -- 2.1.1