Tcl Source Code

Artifact [5911041f11]
Login

Artifact 5911041f11665b8a7f77585613e4a79359fa71d8:

Attachment "winReg_v2.diff" to ticket [3362446fff] added by mistachkin 2011-07-11 17:19:05.
--- win/tclWinReg.c
+++ win/tclWinReg.c
@@ -32,10 +32,18 @@
 #ifndef KEY_WOW64_32KEY
 #define KEY_WOW64_32KEY		(0x0200)
 #endif
 
 /*
+ * The maximum length of a sub-key name.
+ */
+
+#ifndef MAX_KEY_LENGTH
+#define MAX_KEY_LENGTH		256
+#endif
+
+/*
  * TCL_STORAGE_CLASS is set unconditionally to DLLEXPORT because the
  * Registry_Init declaration is in the source file itself, which is only
  * accessed when we are building a library.
  */
 
@@ -553,10 +561,11 @@
     const 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 */
     TCHAR *buffer;		/* Buffer to hold the subkey name */
+    DWORD maxBufSize;		/* Maximum size of the buffer */
     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 */
@@ -590,30 +599,38 @@
 		Tcl_GetString(keyNameObj), "\": ", NULL);
 	AppendSystemError(interp, result);
 	RegCloseKey(key);
 	return TCL_ERROR;
     }
-    buffer = ckalloc((maxSubKeyLen+1) * sizeof(TCHAR));
+    maxBufSize = maxSubKeyLen + 1;
+    buffer = ckalloc(maxBufSize * sizeof(TCHAR));
 
     /*
      * Enumerate the subkeys.
      */
 
     resultPtr = Tcl_NewObj();
     for (index = 0; index < subKeyCount; ++index) {
-	bufSize = maxSubKeyLen+1;
+	bufSize = maxBufSize;
 	result = RegEnumKeyEx(key, index, buffer, &bufSize,
 		NULL, NULL, NULL, NULL);
+	if (result == ERROR_MORE_DATA && maxBufSize < MAX_KEY_LENGTH) {
+	    maxBufSize = MAX_KEY_LENGTH + 1;
+	    buffer = ckrealloc(buffer, maxBufSize * sizeof(TCHAR));
+	    bufSize = maxBufSize;
+	    result = RegEnumKeyEx(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;
 	}
-	Tcl_WinTCharToUtf(buffer, bufSize * sizeof(WCHAR), &ds);
+	Tcl_WinTCharToUtf(buffer, bufSize * sizeof(TCHAR), &ds);
 	name = Tcl_DStringValue(&ds);
 	if (pattern && !Tcl_StringMatch(name, pattern)) {
 	    Tcl_DStringFree(&ds);
 	    continue;
 	}
@@ -624,10 +641,12 @@
 	    break;
 	}
     }
     if (result == TCL_OK) {
 	Tcl_SetObjResult(interp, resultPtr);
+    } else {
+	Tcl_DecrRefCount(resultPtr); /* BUGFIX: Don't leak on failure. */
     }
 
     ckfree(buffer);
     RegCloseKey(key);
     return result;
@@ -896,11 +915,11 @@
     maxSize++;
 
     resultPtr = Tcl_NewObj();
     Tcl_DStringInit(&buffer);
     Tcl_DStringSetLength(&buffer,
-	    (int) (maxSize*sizeof(WCHAR)));
+	    (int) (maxSize*sizeof(TCHAR)));
     index = 0;
     result = TCL_OK;
 
     if (patternObj) {
 	pattern = Tcl_GetString(patternObj);
@@ -1207,11 +1226,11 @@
 	return result;
     }
 
     Tcl_DStringInit(&subkey);
     Tcl_DStringSetLength(&subkey,
-	    (int) (maxSize * sizeof(WCHAR)));
+	    (int) (maxSize * sizeof(TCHAR)));
 
     mode = saveMode;
     while (result == ERROR_SUCCESS) {
 	/*
 	 * Always get index 0 because key deletion changes ordering.