📄 tclwinreg.c
字号:
/* * tclWinReg.c -- * * This file contains the implementation of the "registry" Tcl * built-in command. This command is built as a dynamically * loadable extension in a separate DLL. * * Copyright (c) 1997 by Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * 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.20 2003/01/16 19:02:00 mdejong Exp $ */#include <tclPort.h>#include <stdlib.h>/* * 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. */#undef TCL_STORAGE_CLASS#define TCL_STORAGE_CLASS DLLEXPORT/* * The following macros convert between different endian ints. */#define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))#define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))/* * The following flag is used in OpenKeys to indicate that the specified * key should be created if it doesn't currently exist. */#define REG_CREATE 1/* * The following tables contain the mapping from registry root names * to the system predefined keys. */static CONST char *rootKeyNames[] = { "HKEY_LOCAL_MACHINE", "HKEY_USERS", "HKEY_CLASSES_ROOT", "HKEY_CURRENT_USER", "HKEY_CURRENT_CONFIG", "HKEY_PERFORMANCE_DATA", "HKEY_DYN_DATA", NULL};static HKEY rootKeys[] = { HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, HKEY_DYN_DATA};/* * The following table maps from registry types to strings. Note that * the indices for this array are the same as the constants for the * known registry types so we don't need a separate table to hold the * mapping. */static CONST char *typeNames[] = { "none", "sz", "expand_sz", "binary", "dword", "dword_big_endian", "link", "multi_sz", "resource_list", NULL};static DWORD lastType = REG_RESOURCE_LIST;/* * The following structures allow us to select between the Unicode and ASCII * interfaces at run time based on whether Unicode APIs are available. The * Unicode APIs are preferable because they will handle characters outside * of the current code page. */typedef struct RegWinProcs { int useWide; LONG (WINAPI *regConnectRegistryProc)(CONST TCHAR *, HKEY, PHKEY); LONG (WINAPI *regCreateKeyExProc)(HKEY, CONST TCHAR *, DWORD, TCHAR *, DWORD, REGSAM, SECURITY_ATTRIBUTES *, HKEY *, DWORD *); LONG (WINAPI *regDeleteKeyProc)(HKEY, CONST TCHAR *); LONG (WINAPI *regDeleteValueProc)(HKEY, CONST TCHAR *); LONG (WINAPI *regEnumKeyProc)(HKEY, DWORD, TCHAR *, DWORD); LONG (WINAPI *regEnumKeyExProc)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *, TCHAR *, DWORD *, FILETIME *); LONG (WINAPI *regEnumValueProc)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *, DWORD *, BYTE *, DWORD *); LONG (WINAPI *regOpenKeyExProc)(HKEY, CONST TCHAR *, DWORD, REGSAM, HKEY *); LONG (WINAPI *regQueryInfoKeyProc)(HKEY, TCHAR *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, FILETIME *); LONG (WINAPI *regQueryValueExProc)(HKEY, CONST TCHAR *, DWORD *, DWORD *, BYTE *, DWORD *); LONG (WINAPI *regSetValueExProc)(HKEY, CONST TCHAR *, DWORD, DWORD, CONST BYTE*, DWORD);} RegWinProcs;static RegWinProcs *regWinProcs;static RegWinProcs asciiProcs = { 0, (LONG (WINAPI *)(CONST TCHAR *, HKEY, PHKEY)) RegConnectRegistryA, (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, TCHAR *, DWORD, REGSAM, SECURITY_ATTRIBUTES *, HKEY *, DWORD *)) RegCreateKeyExA, (LONG (WINAPI *)(HKEY, CONST TCHAR *)) RegDeleteKeyA, (LONG (WINAPI *)(HKEY, CONST TCHAR *)) RegDeleteValueA, (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD)) RegEnumKeyA, (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *, TCHAR *, DWORD *, FILETIME *)) RegEnumKeyExA, (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *, DWORD *, BYTE *, DWORD *)) RegEnumValueA, (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, REGSAM, HKEY *)) RegOpenKeyExA, (LONG (WINAPI *)(HKEY, TCHAR *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, FILETIME *)) RegQueryInfoKeyA, (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD *, DWORD *, BYTE *, DWORD *)) RegQueryValueExA, (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, DWORD, CONST BYTE*, DWORD)) RegSetValueExA,};static RegWinProcs unicodeProcs = { 1, (LONG (WINAPI *)(CONST TCHAR *, HKEY, PHKEY)) RegConnectRegistryW, (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, TCHAR *, DWORD, REGSAM, SECURITY_ATTRIBUTES *, HKEY *, DWORD *)) RegCreateKeyExW, (LONG (WINAPI *)(HKEY, CONST TCHAR *)) RegDeleteKeyW, (LONG (WINAPI *)(HKEY, CONST TCHAR *)) RegDeleteValueW, (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD)) RegEnumKeyW, (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *, TCHAR *, DWORD *, FILETIME *)) RegEnumKeyExW, (LONG (WINAPI *)(HKEY, DWORD, TCHAR *, DWORD *, DWORD *, DWORD *, BYTE *, DWORD *)) RegEnumValueW, (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, REGSAM, HKEY *)) RegOpenKeyExW, (LONG (WINAPI *)(HKEY, TCHAR *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, DWORD *, FILETIME *)) RegQueryInfoKeyW, (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD *, DWORD *, BYTE *, DWORD *)) RegQueryValueExW, (LONG (WINAPI *)(HKEY, CONST TCHAR *, DWORD, DWORD, CONST BYTE*, DWORD)) RegSetValueExW,};/* * Declarations for functions defined in this file. */static void AppendSystemError(Tcl_Interp *interp, DWORD error);static int BroadcastValue(Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]);static DWORD ConvertDWORD(DWORD type, DWORD value);static int DeleteKey(Tcl_Interp *interp, Tcl_Obj *keyNameObj);static int DeleteValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj, Tcl_Obj *valueNameObj);static int GetKeyNames(Tcl_Interp *interp, Tcl_Obj *keyNameObj, Tcl_Obj *patternObj);static int GetType(Tcl_Interp *interp, Tcl_Obj *keyNameObj, Tcl_Obj *valueNameObj);static int GetValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj, Tcl_Obj *valueNameObj);static int GetValueNames(Tcl_Interp *interp, Tcl_Obj *keyNameObj, Tcl_Obj *patternObj);static int OpenKey(Tcl_Interp *interp, Tcl_Obj *keyNameObj, REGSAM mode, int flags, HKEY *keyPtr);static DWORD OpenSubKey(char *hostName, HKEY rootKey, char *keyName, REGSAM mode, int flags, HKEY *keyPtr);static int ParseKeyName(Tcl_Interp *interp, char *name, char **hostNamePtr, HKEY *rootKeyPtr, char **keyNamePtr);static DWORD RecursiveDeleteKey(HKEY hStartKey, CONST TCHAR * pKeyName);static int RegistryObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]);static int SetValue(Tcl_Interp *interp, Tcl_Obj *keyNameObj, Tcl_Obj *valueNameObj, Tcl_Obj *dataObj, Tcl_Obj *typeObj);EXTERN int Registry_Init(Tcl_Interp *interp);/* *---------------------------------------------------------------------- * * Registry_Init -- * * This procedure initializes the registry command. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */intRegistry_Init( Tcl_Interp *interp){ if (!Tcl_InitStubs(interp, "8.0", 0)) { return TCL_ERROR; } /* * Determine if the unicode interfaces are available and select the * appropriate registry function table. */ if (TclWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { regWinProcs = &unicodeProcs; } else { regWinProcs = &asciiProcs; } Tcl_CreateObjCommand(interp, "registry", RegistryObjCmd, NULL, NULL); return Tcl_PkgProvide(interp, "registry", "1.1");}/* *---------------------------------------------------------------------- * * RegistryObjCmd -- * * This function implements the Tcl "registry" command. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */static intRegistryObjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj * CONST objv[]) /* Argument values. */{ int index; char *errString; static CONST char *subcommands[] = { "broadcast", "delete", "get", "keys", "set", "type", "values", (char *) NULL }; enum SubCmdIdx { BroadcastIdx, DeleteIdx, GetIdx, KeysIdx, SetIdx, TypeIdx, ValuesIdx }; if (objc < 2) { Tcl_WrongNumArgs(interp, objc, objv, "option ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], subcommands, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case BroadcastIdx: /* broadcast */ return BroadcastValue(interp, objc, objv); break; case DeleteIdx: /* delete */ if (objc == 3) { return DeleteKey(interp, objv[2]); } else if (objc == 4) { return DeleteValue(interp, objv[2], objv[3]); } errString = "keyName ?valueName?"; break; case GetIdx: /* get */ if (objc == 4) { return GetValue(interp, objv[2], objv[3]); } errString = "keyName valueName"; break; case KeysIdx: /* keys */ if (objc == 3) { return GetKeyNames(interp, objv[2], NULL); } else if (objc == 4) { return GetKeyNames(interp, objv[2], objv[3]); } errString = "keyName ?pattern?"; break; case SetIdx: /* set */ if (objc == 3) { HKEY key; /* * Create the key and then close it immediately. */ if (OpenKey(interp, objv[2], KEY_ALL_ACCESS, 1, &key) != TCL_OK) { return TCL_ERROR; } RegCloseKey(key); return TCL_OK; } else if (objc == 5 || objc == 6) { Tcl_Obj *typeObj = (objc == 5) ? NULL : objv[5]; return SetValue(interp, objv[2], objv[3], objv[4], typeObj); } errString = "keyName ?valueName data ?type??"; break; case TypeIdx: /* type */ if (objc == 4) { return GetType(interp, objv[2], objv[3]); } errString = "keyName valueName"; break; case ValuesIdx: /* values */ if (objc == 3) { return GetValueNames(interp, objv[2], NULL); } else if (objc == 4) { return GetValueNames(interp, objv[2], objv[3]); } errString = "keyName ?pattern?"; break; } Tcl_WrongNumArgs(interp, 2, objv, errString); return TCL_ERROR;}/* *---------------------------------------------------------------------- * * DeleteKey -- * * This function deletes a registry key. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */static intDeleteKey( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *keyNameObj) /* Name of key to delete. */{ char *tail, *buffer, *hostName, *keyName; CONST char *nativeTail; HKEY rootKey, subkey; DWORD result; int length; Tcl_Obj *resultPtr; Tcl_DString buf; /* * Find the parent of the key being deleted and open it. */ keyName = Tcl_GetStringFromObj(keyNameObj, &length); buffer = ckalloc((unsigned int) length + 1); strcpy(buffer, keyName); if (ParseKeyName(interp, buffer, &hostName, &rootKey, &keyName) != TCL_OK) { ckfree(buffer); return TCL_ERROR; } resultPtr = Tcl_GetObjResult(interp); if (*keyName == '\0') { Tcl_AppendToObj(resultPtr, "bad key: cannot delete root keys", -1); ckfree(buffer); return TCL_ERROR; } tail = strrchr(keyName, '\\'); if (tail) { *tail++ = '\0'; } else { tail = keyName; keyName = NULL; } result = OpenSubKey(hostName, rootKey, keyName, KEY_ENUMERATE_SUB_KEYS | DELETE, 0, &subkey); if (result != ERROR_SUCCESS) { ckfree(buffer); if (result == ERROR_FILE_NOT_FOUND) { return TCL_OK; } else { Tcl_AppendToObj(resultPtr, "unable to delete key: ", -1); AppendSystemError(interp, result); return TCL_ERROR; } } /* * Now we recursively delete the key and everything below it. */ nativeTail = Tcl_WinUtfToTChar(tail, -1, &buf); result = RecursiveDeleteKey(subkey, nativeTail); Tcl_DStringFree(&buf); if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { Tcl_AppendToObj(resultPtr, "unable to delete key: ", -1); AppendSystemError(interp, result); result = TCL_ERROR; } else { result = TCL_OK; } RegCloseKey(subkey); ckfree(buffer); return result;}/* *---------------------------------------------------------------------- * * DeleteValue -- * * This function deletes a value from a registry key. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */static intDeleteValue( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *keyNameObj, /* Name of key. */ Tcl_Obj *valueNameObj) /* Name of value to delete. */{ HKEY key; char *valueName; int length; DWORD result; Tcl_Obj *resultPtr; Tcl_DString ds; /* * Attempt to open the key for deletion. */ if (OpenKey(interp, keyNameObj, KEY_SET_VALUE, 0, &key) != TCL_OK) { return TCL_ERROR; } resultPtr = Tcl_GetObjResult(interp); valueName = Tcl_GetStringFromObj(valueNameObj, &length); Tcl_WinUtfToTChar(valueName, length, &ds); result = (*regWinProcs->regDeleteValueProc)(key, Tcl_DStringValue(&ds)); Tcl_DStringFree(&ds); if (result != ERROR_SUCCESS) { Tcl_AppendStringsToObj(resultPtr, "unable to delete value \"", Tcl_GetString(valueNameObj), "\" from key \"", Tcl_GetString(keyNameObj), "\": ", NULL); AppendSystemError(interp, result); result = TCL_ERROR; } else { result = TCL_OK; } RegCloseKey(key); return result;}/* *---------------------------------------------------------------------- * * GetKeyNames -- * * This function enumerates the subkeys of a given key. If the * optional pattern is supplied, then only keys that match the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -