summaryrefslogtreecommitdiffstats
path: root/win
diff options
context:
space:
mode:
authorKevin B Kenny <kennykb@acm.org>2007-03-17 22:41:04 (GMT)
committerKevin B Kenny <kennykb@acm.org>2007-03-17 22:41:04 (GMT)
commit81071e7c69ad7aef5a908c64b219977a52442ff5 (patch)
tree86d986add8cf15393e8a67dec77791f8cc17237e /win
parent76a2ced0a1bab38668ad8bbf071794a9e437ed18 (diff)
downloadtcl-81071e7c69ad7aef5a908c64b219977a52442ff5.zip
tcl-81071e7c69ad7aef5a908c64b219977a52442ff5.tar.gz
tcl-81071e7c69ad7aef5a908c64b219977a52442ff5.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')
-rw-r--r--win/tclWinReg.c89
1 files changed, 66 insertions, 23 deletions
diff --git a/win/tclWinReg.c b/win/tclWinReg.c
index ccd715a..fb6d2be 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.21.2.5 2006/04/05 16:22:18 dgp Exp $
+ * RCS: @(#) $Id: tclWinReg.c,v 1.21.2.6 2007/03/17 22:41:05 kennykb Exp $
*/
#include <tclPort.h>
@@ -513,21 +513,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);
@@ -535,15 +531,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
*/
- resultPtr = Tcl_GetObjResult(interp);
- for (index = 0; (*regWinProcs->regEnumKeyProc)(key, index, buffer,
- MAX_PATH+1) == ERROR_SUCCESS; index++) {
- Tcl_WinTCharToUtf((TCHAR *) buffer, -1, &ds);
+ 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; 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);
@@ -556,7 +595,11 @@ GetKeyNames(
break;
}
}
+ if (result == TCL_OK) {
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ ckfree(buffer);
RegCloseKey(key);
return result;
}