diff --git a/src/w32-reg.c b/src/w32-reg.c index 5510df8..b1134a5 100644 --- a/src/w32-reg.c +++ b/src/w32-reg.c @@ -1,201 +1,216 @@ /* w32-reg.c - Windows registry support * Copyright (C) 2002, 2005, 2010, 2012, 2017 g10 Code GmbH * * This file is part of Libgpg-error. * * Libgpg-error is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgpg-error is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ */ #if HAVE_CONFIG_H #include #endif #ifndef HAVE_W32_SYSTEM # error This module may only be build for Windows. #endif #include #include #include #include #include #define WIN32_LEAN_AND_MEAN #include #include "gpgrt-int.h" /* Return a string from the W32 Registry or NULL in case of error. * Caller must release the return value. A NULL for root is an alias * for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. The returned * string is UTF-8 encoded; ROOT, DIR, and NAME must be plain * ASCII. */ char * _gpgrt_w32_reg_query_string (const char *root, const char *dir, const char *name) { HKEY root_key, key_handle; DWORD n1, nbytes, type; char *result = NULL; if (!root) root_key = HKEY_CURRENT_USER; else if (!strcmp (root, "HKEY_CLASSES_ROOT") || !strcmp (root, "HKCR")) root_key = HKEY_CLASSES_ROOT; else if (!strcmp (root, "HKEY_CURRENT_USER") || !strcmp (root, "HKCU")) root_key = HKEY_CURRENT_USER; else if (!strcmp (root, "HKEY_LOCAL_MACHINE") || !strcmp (root, "HKLM")) root_key = HKEY_LOCAL_MACHINE; else if (!strcmp (root, "HKEY_USERS") || !strcmp (root, "HKU")) root_key = HKEY_USERS; else if (!strcmp (root, "HKEY_PERFORMANCE_DATA")) root_key = HKEY_PERFORMANCE_DATA; else if (!strcmp (root, "HKEY_CURRENT_CONFIG") || !strcmp (root, "HKCC")) root_key = HKEY_CURRENT_CONFIG; else return NULL; if (RegOpenKeyExA (root_key, dir, 0, KEY_READ, &key_handle)) { if (root) return NULL; /* No need for a RegClose, so return direct. */ /* It seems to be common practise to fall back to HKLM. */ if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle)) return NULL; /* still no need for a RegClose, so return direct */ } /* FIXME: Use wide functions and convert to utf-8. */ nbytes = 1; if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes)) { if (root) goto leave; /* Try to fallback to HKLM also for a missing value. */ RegCloseKey (key_handle); if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle)) return NULL; /* Nope. */ if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes)) goto leave; } n1 = nbytes + 1; result = xtrymalloc (n1); if (!result) goto leave; if (RegQueryValueExA (key_handle, name, 0, &type, (LPBYTE) result, &n1)) { xfree (result); result = NULL; goto leave; } result[nbytes] = 0; /* Make sure it is really a string. */ if (type == REG_EXPAND_SZ && strchr (result, '%')) { char *tmp; n1 += 1000; tmp = xtrymalloc (n1 + 1); if (!tmp) goto leave; nbytes = ExpandEnvironmentStrings (result, tmp, n1); if (nbytes && nbytes > n1) { xfree (tmp); n1 = nbytes; tmp = xtrymalloc (n1 + 1); if (!tmp) goto leave; nbytes = ExpandEnvironmentStrings (result, tmp, n1); if (nbytes && nbytes > n1) { xfree (tmp); /* Oops - truncated, better don't expand at all. */ goto leave; } tmp[nbytes] = 0; xfree (result); result = tmp; } else if (nbytes) /* Okay, reduce the length. */ { tmp[nbytes] = 0; xfree (result); result = xtrymalloc (strlen (tmp)+1); if (!result) result = tmp; else { strcpy (result, tmp); xfree (tmp); } } else /* Error - don't expand. */ { xfree (tmp); } } + else if (type == REG_DWORD && nbytes == sizeof (DWORD)) + { + char *tmp; + DWORD dummy; + + memcpy (&dummy, result, nbytes); + tmp = _gpgrt_estream_bsprintf ("%u", (unsigned int)dummy); + if (tmp) + { + xfree (result); + result = tmp; + } + else + _gpgrt_log_info ("warning: malloc failed while reading registry key\n"); + } leave: RegCloseKey (key_handle); return result; } /* Compact version of gpgrt_w32_reg_query_string. This version * expects a single string as key described here using an example: * * HKCU\Software\GNU\GnuPG:HomeDir * * HKCU := the class, other supported classes are HKLM, HKCR, HKU, and * HKCC. If no class is given and the string thus starts with * a backslash HKCU with a fallback to HKLM is used. * Software\GNU\GnuPG := The actual key. * HomeDir := the name of the item. The name is optional to use the default * value. * * Note that the first backslash and the first colon act as delimiters. * * Returns a malloced string or NULL if not found. */ char * _gpgrt_w32_reg_get_string (const char *key_arg) { char *key; char *p1, *p2; char *result; if (!key_arg) return NULL; key = xtrystrdup (key_arg); if (!key) { _gpgrt_log_info ("warning: malloc failed while reading registry key\n"); return NULL; } p1 = strchr (key, '\\'); if (!p1) { xfree (key); return NULL; } *p1++ = 0; p2 = strchr (p1, ':'); if (p2) *p2++ = 0; result = _gpgrt_w32_reg_query_string (*key? key : NULL, p1, p2); xfree (key); return result; }