summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--doc/zlib.n1
-rw-r--r--generic/tclFileSystem.h14
-rw-r--r--generic/tclIOUtil.c40
-rw-r--r--generic/tclPathObj.c115
-rwxr-xr-xlibrary/reg/pkgIndex.tcl4
-rw-r--r--tests/registry.test6
-rw-r--r--win/tclWinReg.c116
8 files changed, 104 insertions, 197 deletions
diff --git a/ChangeLog b/ChangeLog
index 4ac5205..b84440c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2012-06-21 Jan Nijtmans <nijtmans@users.sf.net>
+
+ * win/tclWinReg.c: [Bug #3362446]: registry keys command fails
+ * tests/registry.test: with 8.5/8.6
+
2012-06-11 Don Porter <dgp@users.sourceforge.net>
* generic/tclBasic.c: [Bug 3532959] Make sure the lifetime management
diff --git a/doc/zlib.n b/doc/zlib.n
index 2edd62f..a78e8e3 100644
--- a/doc/zlib.n
+++ b/doc/zlib.n
@@ -262,7 +262,6 @@ The stream will be a compressing stream that produces gzip-format output,
using compression level \fIlevel\fR (if specified) which will be an integer
from 0 to 9, and the header descriptor dictionary \fIheader\fR (if specified;
for keys see \fBzlib gzip\fR).
-'\" TODO: Header dictionary!
.TP
\fBzlib stream inflate\fR ?\fB\-dictionary \fIbindata\fR?
.
diff --git a/generic/tclFileSystem.h b/generic/tclFileSystem.h
index 5e48dec..8a85421 100644
--- a/generic/tclFileSystem.h
+++ b/generic/tclFileSystem.h
@@ -63,23 +63,17 @@ typedef struct ThreadSpecificData {
MODULE_SCOPE int TclFSCwdPointerEquals(Tcl_Obj **pathPtrPtr);
MODULE_SCOPE int TclFSMakePathFromNormalized(Tcl_Interp *interp,
- Tcl_Obj *pathPtr, ClientData clientData);
+ Tcl_Obj *pathPtr);
MODULE_SCOPE int TclFSNormalizeToUniquePath(Tcl_Interp *interp,
- Tcl_Obj *pathPtr, int startAt,
- ClientData *clientDataPtr);
+ Tcl_Obj *pathPtr, int startAt);
MODULE_SCOPE Tcl_Obj * TclFSMakePathRelative(Tcl_Interp *interp,
Tcl_Obj *pathPtr, Tcl_Obj *cwdPtr);
-MODULE_SCOPE Tcl_Obj * TclFSInternalToNormalized(
- const Tcl_Filesystem *fromFilesystem,
- ClientData clientData,
- FilesystemRecord **fsRecPtrPtr);
MODULE_SCOPE int TclFSEnsureEpochOk(Tcl_Obj *pathPtr,
const Tcl_Filesystem **fsPtrPtr);
MODULE_SCOPE void TclFSSetPathDetails(Tcl_Obj *pathPtr,
- FilesystemRecord *fsRecPtr,
- ClientData clientData);
+ const Tcl_Filesystem *fsPtr, ClientData clientData);
MODULE_SCOPE Tcl_Obj * TclFSNormalizeAbsolutePath(Tcl_Interp *interp,
- Tcl_Obj *pathPtr, ClientData *clientDataPtr);
+ Tcl_Obj *pathPtr);
/*
* Private shared variables for use by tclIOUtil.c and tclPathObj.c
diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c
index c4e7db0..f466ca8 100644
--- a/generic/tclIOUtil.c
+++ b/generic/tclIOUtil.c
@@ -1347,14 +1347,9 @@ int
TclFSNormalizeToUniquePath(
Tcl_Interp *interp, /* Used for error messages. */
Tcl_Obj *pathPtr, /* The path to normalize in place. */
- int startAt, /* Start at this char-offset. */
- ClientData *clientDataPtr) /* If we generated a complete normalized path
- * for a given filesystem, we can optionally
- * return an fs-specific clientdata here. */
+ int startAt) /* Start at this char-offset. */
{
FilesystemRecord *fsRecPtr, *firstFsRecPtr;
- /* Ignore this variable */
- (void) clientDataPtr;
/*
* Call each of the "normalise path" functions in succession. This is a
@@ -2633,7 +2628,7 @@ Tcl_FSGetCwd(
retVal = fsRecPtr->fsPtr->internalToNormalizedProc(retCd);
Tcl_IncrRefCount(retVal);
- norm = TclFSNormalizeAbsolutePath(interp,retVal,NULL);
+ norm = TclFSNormalizeAbsolutePath(interp,retVal);
if (norm != NULL) {
/*
* We found a cwd, which is now in our global storage. We
@@ -2672,7 +2667,7 @@ Tcl_FSGetCwd(
*/
if (retVal != NULL) {
- Tcl_Obj *norm = TclFSNormalizeAbsolutePath(interp, retVal, NULL);
+ Tcl_Obj *norm = TclFSNormalizeAbsolutePath(interp, retVal);
if (norm != NULL) {
/*
@@ -2762,7 +2757,7 @@ Tcl_FSGetCwd(
* Normalize the path.
*/
- norm = TclFSNormalizeAbsolutePath(interp, retVal, NULL);
+ norm = TclFSNormalizeAbsolutePath(interp, retVal);
/*
* Check whether cwd has changed from the value previously stored in
@@ -3953,31 +3948,6 @@ Tcl_FSSplitPath(
}
return result;
}
-
-/* Simple helper function. */
-Tcl_Obj *
-TclFSInternalToNormalized(
- const Tcl_Filesystem *fromFilesystem,
- ClientData clientData,
- FilesystemRecord **fsRecPtrPtr)
-{
- FilesystemRecord *fsRecPtr = FsGetFirstFilesystem();
-
- while (fsRecPtr != NULL) {
- if (fsRecPtr->fsPtr == fromFilesystem) {
- *fsRecPtrPtr = fsRecPtr;
- break;
- }
- fsRecPtr = fsRecPtr->nextPtr;
- }
-
- if ((fsRecPtr == NULL)
- || (fromFilesystem->internalToNormalizedProc == NULL)) {
- return NULL;
- }
- return fromFilesystem->internalToNormalizedProc(clientData);
-}
-
/*
*----------------------------------------------------------------------
*
@@ -4568,7 +4538,7 @@ Tcl_FSGetFileSystemForPath(
* call to the pathInFilesystemProc.
*/
- TclFSSetPathDetails(pathPtr, fsRecPtr, clientData);
+ TclFSSetPathDetails(pathPtr, fsRecPtr->fsPtr, clientData);
return fsRecPtr->fsPtr;
}
}
diff --git a/generic/tclPathObj.c b/generic/tclPathObj.c
index 2402128..06ee984 100644
--- a/generic/tclPathObj.c
+++ b/generic/tclPathObj.c
@@ -92,9 +92,7 @@ typedef struct FsPath {
* generated during the correct filesystem
* epoch. The epoch changes when
* filesystem-mounts are changed. */
- struct FilesystemRecord *fsRecPtr;
- /* Pointer to the filesystem record entry to
- * use for this path. */
+ const Tcl_Filesystem *fsPtr;/* The Tcl_Filesystem that claims this path */
} FsPath;
/*
@@ -152,14 +150,8 @@ typedef struct FsPath {
Tcl_Obj *
TclFSNormalizeAbsolutePath(
Tcl_Interp *interp, /* Interpreter to use */
- Tcl_Obj *pathPtr, /* Absolute path to normalize */
- ClientData *clientDataPtr) /* If non-NULL, then may be set to the
- * fs-specific clientData for this path. This
- * will happen when that extra information can
- * be calculated efficiently as a side-effect
- * of normalization. */
+ Tcl_Obj *pathPtr) /* Absolute path to normalize */
{
- ClientData clientData = NULL;
const char *dirSep, *oldDirSep;
int first = 1; /* Set to zero once we've passed the first
* directory separator - we can't use '..' to
@@ -433,17 +425,14 @@ TclFSNormalizeAbsolutePath(
* for normalizing a path.
*/
- TclFSNormalizeToUniquePath(interp, retVal, 0, &clientData);
+ TclFSNormalizeToUniquePath(interp, retVal, 0);
/*
* Since we know it is a normalized path, we can actually convert this
* object into an FsPath for greater efficiency
*/
- TclFSMakePathFromNormalized(interp, retVal, clientData);
- if (clientDataPtr != NULL) {
- *clientDataPtr = clientData;
- }
+ TclFSMakePathFromNormalized(interp, retVal);
/*
* This has a refCount of 1 for the caller, unlike many Tcl_Obj APIs.
@@ -1317,7 +1306,7 @@ TclNewFSPathObj(
fsPathPtr->cwdPtr = dirPtr;
Tcl_IncrRefCount(dirPtr);
fsPathPtr->nativePathPtr = NULL;
- fsPathPtr->fsRecPtr = NULL;
+ fsPathPtr->fsPtr = NULL;
fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
SETPATHOBJ(pathPtr, fsPathPtr);
@@ -1428,8 +1417,7 @@ TclFSMakePathRelative(
if (pathPtr->typePtr == &tclFsPathType) {
FsPath *fsPathPtr = PATHOBJ(pathPtr);
- if (PATHFLAGS(pathPtr) != 0
- && fsPathPtr->cwdPtr == cwdPtr) {
+ if (PATHFLAGS(pathPtr) != 0 && fsPathPtr->cwdPtr == cwdPtr) {
return fsPathPtr->normPathPtr;
}
}
@@ -1490,9 +1478,7 @@ TclFSMakePathRelative(
int
TclFSMakePathFromNormalized(
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
- Tcl_Obj *pathPtr, /* The object to convert. */
- ClientData nativeRep) /* The native rep for the object, if known
- * else NULL. */
+ Tcl_Obj *pathPtr) /* The object to convert. */
{
FsPath *fsPathPtr;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
@@ -1536,8 +1522,8 @@ TclFSMakePathFromNormalized(
fsPathPtr->normPathPtr = pathPtr;
fsPathPtr->cwdPtr = NULL;
- fsPathPtr->nativePathPtr = nativeRep;
- fsPathPtr->fsRecPtr = NULL;
+ fsPathPtr->nativePathPtr = NULL;
+ fsPathPtr->fsPtr = NULL;
fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
SETPATHOBJ(pathPtr, fsPathPtr);
@@ -1577,14 +1563,14 @@ Tcl_FSNewNativePath(
const Tcl_Filesystem *fromFilesystem,
ClientData clientData)
{
- Tcl_Obj *pathPtr;
+ Tcl_Obj *pathPtr = NULL;
FsPath *fsPathPtr;
- FilesystemRecord *fsFromPtr;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
- pathPtr = TclFSInternalToNormalized(fromFilesystem, clientData,
- &fsFromPtr);
+ if (fromFilesystem->internalToNormalizedProc != NULL) {
+ pathPtr = (*fromFilesystem->internalToNormalizedProc)(clientData);
+ }
if (pathPtr == NULL) {
return NULL;
}
@@ -1615,8 +1601,7 @@ Tcl_FSNewNativePath(
fsPathPtr->normPathPtr = pathPtr;
fsPathPtr->cwdPtr = NULL;
fsPathPtr->nativePathPtr = clientData;
- fsPathPtr->fsRecPtr = fsFromPtr;
- fsPathPtr->fsRecPtr->fileRefCount++;
+ fsPathPtr->fsPtr = fromFilesystem;
fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
SETPATHOBJ(pathPtr, fsPathPtr);
@@ -1778,7 +1763,6 @@ Tcl_FSGetNormalizedPath(
Tcl_Obj *dir, *copy;
int cwdLen, pathType;
- ClientData clientData = NULL;
pathType = Tcl_FSGetPathType(fsPathPtr->cwdPtr);
dir = Tcl_FSGetNormalizedPath(interp, fsPathPtr->cwdPtr);
@@ -1811,7 +1795,7 @@ Tcl_FSGetNormalizedPath(
* 2385549] ...
*/
- Tcl_Obj *newCopy = TclFSNormalizeAbsolutePath(interp, copy, NULL);
+ Tcl_Obj *newCopy = TclFSNormalizeAbsolutePath(interp, copy);
Tcl_DecrRefCount(copy);
copy = newCopy;
@@ -1826,8 +1810,7 @@ Tcl_FSGetNormalizedPath(
* will actually start off directly after that separator.
*/
- TclFSNormalizeToUniquePath(interp, copy, cwdLen-1,
- (fsPathPtr->nativePathPtr == NULL ? &clientData : NULL));
+ TclFSNormalizeToUniquePath(interp, copy, cwdLen-1);
}
/* Now we need to construct the new path object. */
@@ -1870,15 +1853,6 @@ Tcl_FSGetNormalizedPath(
TclDecrRefCount(dir);
}
- if (clientData != NULL) {
- /*
- * This may be unnecessary. It appears that the
- * TclFSNormalizeToUniquePath call above should have already set
- * this up. Not changing out of fear of the unknown.
- */
-
- fsPathPtr->nativePathPtr = clientData;
- }
PATHFLAGS(pathPtr) = 0;
}
@@ -1899,7 +1873,6 @@ Tcl_FSGetNormalizedPath(
} else if (fsPathPtr->normPathPtr == NULL) {
int cwdLen;
Tcl_Obj *copy;
- ClientData clientData = NULL;
copy = AppendPath(fsPathPtr->cwdPtr, pathPtr);
@@ -1911,17 +1884,12 @@ Tcl_FSGetNormalizedPath(
* of the previously normalized 'dir'. This should be much faster!
*/
- TclFSNormalizeToUniquePath(interp, copy, cwdLen-1,
- (fsPathPtr->nativePathPtr == NULL ? &clientData : NULL));
+ TclFSNormalizeToUniquePath(interp, copy, cwdLen-1);
fsPathPtr->normPathPtr = copy;
Tcl_IncrRefCount(fsPathPtr->normPathPtr);
- if (clientData != NULL) {
- fsPathPtr->nativePathPtr = clientData;
- }
}
}
if (fsPathPtr->normPathPtr == NULL) {
- ClientData clientData = NULL;
Tcl_Obj *useThisCwd = NULL;
int pureNormalized = 1;
@@ -2003,12 +1971,7 @@ Tcl_FSGetNormalizedPath(
*/
fsPathPtr->normPathPtr = TclFSNormalizeAbsolutePath(interp,
- absolutePath,
- (fsPathPtr->nativePathPtr == NULL ? &clientData : NULL));
- if (0 && (clientData != NULL)) {
- fsPathPtr->nativePathPtr =
- fsPathPtr->fsRecPtr->fsPtr->dupInternalRepProc(clientData);
- }
+ absolutePath);
/*
* Check if path is pure normalized (this can only be the case if it
@@ -2099,7 +2062,7 @@ Tcl_FSGetInternalRep(
* not easily achievable with the current implementation.
*/
- if (srcFsPathPtr->fsRecPtr == NULL) {
+ if (srcFsPathPtr->fsPtr == NULL) {
/*
* This only usually happens in wrappers like TclpStat which create a
* string object and pass it to TclpObjStat. Code which calls the
@@ -2119,7 +2082,7 @@ Tcl_FSGetInternalRep(
*/
srcFsPathPtr = PATHOBJ(pathPtr);
- if (srcFsPathPtr->fsRecPtr == NULL) {
+ if (srcFsPathPtr->fsPtr == NULL) {
return NULL;
}
}
@@ -2131,7 +2094,7 @@ Tcl_FSGetInternalRep(
* for this is we ask what filesystem this path belongs to.
*/
- if (fsPtr != srcFsPathPtr->fsRecPtr->fsPtr) {
+ if (fsPtr != srcFsPathPtr->fsPtr) {
const Tcl_Filesystem *actualFs = Tcl_FSGetFileSystemForPath(pathPtr);
if (actualFs == fsPtr) {
@@ -2144,7 +2107,7 @@ Tcl_FSGetInternalRep(
Tcl_FSCreateInternalRepProc *proc;
char *nativePathPtr;
- proc = srcFsPathPtr->fsRecPtr->fsPtr->createInternalRepProc;
+ proc = srcFsPathPtr->fsPtr->createInternalRepProc;
if (proc == NULL) {
return NULL;
}
@@ -2212,8 +2175,8 @@ TclFSEnsureEpochOk(
* Check whether the object is already assigned to a fs.
*/
- if (srcFsPathPtr->fsRecPtr != NULL) {
- *fsPtrPtr = srcFsPathPtr->fsRecPtr->fsPtr;
+ if (srcFsPathPtr->fsPtr != NULL) {
+ *fsPtrPtr = srcFsPathPtr->fsPtr;
}
return TCL_OK;
}
@@ -2237,7 +2200,7 @@ TclFSEnsureEpochOk(
void
TclFSSetPathDetails(
Tcl_Obj *pathPtr,
- FilesystemRecord *fsRecPtr,
+ const Tcl_Filesystem *fsPtr,
ClientData clientData)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tclFsDataKey);
@@ -2254,10 +2217,9 @@ TclFSSetPathDetails(
}
srcFsPathPtr = PATHOBJ(pathPtr);
- srcFsPathPtr->fsRecPtr = fsRecPtr;
+ srcFsPathPtr->fsPtr = fsPtr;
srcFsPathPtr->nativePathPtr = clientData;
srcFsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
- fsRecPtr->fileRefCount++;
}
/*
@@ -2504,7 +2466,7 @@ SetFsPathFromAny(
fsPathPtr->normPathPtr = NULL;
fsPathPtr->cwdPtr = NULL;
fsPathPtr->nativePathPtr = NULL;
- fsPathPtr->fsRecPtr = NULL;
+ fsPathPtr->fsPtr = NULL;
fsPathPtr->filesystemEpoch = tsdPtr->filesystemEpoch;
/*
@@ -2538,25 +2500,15 @@ FreeFsPathInternalRep(
if (fsPathPtr->cwdPtr != NULL) {
TclDecrRefCount(fsPathPtr->cwdPtr);
}
- if (fsPathPtr->nativePathPtr != NULL && fsPathPtr->fsRecPtr != NULL) {
+ if (fsPathPtr->nativePathPtr != NULL && fsPathPtr->fsPtr != NULL) {
Tcl_FSFreeInternalRepProc *freeProc =
- fsPathPtr->fsRecPtr->fsPtr->freeInternalRepProc;
+ fsPathPtr->fsPtr->freeInternalRepProc;
if (freeProc != NULL) {
freeProc(fsPathPtr->nativePathPtr);
fsPathPtr->nativePathPtr = NULL;
}
}
- if (fsPathPtr->fsRecPtr != NULL) {
- fsPathPtr->fsRecPtr->fileRefCount--;
- if (fsPathPtr->fsRecPtr->fileRefCount <= 0) {
- /*
- * It has been unregistered already.
- */
-
- ckfree(fsPathPtr->fsRecPtr);
- }
- }
ckfree(fsPathPtr);
pathPtr->typePtr = NULL;
@@ -2599,10 +2551,10 @@ DupFsPathInternalRep(
copyFsPathPtr->flags = srcFsPathPtr->flags;
- if (srcFsPathPtr->fsRecPtr != NULL
+ if (srcFsPathPtr->fsPtr != NULL
&& srcFsPathPtr->nativePathPtr != NULL) {
Tcl_FSDupInternalRepProc *dupProc =
- srcFsPathPtr->fsRecPtr->fsPtr->dupInternalRepProc;
+ srcFsPathPtr->fsPtr->dupInternalRepProc;
if (dupProc != NULL) {
copyFsPathPtr->nativePathPtr =
@@ -2613,11 +2565,8 @@ DupFsPathInternalRep(
} else {
copyFsPathPtr->nativePathPtr = NULL;
}
- copyFsPathPtr->fsRecPtr = srcFsPathPtr->fsRecPtr;
+ copyFsPathPtr->fsPtr = srcFsPathPtr->fsPtr;
copyFsPathPtr->filesystemEpoch = srcFsPathPtr->filesystemEpoch;
- if (copyFsPathPtr->fsRecPtr != NULL) {
- copyFsPathPtr->fsRecPtr->fileRefCount++;
- }
copyPtr->typePtr = &tclFsPathType;
}
diff --git a/library/reg/pkgIndex.tcl b/library/reg/pkgIndex.tcl
index f87d15c..f71b09f 100755
--- a/library/reg/pkgIndex.tcl
+++ b/library/reg/pkgIndex.tcl
@@ -1,9 +1,9 @@
if {![package vsatisfies [package provide Tcl] 8.5]} return
if {[info sharedlibextension] ne ".dll"} return
if {[::tcl::pkgconfig get debug]} {
- package ifneeded registry 1.3 \
+ package ifneeded registry 1.3.0 \
[list load [file join $dir tclreg13g.dll] registry]
} else {
- package ifneeded registry 1.3 \
+ package ifneeded registry 1.3.0 \
[list load [file join $dir tclreg13.dll] registry]
}
diff --git a/tests/registry.test b/tests/registry.test
index 7234a32..400277f 100644
--- a/tests/registry.test
+++ b/tests/registry.test
@@ -505,6 +505,12 @@ test registry-6.20 {GetValue: values with Unicode strings with embedded nulls} {
registry delete HKEY_CURRENT_USER\\TclFoobar
set result
} "foo ba r baz"
+test registry-6.21 {GetValue: very long value names and values} {pcOnly} {
+ registry set HKEY_CURRENT_USER\\TclFoobar [string repeat k 16383] [string repeat x 16383] multi_sz
+ set result [registry get HKEY_CURRENT_USER\\TclFoobar [string repeat k 16383]]
+ registry delete HKEY_CURRENT_USER\\TclFoobar
+ set result
+} [string repeat x 16383]
test registry-7.1 {GetValueNames: bad key} -constraints {win reg english} -setup {
registry delete HKEY_CURRENT_USER\\TclFoobar
diff --git a/win/tclWinReg.c b/win/tclWinReg.c
index 937089c..c508fdf 100644
--- a/win/tclWinReg.c
+++ b/win/tclWinReg.c
@@ -22,6 +22,13 @@
#endif
#include <stdlib.h>
+#ifndef UNICODE
+# undef Tcl_WinTCharToUtf
+# define Tcl_WinTCharToUtf(a,b,c) Tcl_ExternalToUtfDString(NULL,a,b,c)
+# undef Tcl_WinUtfToTChar
+# define Tcl_WinUtfToTChar(a,b,c) Tcl_UtfToExternalDString(NULL,a,b,c)
+#endif
+
/*
* Ensure that we can say which registry is being accessed.
*/
@@ -34,6 +41,14 @@
#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.
@@ -43,6 +58,14 @@
#define TCL_STORAGE_CLASS DLLEXPORT
/*
+ * The maximum length of a sub-key name.
+ */
+
+#ifndef MAX_KEY_LENGTH
+#define MAX_KEY_LENGTH 256
+#endif
+
+/*
* The following macros convert between different endian ints.
*/
@@ -157,7 +180,7 @@ Registry_Init(
cmd = Tcl_CreateObjCommand(interp, "registry", RegistryObjCmd,
interp, DeleteCmd);
Tcl_SetAssocData(interp, REGISTRY_ASSOC_KEY, NULL, cmd);
- return Tcl_PkgProvide(interp, "registry", "1.3");
+ return Tcl_PkgProvide(interp, "registry", "1.3.0");
}
/*
@@ -552,9 +575,7 @@ GetKeyNames(
{
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 */
+ TCHAR buffer[MAX_KEY_LENGTH]; /* Buffer to hold the subkey name */
DWORD bufSize; /* Size of the buffer */
DWORD index; /* Position of the current subkey */
char *name; /* Subkey name */
@@ -578,40 +599,27 @@ GetKeyNames(
}
/*
- * Determine how big a buffer is needed for enumerating subkeys, and how
- * many subkeys there are.
- */
-
- result = RegQueryInfoKey(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;
- }
- buffer = ckalloc((maxSubKeyLen+1) * sizeof(TCHAR));
-
- /*
* Enumerate the subkeys.
*/
resultPtr = Tcl_NewObj();
- for (index = 0; index < subKeyCount; ++index) {
- bufSize = maxSubKeyLen+1;
+ for (index = 0;; ++index) {
+ bufSize = MAX_KEY_LENGTH;
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;
+ if (result == ERROR_NO_MORE_ITEMS) {
+ result = TCL_OK;
+ } else {
+ 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);
@@ -626,9 +634,10 @@ GetKeyNames(
}
if (result == TCL_OK) {
Tcl_SetObjResult(interp, resultPtr);
+ } else {
+ Tcl_DecrRefCount(resultPtr); /* BUGFIX: Don't leak on failure. */
}
- ckfree(buffer);
RegCloseKey(key);
return result;
}
@@ -756,8 +765,8 @@ GetValue(
*/
Tcl_DStringInit(&data);
- length = TCL_DSTRING_STATIC_SIZE - 1;
- Tcl_DStringSetLength(&data, (int) length);
+ Tcl_DStringSetLength(&data, TCL_DSTRING_STATIC_SIZE - 1);
+ length = TCL_DSTRING_STATIC_SIZE/sizeof(TCHAR) - 1;
valueName = Tcl_GetStringFromObj(valueNameObj, &nameLen);
nativeValue = Tcl_WinUtfToTChar(valueName, nameLen, &buf);
@@ -772,7 +781,7 @@ GetValue(
*/
length *= 2;
- Tcl_DStringSetLength(&data, (int) length);
+ Tcl_DStringSetLength(&data, (int) length * sizeof(TCHAR));
result = RegQueryValueEx(key, nativeValue,
NULL, &type, (BYTE *) Tcl_DStringValue(&data), &length);
}
@@ -865,7 +874,7 @@ GetValueNames(
{
HKEY key;
Tcl_Obj *resultPtr;
- DWORD index, size, maxSize, result;
+ DWORD index, size, result;
Tcl_DString buffer, ds;
const char *pattern, *name;
@@ -878,27 +887,10 @@ GetValueNames(
return TCL_ERROR;
}
- /*
- * Query the key to determine the appropriate buffer size to hold the
- * largest value name plus the terminating null.
- */
-
- result = RegQueryInfoKey(key, NULL, NULL, NULL, NULL,
- NULL, NULL, &index, &maxSize, NULL, NULL, NULL);
- if (result != ERROR_SUCCESS) {
- Tcl_AppendResult(interp, "unable to query key \"",
- Tcl_GetString(keyNameObj), "\": ", NULL);
- AppendSystemError(interp, result);
- RegCloseKey(key);
- result = TCL_ERROR;
- goto done;
- }
- maxSize++;
-
resultPtr = Tcl_NewObj();
Tcl_DStringInit(&buffer);
Tcl_DStringSetLength(&buffer,
- (int) (maxSize*sizeof(WCHAR)));
+ (int) (MAX_KEY_LENGTH*sizeof(TCHAR)));
index = 0;
result = TCL_OK;
@@ -914,10 +906,10 @@ GetValueNames(
* each iteration because RegEnumValue smashes the old value.
*/
- size = maxSize;
+ size = MAX_KEY_LENGTH;
while (RegEnumValue(key,index, (TCHAR *)Tcl_DStringValue(&buffer),
&size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
- size *= 2;
+ size *= sizeof(TCHAR);
Tcl_WinTCharToUtf((TCHAR *) Tcl_DStringValue(&buffer), (int) size,
&ds);
@@ -933,12 +925,10 @@ GetValueNames(
Tcl_DStringFree(&ds);
index++;
- size = maxSize;
+ size = MAX_KEY_LENGTH;
}
Tcl_SetObjResult(interp, resultPtr);
Tcl_DStringFree(&buffer);
-
- done:
RegCloseKey(key);
return result;
}
@@ -1180,7 +1170,7 @@ RecursiveDeleteKey(
* encoding, not UTF. */
REGSAM mode) /* Mode flags to pass. */
{
- DWORD result, size, maxSize;
+ DWORD result, size;
Tcl_DString subkey;
HKEY hKey;
REGSAM saveMode = mode;
@@ -1200,16 +1190,10 @@ RecursiveDeleteKey(
if (result != ERROR_SUCCESS) {
return result;
}
- result = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL,
- &maxSize, NULL, NULL, NULL, NULL, NULL, NULL);
- maxSize++;
- if (result != ERROR_SUCCESS) {
- return result;
- }
Tcl_DStringInit(&subkey);
Tcl_DStringSetLength(&subkey,
- (int) (maxSize * sizeof(WCHAR)));
+ (int) (MAX_KEY_LENGTH * sizeof(TCHAR)));
mode = saveMode;
while (result == ERROR_SUCCESS) {
@@ -1217,7 +1201,7 @@ RecursiveDeleteKey(
* Always get index 0 because key deletion changes ordering.
*/
- size = maxSize;
+ size = MAX_KEY_LENGTH;
result = RegEnumKeyEx(hKey, 0, (TCHAR *)Tcl_DStringValue(&subkey),
&size, NULL, NULL, NULL, NULL);
if (result == ERROR_NO_MORE_ITEMS) {