os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/win/tclWinReg.c
First public contribution.
4 * This file contains the implementation of the "registry" Tcl
5 * built-in command. This command is built as a dynamically
6 * loadable extension in a separate DLL.
8 * Copyright (c) 1997 by Sun Microsystems, Inc.
9 * Copyright (c) 1998-1999 by Scriptics Corporation.
11 * See the file "license.terms" for information on usage and redistribution
12 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 * RCS: @(#) $Id: tclWinReg.c,v 1.21.2.7 2007/05/15 16:08:22 dgp Exp $
21 * TCL_STORAGE_CLASS is set unconditionally to DLLEXPORT because the
22 * Registry_Init declaration is in the source file itself, which is only
23 * accessed when we are building a library.
26 #undef TCL_STORAGE_CLASS
27 #define TCL_STORAGE_CLASS DLLEXPORT
30 * The following macros convert between different endian ints.
33 #define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
34 #define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
37 * The following flag is used in OpenKeys to indicate that the specified
38 * key should be created if it doesn't currently exist.
44 * The following tables contain the mapping from registry root names
45 * to the system predefined keys.
48 static CONST char *rootKeyNames[] = {
49 "HKEY_LOCAL_MACHINE", "HKEY_USERS", "HKEY_CLASSES_ROOT",
50 "HKEY_CURRENT_USER", "HKEY_CURRENT_CONFIG",
51 "HKEY_PERFORMANCE_DATA", "HKEY_DYN_DATA", NULL
54 static HKEY rootKeys[] = {
55 HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER,
56 HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, HKEY_DYN_DATA
60 * The following table maps from registry types to strings. Note that
61 * the indices for this array are the same as the constants for the
62 * known registry types so we don't need a separate table to hold the
66 static CONST char *typeNames[] = {
67 "none", "sz", "expand_sz", "binary", "dword",
68 "dword_big_endian", "link", "multi_sz", "resource_list", NULL
71 static DWORD lastType = REG_RESOURCE_LIST;
74 * The following structures allow us to select between the Unicode and ASCII
75 * interfaces at run time based on whether Unicode APIs are available. The
76 * Unicode APIs are preferable because they will handle characters outside
77 * of the current code page.
80 typedef struct RegWinProcs {
83 LONG (WINAPI *regConnectRegistryProc)(CONST TCHAR *, HKEY, PHKEY);
84 LONG (WINAPI *regCreateKeyExProc)(HKEY, CONST TCHAR *, DWORD, TCHAR *,
85 DWORD, REGSAM, SECURITY_ATTRIBUTES *, HKEY *, DWORD *);
86 LONG (WINAPI *regDeleteKeyProc)(HKEY, CONST TCHAR *);
87 LONG (WINAPI *regDeleteValueProc)(HKEY, CONST TCHAR *);
88 LONG (WINAPI *regEnumKeyProc)(HKEY, DWORD, TCHAR *, DWORD);
89 LONG (WINAPI *regEnumKeyExProc)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *,
90 TCHAR *, DWORD *, FILETIME *);
91 LONG (WINAPI *regEnumValueProc)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *,
92 DWORD *, BYTE *, DWORD *);
93 LONG (WINAPI *regOpenKeyExProc)(HKEY, CONST TCHAR *, DWORD, REGSAM,
95 LONG (WINAPI *regQueryInfoKeyProc)(HKEY, TCHAR *, DWORD *, DWORD *,
96 DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *,
98 LONG (WINAPI *regQueryValueExProc)(HKEY, CONST TCHAR *, DWORD *, DWORD *,
100 LONG (WINAPI *regSetValueExProc)(HKEY, CONST TCHAR *, DWORD, DWORD,
104 static RegWinProcs *regWinProcs;
106 static RegWinProcs asciiProcs = {
109 (LONG (WINAPI *)(CONST TCHAR *, HKEY, PHKEY)) RegConnectRegistryA,
110 (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, TCHAR *,
111 DWORD, REGSAM, SECURITY_ATTRIBUTES *, HKEY *,
112 DWORD *)) RegCreateKeyExA,
113 (LONG (WINAPI *)(HKEY, CONST TCHAR *)) RegDeleteKeyA,
114 (LONG (WINAPI *)(HKEY, CONST TCHAR *)) RegDeleteValueA,
115 (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD)) RegEnumKeyA,
116 (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *,
117 TCHAR *, DWORD *, FILETIME *)) RegEnumKeyExA,
118 (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *,
119 DWORD *, BYTE *, DWORD *)) RegEnumValueA,
120 (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, REGSAM,
121 HKEY *)) RegOpenKeyExA,
122 (LONG (WINAPI *)(HKEY, TCHAR *, DWORD *, DWORD *,
123 DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *,
124 FILETIME *)) RegQueryInfoKeyA,
125 (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD *, DWORD *,
126 BYTE *, DWORD *)) RegQueryValueExA,
127 (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, DWORD,
128 CONST BYTE*, DWORD)) RegSetValueExA,
131 static RegWinProcs unicodeProcs = {
134 (LONG (WINAPI *)(CONST TCHAR *, HKEY, PHKEY)) RegConnectRegistryW,
135 (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, TCHAR *,
136 DWORD, REGSAM, SECURITY_ATTRIBUTES *, HKEY *,
137 DWORD *)) RegCreateKeyExW,
138 (LONG (WINAPI *)(HKEY, CONST TCHAR *)) RegDeleteKeyW,
139 (LONG (WINAPI *)(HKEY, CONST TCHAR *)) RegDeleteValueW,
140 (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD)) RegEnumKeyW,
141 (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *,
142 TCHAR *, DWORD *, FILETIME *)) RegEnumKeyExW,
143 (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *,
144 DWORD *, BYTE *, DWORD *)) RegEnumValueW,
145 (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, REGSAM,
146 HKEY *)) RegOpenKeyExW,
147 (LONG (WINAPI *)(HKEY, TCHAR *, DWORD *, DWORD *,
148 DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *,
149 FILETIME *)) RegQueryInfoKeyW,
150 (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD *, DWORD *,
151 BYTE *, DWORD *)) RegQueryValueExW,
152 (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, DWORD,
153 CONST BYTE*, DWORD)) RegSetValueExW,
158 * Declarations for functions defined in this file.
161 static void AppendSystemError(Tcl_Interp *interp, DWORD error);
162 static int BroadcastValue(Tcl_Interp *interp, int objc,
163 Tcl_Obj * CONST objv[]);
164 static DWORD ConvertDWORD(DWORD type, DWORD value);
165 static int DeleteKey(Tcl_Interp *interp, Tcl_Obj *keyNameObj);
166 static int DeleteValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
167 Tcl_Obj *valueNameObj);
168 static int GetKeyNames(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
169 Tcl_Obj *patternObj);
170 static int GetType(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
171 Tcl_Obj *valueNameObj);
172 static int GetValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
173 Tcl_Obj *valueNameObj);
174 static int GetValueNames(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
175 Tcl_Obj *patternObj);
176 static int OpenKey(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
177 REGSAM mode, int flags, HKEY *keyPtr);
178 static DWORD OpenSubKey(char *hostName, HKEY rootKey,
179 char *keyName, REGSAM mode, int flags,
181 static int ParseKeyName(Tcl_Interp *interp, char *name,
182 char **hostNamePtr, HKEY *rootKeyPtr,
184 static DWORD RecursiveDeleteKey(HKEY hStartKey,
185 CONST TCHAR * pKeyName);
186 static int RegistryObjCmd(ClientData clientData,
187 Tcl_Interp *interp, int objc,
188 Tcl_Obj * CONST objv[]);
189 static int SetValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj,
190 Tcl_Obj *valueNameObj, Tcl_Obj *dataObj,
193 EXTERN int Registry_Init(Tcl_Interp *interp);
196 *----------------------------------------------------------------------
200 * This procedure initializes the registry command.
203 * A standard Tcl result.
208 *----------------------------------------------------------------------
215 if (!Tcl_InitStubs(interp, "8.0", 0)) {
220 * Determine if the unicode interfaces are available and select the
221 * appropriate registry function table.
224 if (TclWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
225 regWinProcs = &unicodeProcs;
227 regWinProcs = &asciiProcs;
230 Tcl_CreateObjCommand(interp, "registry", RegistryObjCmd, NULL, NULL);
231 return Tcl_PkgProvide(interp, "registry", "1.1.5");
235 *----------------------------------------------------------------------
239 * This function implements the Tcl "registry" command.
242 * A standard Tcl result.
247 *----------------------------------------------------------------------
252 ClientData clientData, /* Not used. */
253 Tcl_Interp *interp, /* Current interpreter. */
254 int objc, /* Number of arguments. */
255 Tcl_Obj * CONST objv[]) /* Argument values. */
260 static CONST char *subcommands[] = {
261 "broadcast", "delete", "get", "keys", "set", "type", "values",
265 BroadcastIdx, DeleteIdx, GetIdx, KeysIdx, SetIdx, TypeIdx, ValuesIdx
269 Tcl_WrongNumArgs(interp, objc, objv, "option ?arg arg ...?");
273 if (Tcl_GetIndexFromObj(interp, objv[1], subcommands, "option", 0, &index)
279 case BroadcastIdx: /* broadcast */
280 return BroadcastValue(interp, objc, objv);
282 case DeleteIdx: /* delete */
284 return DeleteKey(interp, objv[2]);
285 } else if (objc == 4) {
286 return DeleteValue(interp, objv[2], objv[3]);
288 errString = "keyName ?valueName?";
290 case GetIdx: /* get */
292 return GetValue(interp, objv[2], objv[3]);
294 errString = "keyName valueName";
296 case KeysIdx: /* keys */
298 return GetKeyNames(interp, objv[2], NULL);
299 } else if (objc == 4) {
300 return GetKeyNames(interp, objv[2], objv[3]);
302 errString = "keyName ?pattern?";
304 case SetIdx: /* set */
309 * Create the key and then close it immediately.
312 if (OpenKey(interp, objv[2], KEY_ALL_ACCESS, 1, &key)
318 } else if (objc == 5 || objc == 6) {
319 Tcl_Obj *typeObj = (objc == 5) ? NULL : objv[5];
320 return SetValue(interp, objv[2], objv[3], objv[4], typeObj);
322 errString = "keyName ?valueName data ?type??";
324 case TypeIdx: /* type */
326 return GetType(interp, objv[2], objv[3]);
328 errString = "keyName valueName";
330 case ValuesIdx: /* values */
332 return GetValueNames(interp, objv[2], NULL);
333 } else if (objc == 4) {
334 return GetValueNames(interp, objv[2], objv[3]);
336 errString = "keyName ?pattern?";
339 Tcl_WrongNumArgs(interp, 2, objv, errString);
344 *----------------------------------------------------------------------
348 * This function deletes a registry key.
351 * A standard Tcl result.
356 *----------------------------------------------------------------------
361 Tcl_Interp *interp, /* Current interpreter. */
362 Tcl_Obj *keyNameObj) /* Name of key to delete. */
364 char *tail, *buffer, *hostName, *keyName;
365 CONST char *nativeTail;
366 HKEY rootKey, subkey;
373 * Find the parent of the key being deleted and open it.
376 keyName = Tcl_GetStringFromObj(keyNameObj, &length);
377 buffer = ckalloc((unsigned int) length + 1);
378 strcpy(buffer, keyName);
380 if (ParseKeyName(interp, buffer, &hostName, &rootKey, &keyName)
386 resultPtr = Tcl_GetObjResult(interp);
387 if (*keyName == '\0') {
388 Tcl_AppendToObj(resultPtr, "bad key: cannot delete root keys", -1);
393 tail = strrchr(keyName, '\\');
401 result = OpenSubKey(hostName, rootKey, keyName,
402 KEY_ENUMERATE_SUB_KEYS | DELETE, 0, &subkey);
403 if (result != ERROR_SUCCESS) {
405 if (result == ERROR_FILE_NOT_FOUND) {
408 Tcl_AppendToObj(resultPtr, "unable to delete key: ", -1);
409 AppendSystemError(interp, result);
415 * Now we recursively delete the key and everything below it.
418 nativeTail = Tcl_WinUtfToTChar(tail, -1, &buf);
419 result = RecursiveDeleteKey(subkey, nativeTail);
420 Tcl_DStringFree(&buf);
422 if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
423 Tcl_AppendToObj(resultPtr, "unable to delete key: ", -1);
424 AppendSystemError(interp, result);
436 *----------------------------------------------------------------------
440 * This function deletes a value from a registry key.
443 * A standard Tcl result.
448 *----------------------------------------------------------------------
453 Tcl_Interp *interp, /* Current interpreter. */
454 Tcl_Obj *keyNameObj, /* Name of key. */
455 Tcl_Obj *valueNameObj) /* Name of value to delete. */
465 * Attempt to open the key for deletion.
468 if (OpenKey(interp, keyNameObj, KEY_SET_VALUE, 0, &key)
473 resultPtr = Tcl_GetObjResult(interp);
474 valueName = Tcl_GetStringFromObj(valueNameObj, &length);
475 Tcl_WinUtfToTChar(valueName, length, &ds);
476 result = (*regWinProcs->regDeleteValueProc)(key, Tcl_DStringValue(&ds));
477 Tcl_DStringFree(&ds);
478 if (result != ERROR_SUCCESS) {
479 Tcl_AppendStringsToObj(resultPtr, "unable to delete value \"",
480 Tcl_GetString(valueNameObj), "\" from key \"",
481 Tcl_GetString(keyNameObj), "\": ", NULL);
482 AppendSystemError(interp, result);
492 *----------------------------------------------------------------------
496 * This function enumerates the subkeys of a given key. If the
497 * optional pattern is supplied, then only keys that match the
498 * pattern will be returned.
501 * Returns the list of subkeys in the result object of the
502 * interpreter, or an error message on failure.
507 *----------------------------------------------------------------------
512 Tcl_Interp *interp, /* Current interpreter. */
513 Tcl_Obj *keyNameObj, /* Key to enumerate. */
514 Tcl_Obj *patternObj) /* Optional match pattern. */
516 char *pattern; /* Pattern being matched against subkeys */
517 HKEY key; /* Handle to the key being examined */
518 DWORD subKeyCount; /* Number of subkeys to list */
519 DWORD maxSubKeyLen; /* Maximum string length of any subkey */
520 char *buffer; /* Buffer to hold the subkey name */
521 DWORD bufSize; /* Size of the buffer */
522 DWORD index; /* Position of the current subkey */
523 char *name; /* Subkey name */
524 Tcl_Obj *resultPtr; /* List of subkeys being accumulated */
525 int result = TCL_OK; /* Return value from this command */
526 Tcl_DString ds; /* Buffer to translate subkey name to UTF-8 */
529 pattern = Tcl_GetString(patternObj);
534 /* Attempt to open the key for enumeration. */
536 if (OpenKey(interp, keyNameObj,
537 KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
538 0, &key) != TCL_OK) {
543 * Determine how big a buffer is needed for enumerating subkeys, and
544 * how many subkeys there are
547 result = (*regWinProcs->regQueryInfoKeyProc)
548 (key, NULL, NULL, NULL, &subKeyCount, &maxSubKeyLen, NULL, NULL,
549 NULL, NULL, NULL, NULL);
550 if (result != ERROR_SUCCESS) {
551 Tcl_SetObjResult(interp, Tcl_NewObj());
552 Tcl_AppendResult(interp, "unable to query key \"",
553 Tcl_GetString(keyNameObj), "\": ", NULL);
554 AppendSystemError(interp, result);
558 if (regWinProcs->useWide) {
559 buffer = ckalloc((maxSubKeyLen+1) * sizeof(WCHAR));
561 buffer = ckalloc(maxSubKeyLen+1);
564 /* Enumerate the subkeys */
566 resultPtr = Tcl_NewObj();
567 for (index = 0; index < subKeyCount; ++index) {
568 bufSize = maxSubKeyLen+1;
569 result = (*regWinProcs->regEnumKeyExProc)
570 (key, index, buffer, &bufSize, NULL, NULL, NULL, NULL);
571 if (result != ERROR_SUCCESS) {
572 Tcl_SetObjResult(interp, Tcl_NewObj());
573 Tcl_AppendResult(interp,
574 "unable to enumerate subkeys of \"",
575 Tcl_GetString(keyNameObj),
577 AppendSystemError(interp, result);
581 if (regWinProcs->useWide) {
582 Tcl_WinTCharToUtf((TCHAR *) buffer, bufSize * sizeof(WCHAR), &ds);
584 Tcl_WinTCharToUtf((TCHAR *) buffer, bufSize, &ds);
586 name = Tcl_DStringValue(&ds);
587 if (pattern && !Tcl_StringMatch(name, pattern)) {
588 Tcl_DStringFree(&ds);
591 result = Tcl_ListObjAppendElement(interp, resultPtr,
592 Tcl_NewStringObj(name, Tcl_DStringLength(&ds)));
593 Tcl_DStringFree(&ds);
594 if (result != TCL_OK) {
598 if (result == TCL_OK) {
599 Tcl_SetObjResult(interp, resultPtr);
608 *----------------------------------------------------------------------
612 * This function gets the type of a given registry value and
613 * places it in the interpreter result.
616 * Returns a normal Tcl result.
621 *----------------------------------------------------------------------
626 Tcl_Interp *interp, /* Current interpreter. */
627 Tcl_Obj *keyNameObj, /* Name of key. */
628 Tcl_Obj *valueNameObj) /* Name of value to get. */
636 CONST char *nativeValue;
640 * Attempt to open the key for reading.
643 if (OpenKey(interp, keyNameObj, KEY_QUERY_VALUE, 0, &key)
649 * Get the type of the value.
652 resultPtr = Tcl_GetObjResult(interp);
654 valueName = Tcl_GetStringFromObj(valueNameObj, &length);
655 nativeValue = Tcl_WinUtfToTChar(valueName, length, &ds);
656 result = (*regWinProcs->regQueryValueExProc)(key, nativeValue, NULL, &type,
658 Tcl_DStringFree(&ds);
661 if (result != ERROR_SUCCESS) {
662 Tcl_AppendStringsToObj(resultPtr, "unable to get type of value \"",
663 Tcl_GetString(valueNameObj), "\" from key \"",
664 Tcl_GetString(keyNameObj), "\": ", NULL);
665 AppendSystemError(interp, result);
670 * Set the type into the result. Watch out for unknown types.
671 * If we don't know about the type, just use the numeric value.
674 if (type > lastType || type < 0) {
675 Tcl_SetIntObj(resultPtr, (int) type);
677 Tcl_SetStringObj(resultPtr, typeNames[type], -1);
683 *----------------------------------------------------------------------
687 * This function gets the contents of a registry value and places
688 * a list containing the data and the type in the interpreter
692 * Returns a normal Tcl result.
697 *----------------------------------------------------------------------
702 Tcl_Interp *interp, /* Current interpreter. */
703 Tcl_Obj *keyNameObj, /* Name of key. */
704 Tcl_Obj *valueNameObj) /* Name of value to get. */
708 CONST char *nativeValue;
709 DWORD result, length, type;
711 Tcl_DString data, buf;
715 * Attempt to open the key for reading.
718 if (OpenKey(interp, keyNameObj, KEY_QUERY_VALUE, 0, &key)
724 * Initialize a Dstring to maximum statically allocated size
725 * we could get one more byte by avoiding Tcl_DStringSetLength()
726 * and just setting length to TCL_DSTRING_STATIC_SIZE, but this
727 * should be safer if the implementation of Dstrings changes.
729 * This allows short values to be read from the registy in one call.
730 * Longer values need a second call with an expanded DString.
733 Tcl_DStringInit(&data);
734 length = TCL_DSTRING_STATIC_SIZE - 1;
735 Tcl_DStringSetLength(&data, (int) length);
737 resultPtr = Tcl_GetObjResult(interp);
739 valueName = Tcl_GetStringFromObj(valueNameObj, &nameLen);
740 nativeValue = Tcl_WinUtfToTChar(valueName, nameLen, &buf);
742 result = (*regWinProcs->regQueryValueExProc)(key, nativeValue, NULL, &type,
743 (BYTE *) Tcl_DStringValue(&data), &length);
744 while (result == ERROR_MORE_DATA) {
746 * The Windows docs say that in this error case, we just need
747 * to expand our buffer and request more data.
748 * Required for HKEY_PERFORMANCE_DATA
751 Tcl_DStringSetLength(&data, (int) length);
752 result = (*regWinProcs->regQueryValueExProc)(key, (char *) nativeValue,
753 NULL, &type, (BYTE *) Tcl_DStringValue(&data), &length);
755 Tcl_DStringFree(&buf);
757 if (result != ERROR_SUCCESS) {
758 Tcl_AppendStringsToObj(resultPtr, "unable to get value \"",
759 Tcl_GetString(valueNameObj), "\" from key \"",
760 Tcl_GetString(keyNameObj), "\": ", NULL);
761 AppendSystemError(interp, result);
762 Tcl_DStringFree(&data);
767 * If the data is a 32-bit quantity, store it as an integer object. If it
768 * is a multi-string, store it as a list of strings. For null-terminated
769 * strings, append up the to first null. Otherwise, store it as a binary
773 if (type == REG_DWORD || type == REG_DWORD_BIG_ENDIAN) {
774 Tcl_SetIntObj(resultPtr, (int) ConvertDWORD(type,
775 *((DWORD*) Tcl_DStringValue(&data))));
776 } else if (type == REG_MULTI_SZ) {
777 char *p = Tcl_DStringValue(&data);
778 char *end = Tcl_DStringValue(&data) + length;
781 * Multistrings are stored as an array of null-terminated strings,
782 * terminated by two null characters. Also do a bounds check in
783 * case we get bogus data.
786 while (p < end && ((regWinProcs->useWide)
787 ? *((Tcl_UniChar *)p) : *p) != 0) {
788 Tcl_WinTCharToUtf((TCHAR *) p, -1, &buf);
789 Tcl_ListObjAppendElement(interp, resultPtr,
790 Tcl_NewStringObj(Tcl_DStringValue(&buf),
791 Tcl_DStringLength(&buf)));
792 if (regWinProcs->useWide) {
793 while (*((Tcl_UniChar *)p)++ != 0) {}
795 while (*p++ != '\0') {}
797 Tcl_DStringFree(&buf);
799 } else if ((type == REG_SZ) || (type == REG_EXPAND_SZ)) {
800 Tcl_WinTCharToUtf((TCHAR *) Tcl_DStringValue(&data), -1, &buf);
801 Tcl_SetStringObj(resultPtr, Tcl_DStringValue(&buf),
802 Tcl_DStringLength(&buf));
803 Tcl_DStringFree(&buf);
806 * Save binary data as a byte array.
809 Tcl_SetByteArrayObj(resultPtr, Tcl_DStringValue(&data), (int) length);
811 Tcl_DStringFree(&data);
816 *----------------------------------------------------------------------
820 * This function enumerates the values of the a given key. If
821 * the optional pattern is supplied, then only value names that
822 * match the pattern will be returned.
825 * Returns the list of value names in the result object of the
826 * interpreter, or an error message on failure.
831 *----------------------------------------------------------------------
836 Tcl_Interp *interp, /* Current interpreter. */
837 Tcl_Obj *keyNameObj, /* Key to enumerate. */
838 Tcl_Obj *patternObj) /* Optional match pattern. */
842 DWORD index, size, maxSize, result;
843 Tcl_DString buffer, ds;
844 char *pattern, *name;
847 * Attempt to open the key for enumeration.
850 if (OpenKey(interp, keyNameObj, KEY_QUERY_VALUE, 0, &key)
855 resultPtr = Tcl_GetObjResult(interp);
858 * Query the key to determine the appropriate buffer size to hold the
859 * largest value name plus the terminating null.
862 result = (*regWinProcs->regQueryInfoKeyProc)(key, NULL, NULL, NULL, NULL,
863 NULL, NULL, &index, &maxSize, NULL, NULL, NULL);
864 if (result != ERROR_SUCCESS) {
865 Tcl_AppendStringsToObj(resultPtr, "unable to query key \"",
866 Tcl_GetString(keyNameObj), "\": ", NULL);
867 AppendSystemError(interp, result);
875 Tcl_DStringInit(&buffer);
876 Tcl_DStringSetLength(&buffer,
877 (int) ((regWinProcs->useWide) ? maxSize*2 : maxSize));
882 pattern = Tcl_GetString(patternObj);
888 * Enumerate the values under the given subkey until we get an error,
889 * indicating the end of the list. Note that we need to reset size
890 * after each iteration because RegEnumValue smashes the old value.
894 while ((*regWinProcs->regEnumValueProc)(key, index,
895 Tcl_DStringValue(&buffer), &size, NULL, NULL, NULL, NULL)
898 if (regWinProcs->useWide) {
902 Tcl_WinTCharToUtf((TCHAR *) Tcl_DStringValue(&buffer), (int) size, &ds);
903 name = Tcl_DStringValue(&ds);
904 if (!pattern || Tcl_StringMatch(name, pattern)) {
905 result = Tcl_ListObjAppendElement(interp, resultPtr,
906 Tcl_NewStringObj(name, Tcl_DStringLength(&ds)));
907 if (result != TCL_OK) {
908 Tcl_DStringFree(&ds);
912 Tcl_DStringFree(&ds);
917 Tcl_DStringFree(&buffer);
925 *----------------------------------------------------------------------
929 * This function opens the specified key. This function is a
930 * simple wrapper around ParseKeyName and OpenSubKey.
933 * Returns the opened key in the keyPtr argument and a Tcl
939 *----------------------------------------------------------------------
944 Tcl_Interp *interp, /* Current interpreter. */
945 Tcl_Obj *keyNameObj, /* Key to open. */
946 REGSAM mode, /* Access mode. */
947 int flags, /* 0 or REG_CREATE. */
948 HKEY *keyPtr) /* Returned HKEY. */
950 char *keyName, *buffer, *hostName;
955 keyName = Tcl_GetStringFromObj(keyNameObj, &length);
956 buffer = ckalloc((unsigned int) length + 1);
957 strcpy(buffer, keyName);
959 result = ParseKeyName(interp, buffer, &hostName, &rootKey, &keyName);
960 if (result == TCL_OK) {
961 result = OpenSubKey(hostName, rootKey, keyName, mode, flags, keyPtr);
962 if (result != ERROR_SUCCESS) {
963 Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
964 Tcl_AppendToObj(resultPtr, "unable to open key: ", -1);
965 AppendSystemError(interp, result);
977 *----------------------------------------------------------------------
981 * This function opens a given subkey of a root key on the
985 * Returns the opened key in the keyPtr and a Windows error code
986 * as the return value.
991 *----------------------------------------------------------------------
996 char *hostName, /* Host to access, or NULL for local. */
997 HKEY rootKey, /* Root registry key. */
998 char *keyName, /* Subkey name. */
999 REGSAM mode, /* Access mode. */
1000 int flags, /* 0 or REG_CREATE. */
1001 HKEY *keyPtr) /* Returned HKEY. */
1007 * Attempt to open the root key on a remote host if necessary.
1011 hostName = (char *) Tcl_WinUtfToTChar(hostName, -1, &buf);
1012 result = (*regWinProcs->regConnectRegistryProc)(hostName, rootKey,
1014 Tcl_DStringFree(&buf);
1015 if (result != ERROR_SUCCESS) {
1021 * Now open the specified key with the requested permissions. Note
1022 * that this key must be closed by the caller.
1025 keyName = (char *) Tcl_WinUtfToTChar(keyName, -1, &buf);
1026 if (flags & REG_CREATE) {
1028 result = (*regWinProcs->regCreateKeyExProc)(rootKey, keyName, 0, NULL,
1029 REG_OPTION_NON_VOLATILE, mode, NULL, keyPtr, &create);
1031 if (rootKey == HKEY_PERFORMANCE_DATA) {
1033 * Here we fudge it for this special root key.
1034 * See MSDN for more info on HKEY_PERFORMANCE_DATA and
1035 * the peculiarities surrounding it
1037 *keyPtr = HKEY_PERFORMANCE_DATA;
1038 result = ERROR_SUCCESS;
1040 result = (*regWinProcs->regOpenKeyExProc)(rootKey, keyName, 0,
1044 Tcl_DStringFree(&buf);
1047 * Be sure to close the root key since we are done with it now.
1051 RegCloseKey(rootKey);
1057 *----------------------------------------------------------------------
1061 * This function parses a key name into the host, root, and subkey
1065 * The pointers to the start of the host and subkey names are
1066 * returned in the hostNamePtr and keyNamePtr variables. The
1067 * specified root HKEY is returned in rootKeyPtr. Returns
1068 * a standard Tcl result.
1072 * Modifies the name string by inserting nulls.
1074 *----------------------------------------------------------------------
1079 Tcl_Interp *interp, /* Current interpreter. */
1087 Tcl_Obj *rootObj, *resultPtr = Tcl_GetObjResult(interp);
1090 * Split the key into host and root portions.
1093 *hostNamePtr = *keyNamePtr = rootName = NULL;
1094 if (name[0] == '\\') {
1095 if (name[1] == '\\') {
1096 *hostNamePtr = name;
1097 for (rootName = name+2; *rootName != '\0'; rootName++) {
1098 if (*rootName == '\\') {
1108 Tcl_AppendStringsToObj(resultPtr, "bad key \"", name,
1109 "\": must start with a valid root", NULL);
1114 * Split the root into root and subkey portions.
1117 for (*keyNamePtr = rootName; **keyNamePtr != '\0'; (*keyNamePtr)++) {
1118 if (**keyNamePtr == '\\') {
1119 **keyNamePtr = '\0';
1126 * Look for a matching root name.
1129 rootObj = Tcl_NewStringObj(rootName, -1);
1130 result = Tcl_GetIndexFromObj(interp, rootObj, rootKeyNames, "root name",
1132 Tcl_DecrRefCount(rootObj);
1133 if (result != TCL_OK) {
1136 *rootKeyPtr = rootKeys[index];
1141 *----------------------------------------------------------------------
1143 * RecursiveDeleteKey --
1145 * This function recursively deletes all the keys below a starting
1146 * key. Although Windows 95 does this automatically, we still need
1147 * to do this for Windows NT.
1150 * Returns a Windows error code.
1153 * Deletes all of the keys and values below the given key.
1155 *----------------------------------------------------------------------
1160 HKEY startKey, /* Parent of key to be deleted. */
1161 CONST char *keyName) /* Name of key to be deleted in external
1162 * encoding, not UTF. */
1164 DWORD result, size, maxSize;
1169 * Do not allow NULL or empty key name.
1172 if (!keyName || *keyName == '\0') {
1173 return ERROR_BADKEY;
1176 result = (*regWinProcs->regOpenKeyExProc)(startKey, keyName, 0,
1177 KEY_ENUMERATE_SUB_KEYS | DELETE | KEY_QUERY_VALUE, &hKey);
1178 if (result != ERROR_SUCCESS) {
1181 result = (*regWinProcs->regQueryInfoKeyProc)(hKey, NULL, NULL, NULL, NULL,
1182 &maxSize, NULL, NULL, NULL, NULL, NULL, NULL);
1184 if (result != ERROR_SUCCESS) {
1188 Tcl_DStringInit(&subkey);
1189 Tcl_DStringSetLength(&subkey,
1190 (int) ((regWinProcs->useWide) ? maxSize * 2 : maxSize));
1192 while (result == ERROR_SUCCESS) {
1194 * Always get index 0 because key deletion changes ordering.
1198 result=(*regWinProcs->regEnumKeyExProc)(hKey, 0,
1199 Tcl_DStringValue(&subkey), &size, NULL, NULL, NULL, NULL);
1200 if (result == ERROR_NO_MORE_ITEMS) {
1201 result = (*regWinProcs->regDeleteKeyProc)(startKey, keyName);
1203 } else if (result == ERROR_SUCCESS) {
1204 result = RecursiveDeleteKey(hKey, Tcl_DStringValue(&subkey));
1207 Tcl_DStringFree(&subkey);
1213 *----------------------------------------------------------------------
1217 * This function sets the contents of a registry value. If
1218 * the key or value does not exist, it will be created. If it
1219 * does exist, then the data and type will be replaced.
1222 * Returns a normal Tcl result.
1225 * May create new keys or values.
1227 *----------------------------------------------------------------------
1232 Tcl_Interp *interp, /* Current interpreter. */
1233 Tcl_Obj *keyNameObj, /* Name of key. */
1234 Tcl_Obj *valueNameObj, /* Name of value to set. */
1235 Tcl_Obj *dataObj, /* Data to be written. */
1236 Tcl_Obj *typeObj) /* Type of data to be written. */
1243 Tcl_DString nameBuf;
1245 if (typeObj == NULL) {
1247 } else if (Tcl_GetIndexFromObj(interp, typeObj, typeNames, "type",
1248 0, (int *) &type) != TCL_OK) {
1249 if (Tcl_GetIntFromObj(NULL, typeObj, (int*) &type) != TCL_OK) {
1252 Tcl_ResetResult(interp);
1254 if (OpenKey(interp, keyNameObj, KEY_ALL_ACCESS, 1, &key) != TCL_OK) {
1258 valueName = Tcl_GetStringFromObj(valueNameObj, &length);
1259 valueName = (char *) Tcl_WinUtfToTChar(valueName, length, &nameBuf);
1260 resultPtr = Tcl_GetObjResult(interp);
1262 if (type == REG_DWORD || type == REG_DWORD_BIG_ENDIAN) {
1264 if (Tcl_GetIntFromObj(interp, dataObj, (int*) &value) != TCL_OK) {
1266 Tcl_DStringFree(&nameBuf);
1270 value = ConvertDWORD(type, value);
1271 result = (*regWinProcs->regSetValueExProc)(key, valueName, 0, type,
1272 (BYTE*) &value, sizeof(DWORD));
1273 } else if (type == REG_MULTI_SZ) {
1274 Tcl_DString data, buf;
1278 if (Tcl_ListObjGetElements(interp, dataObj, &objc, &objv) != TCL_OK) {
1280 Tcl_DStringFree(&nameBuf);
1285 * Append the elements as null terminated strings. Note that
1286 * we must not assume the length of the string in case there are
1287 * embedded nulls, which aren't allowed in REG_MULTI_SZ values.
1290 Tcl_DStringInit(&data);
1291 for (i = 0; i < objc; i++) {
1292 Tcl_DStringAppend(&data, Tcl_GetString(objv[i]), -1);
1295 * Add a null character to separate this value from the next.
1296 * We accomplish this by growing the string by one byte. Since the
1297 * DString always tacks on an extra null byte, the new byte will
1298 * already be set to null.
1301 Tcl_DStringSetLength(&data, Tcl_DStringLength(&data)+1);
1304 Tcl_WinUtfToTChar(Tcl_DStringValue(&data), Tcl_DStringLength(&data)+1,
1306 result = (*regWinProcs->regSetValueExProc)(key, valueName, 0, type,
1307 (BYTE *) Tcl_DStringValue(&buf),
1308 (DWORD) Tcl_DStringLength(&buf));
1309 Tcl_DStringFree(&data);
1310 Tcl_DStringFree(&buf);
1311 } else if (type == REG_SZ || type == REG_EXPAND_SZ) {
1313 char *data = Tcl_GetStringFromObj(dataObj, &length);
1315 data = (char *) Tcl_WinUtfToTChar(data, length, &buf);
1318 * Include the null in the length, padding if needed for Unicode.
1321 if (regWinProcs->useWide) {
1322 Tcl_DStringSetLength(&buf, Tcl_DStringLength(&buf)+1);
1324 length = Tcl_DStringLength(&buf) + 1;
1326 result = (*regWinProcs->regSetValueExProc)(key, valueName, 0, type,
1327 (BYTE*)data, (DWORD) length);
1328 Tcl_DStringFree(&buf);
1333 * Store binary data in the registry.
1336 data = Tcl_GetByteArrayFromObj(dataObj, &length);
1337 result = (*regWinProcs->regSetValueExProc)(key, valueName, 0, type,
1338 (BYTE *)data, (DWORD) length);
1340 Tcl_DStringFree(&nameBuf);
1342 if (result != ERROR_SUCCESS) {
1343 Tcl_AppendToObj(resultPtr, "unable to set value: ", -1);
1344 AppendSystemError(interp, result);
1351 *----------------------------------------------------------------------
1355 * This function broadcasts a WM_SETTINGCHANGE message to indicate
1356 * to other programs that we have changed the contents of a registry
1360 * Returns a normal Tcl result.
1363 * Will cause other programs to reload their system settings.
1365 *----------------------------------------------------------------------
1370 Tcl_Interp *interp, /* Current interpreter. */
1371 int objc, /* Number of arguments. */
1372 Tcl_Obj * CONST objv[]) /* Argument values. */
1374 LRESULT result, sendResult;
1375 UINT timeout = 3000;
1380 if ((objc != 3) && (objc != 5)) {
1381 Tcl_WrongNumArgs(interp, 2, objv, "keyName ?-timeout millisecs?");
1386 str = Tcl_GetStringFromObj(objv[3], &len);
1387 if ((len < 2) || (*str != '-') || strncmp(str, "-timeout", (size_t) len)) {
1388 Tcl_WrongNumArgs(interp, 2, objv, "keyName ?-timeout millisecs?");
1391 if (Tcl_GetIntFromObj(interp, objv[4], (int *) &timeout) != TCL_OK) {
1396 str = Tcl_GetStringFromObj(objv[2], &len);
1402 * Use the ignore the result.
1404 result = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE,
1405 (WPARAM) 0, (LPARAM) str, SMTO_ABORTIFHUNG, timeout, &sendResult);
1407 objPtr = Tcl_NewObj();
1408 Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewLongObj((long) result));
1409 Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewLongObj((long) sendResult));
1410 Tcl_SetObjResult(interp, objPtr);
1416 *----------------------------------------------------------------------
1418 * AppendSystemError --
1420 * This routine formats a Windows system error message and places
1421 * it into the interpreter result.
1429 *----------------------------------------------------------------------
1434 Tcl_Interp *interp, /* Current interpreter. */
1435 DWORD error) /* Result code from error. */
1440 char id[TCL_INTEGER_SPACE], msgBuf[24 + TCL_INTEGER_SPACE];
1442 Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
1444 length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM
1445 | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error,
1446 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (WCHAR *) &wMsgPtr,
1451 length = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
1452 | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error,
1453 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char *) &msgPtr,
1456 wMsgPtr = (WCHAR *) LocalAlloc(LPTR, (length + 1) * sizeof(WCHAR));
1457 MultiByteToWideChar(CP_ACP, 0, msgPtr, length + 1, wMsgPtr,
1463 if (error == ERROR_CALL_NOT_IMPLEMENTED) {
1464 msg = "function not supported under Win32s";
1466 sprintf(msgBuf, "unknown error: %ld", error);
1470 Tcl_Encoding encoding;
1472 encoding = Tcl_GetEncoding(NULL, "unicode");
1473 Tcl_ExternalToUtfDString(encoding, (char *) wMsgPtr, -1, &ds);
1474 Tcl_FreeEncoding(encoding);
1477 msg = Tcl_DStringValue(&ds);
1478 length = Tcl_DStringLength(&ds);
1481 * Trim the trailing CR/LF from the system message.
1483 if (msg[length-1] == '\n') {
1486 if (msg[length-1] == '\r') {
1491 sprintf(id, "%ld", error);
1492 Tcl_SetErrorCode(interp, "WINDOWS", id, msg, (char *) NULL);
1493 Tcl_AppendToObj(resultPtr, msg, length);
1496 Tcl_DStringFree(&ds);
1501 *----------------------------------------------------------------------
1505 * This function determines whether a DWORD needs to be byte
1506 * swapped, and returns the appropriately swapped value.
1509 * Returns a converted DWORD.
1514 *----------------------------------------------------------------------
1519 DWORD type, /* Either REG_DWORD or REG_DWORD_BIG_ENDIAN */
1520 DWORD value) /* The value to be converted. */
1526 * Check to see if the low bit is in the first byte.
1529 localType = (*((char*)(&order)) == 1) ? REG_DWORD : REG_DWORD_BIG_ENDIAN;
1530 return (type != localType) ? SWAPLONG(value) : value;