summaryrefslogtreecommitdiffstats
path: root/win/tclWinReg.c
diff options
context:
space:
mode:
authorKevin B Kenny <kennykb@acm.org>2007-03-17 22:31:40 (GMT)
committerKevin B Kenny <kennykb@acm.org>2007-03-17 22:31:40 (GMT)
commitcad5197fbd7951c710146d8333f06a1e1b178211 (patch)
tree47da7b59190c06ddeded1a5fe98e19ebaa6180ff /win/tclWinReg.c
parentdc483516b0161a29c1c349f594a80ddcc2a8f9ff (diff)
downloadtcl-cad5197fbd7951c710146d8333f06a1e1b178211.zip
tcl-cad5197fbd7951c710146d8333f06a1e1b178211.tar.gz
tcl-cad5197fbd7951c710146d8333f06a1e1b178211.tar.bz2
* win/tclWinReg.c (GetKeyNames): Size the buffer for enumerating
key names correctly, so that Unicode names exceeding 127 chars can be retrieved without crashing. [Bug 1682211] * tests/registry.test (registry-4.9): Added test case for the above bug.
Diffstat (limited to 'win/tclWinReg.c')
-rw-r--r--win/tclWinReg.c88
1 files changed, 65 insertions, 23 deletions
diff --git a/win/tclWinReg.c b/win/tclWinReg.c
index f1d7e30..ca61554 100644
--- a/win/tclWinReg.c
+++ b/win/tclWinReg.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclWinReg.c,v 1.37 2006/04/05 16:52:56 dgp Exp $
+ * RCS: @(#) $Id: tclWinReg.c,v 1.38 2007/03/17 22:31:41 kennykb Exp $
*/
#include "tclInt.h"
@@ -589,21 +589,17 @@ GetKeyNames(
Tcl_Obj *keyNameObj, /* Key to enumerate. */
Tcl_Obj *patternObj) /* Optional match pattern. */
{
- HKEY key;
- DWORD index;
- char buffer[MAX_PATH+1], *pattern, *name;
- Tcl_Obj *resultPtr;
- int result = TCL_OK;
- Tcl_DString ds;
-
- /*
- * Attempt to open the key for enumeration.
- */
-
- if (OpenKey(interp, keyNameObj, KEY_ENUMERATE_SUB_KEYS, 0,
- &key) != TCL_OK) {
- return TCL_ERROR;
- }
+ char *pattern; /* Pattern being matched against subkeys */
+ HKEY key; /* Handle to the key being examined */
+ DWORD subKeyCount; /* Number of subkeys to list */
+ DWORD maxSubKeyLen; /* Maximum string length of any subkey */
+ char *buffer; /* Buffer to hold the subkey name */
+ DWORD bufSize; /* Size of the buffer */
+ DWORD index; /* Position of the current subkey */
+ char *name; /* Subkey name */
+ Tcl_Obj *resultPtr; /* List of subkeys being accumulated */
+ int result = TCL_OK; /* Return value from this command */
+ Tcl_DString ds; /* Buffer to translate subkey name to UTF-8 */
if (patternObj) {
pattern = Tcl_GetString(patternObj);
@@ -611,15 +607,58 @@ GetKeyNames(
pattern = NULL;
}
- /*
- * Enumerate over the subkeys until we get an error, indicating the end of
- * the list.
+ /* Attempt to open the key for enumeration. */
+
+ if (OpenKey(interp, keyNameObj,
+ KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
+ 0, &key) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Determine how big a buffer is needed for enumerating subkeys, and
+ * how many subkeys there are
*/
+ result = (*regWinProcs->regQueryInfoKeyProc)
+ (key, NULL, NULL, NULL, &subKeyCount, &maxSubKeyLen, NULL, NULL,
+ NULL, NULL, NULL, NULL);
+ if (result != ERROR_SUCCESS) {
+ Tcl_SetObjResult(interp, Tcl_NewObj());
+ Tcl_AppendResult(interp, "unable to query key \"",
+ Tcl_GetString(keyNameObj), "\": ", NULL);
+ AppendSystemError(interp, result);
+ RegCloseKey(key);
+ return TCL_ERROR;
+ }
+ if (regWinProcs->useWide) {
+ buffer = ckalloc((maxSubKeyLen+1) * sizeof(WCHAR));
+ } else {
+ buffer = ckalloc(maxSubKeyLen+1);
+ }
+
+ /* Enumerate the subkeys */
+
resultPtr = Tcl_NewObj();
- for (index = 0; (*regWinProcs->regEnumKeyProc)(key, index, buffer,
- MAX_PATH+1) == ERROR_SUCCESS; index++) {
- Tcl_WinTCharToUtf((TCHAR *) buffer, -1, &ds);
+ for (index = 0; index < subKeyCount; ++index) {
+ bufSize = maxSubKeyLen+1;
+ result = (*regWinProcs->regEnumKeyExProc)
+ (key, index, buffer, &bufSize, NULL, NULL, NULL, NULL);
+ if (result != ERROR_SUCCESS) {
+ Tcl_SetObjResult(interp, Tcl_NewObj());
+ Tcl_AppendResult(interp,
+ "unable to enumerate subkeys of \"",
+ Tcl_GetString(keyNameObj),
+ "\": ", NULL);
+ AppendSystemError(interp, result);
+ result = TCL_ERROR;
+ break;
+ }
+ if (regWinProcs->useWide) {
+ Tcl_WinTCharToUtf((TCHAR *) buffer, bufSize * sizeof(WCHAR), &ds);
+ } else {
+ Tcl_WinTCharToUtf((TCHAR *) buffer, bufSize, &ds);
+ }
name = Tcl_DStringValue(&ds);
if (pattern && !Tcl_StringMatch(name, pattern)) {
Tcl_DStringFree(&ds);
@@ -632,8 +671,11 @@ GetKeyNames(
break;
}
}
- Tcl_SetObjResult(interp, resultPtr);
+ if (result == TCL_OK) {
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ ckfree(buffer);
RegCloseKey(key);
return result;
}