diff options
author | Kevin B Kenny <kennykb@acm.org> | 2007-03-17 22:31:40 (GMT) |
---|---|---|
committer | Kevin B Kenny <kennykb@acm.org> | 2007-03-17 22:31:40 (GMT) |
commit | cad5197fbd7951c710146d8333f06a1e1b178211 (patch) | |
tree | 47da7b59190c06ddeded1a5fe98e19ebaa6180ff /win/tclWinReg.c | |
parent | dc483516b0161a29c1c349f594a80ddcc2a8f9ff (diff) | |
download | tcl-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.c | 88 |
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; } |