diff options
author | Kevin B Kenny <kennykb@acm.org> | 2007-03-17 22:41:04 (GMT) |
---|---|---|
committer | Kevin B Kenny <kennykb@acm.org> | 2007-03-17 22:41:04 (GMT) |
commit | 81071e7c69ad7aef5a908c64b219977a52442ff5 (patch) | |
tree | 86d986add8cf15393e8a67dec77791f8cc17237e /win | |
parent | 76a2ced0a1bab38668ad8bbf071794a9e437ed18 (diff) | |
download | tcl-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.c | 89 |
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; } |