📄 tclwinreg.c
字号:
* pattern will be returned. * * Results: * Returns the list of subkeys in the result object of the * interpreter, or an error message on failure. * * Side effects: * None. * *---------------------------------------------------------------------- */static intGetKeyNames( Tcl_Interp *interp, /* Current interpreter. */ 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; } if (patternObj) { pattern = Tcl_GetString(patternObj); } else { pattern = NULL; } /* * Enumerate over the subkeys until we get an error, indicating the * end of the list. */ resultPtr = Tcl_GetObjResult(interp); for (index = 0; (*regWinProcs->regEnumKeyProc)(key, index, buffer, MAX_PATH+1) == ERROR_SUCCESS; index++) { Tcl_WinTCharToUtf((TCHAR *) buffer, -1, &ds); name = Tcl_DStringValue(&ds); if (pattern && !Tcl_StringMatch(name, pattern)) { Tcl_DStringFree(&ds); continue; } result = Tcl_ListObjAppendElement(interp, resultPtr, Tcl_NewStringObj(name, Tcl_DStringLength(&ds))); Tcl_DStringFree(&ds); if (result != TCL_OK) { break; } } RegCloseKey(key); return result;}/* *---------------------------------------------------------------------- * * GetType -- * * This function gets the type of a given registry value and * places it in the interpreter result. * * Results: * Returns a normal Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */static intGetType( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *keyNameObj, /* Name of key. */ Tcl_Obj *valueNameObj) /* Name of value to get. */{ HKEY key; Tcl_Obj *resultPtr; DWORD result; DWORD type; Tcl_DString ds; char *valueName; CONST char *nativeValue; int length; /* * Attempt to open the key for reading. */ if (OpenKey(interp, keyNameObj, KEY_QUERY_VALUE, 0, &key) != TCL_OK) { return TCL_ERROR; } /* * Get the type of the value. */ resultPtr = Tcl_GetObjResult(interp); valueName = Tcl_GetStringFromObj(valueNameObj, &length); nativeValue = Tcl_WinUtfToTChar(valueName, length, &ds); result = (*regWinProcs->regQueryValueExProc)(key, nativeValue, NULL, &type, NULL, NULL); Tcl_DStringFree(&ds); RegCloseKey(key); if (result != ERROR_SUCCESS) { Tcl_AppendStringsToObj(resultPtr, "unable to get type of value \"", Tcl_GetString(valueNameObj), "\" from key \"", Tcl_GetString(keyNameObj), "\": ", NULL); AppendSystemError(interp, result); return TCL_ERROR; } /* * Set the type into the result. Watch out for unknown types. * If we don't know about the type, just use the numeric value. */ if (type > lastType || type < 0) { Tcl_SetIntObj(resultPtr, (int) type); } else { Tcl_SetStringObj(resultPtr, typeNames[type], -1); } return TCL_OK;}/* *---------------------------------------------------------------------- * * GetValue -- * * This function gets the contents of a registry value and places * a list containing the data and the type in the interpreter * result. * * Results: * Returns a normal Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */static intGetValue( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *keyNameObj, /* Name of key. */ Tcl_Obj *valueNameObj) /* Name of value to get. */{ HKEY key; char *valueName; CONST char *nativeValue; DWORD result, length, type; Tcl_Obj *resultPtr; Tcl_DString data, buf; int nameLen; /* * Attempt to open the key for reading. */ if (OpenKey(interp, keyNameObj, KEY_QUERY_VALUE, 0, &key) != TCL_OK) { return TCL_ERROR; } /* * Initialize a Dstring to maximum statically allocated size * we could get one more byte by avoiding Tcl_DStringSetLength() * and just setting length to TCL_DSTRING_STATIC_SIZE, but this * should be safer if the implementation of Dstrings changes. * * This allows short values to be read from the registy in one call. * Longer values need a second call with an expanded DString. */ Tcl_DStringInit(&data); length = TCL_DSTRING_STATIC_SIZE - 1; Tcl_DStringSetLength(&data, (int) length); resultPtr = Tcl_GetObjResult(interp); valueName = Tcl_GetStringFromObj(valueNameObj, &nameLen); nativeValue = Tcl_WinUtfToTChar(valueName, nameLen, &buf); result = (*regWinProcs->regQueryValueExProc)(key, nativeValue, NULL, &type, (BYTE *) Tcl_DStringValue(&data), &length); while (result == ERROR_MORE_DATA) { /* * The Windows docs say that in this error case, we just need * to expand our buffer and request more data. * Required for HKEY_PERFORMANCE_DATA */ length *= 2; Tcl_DStringSetLength(&data, (int) length); result = (*regWinProcs->regQueryValueExProc)(key, (char *) nativeValue, NULL, &type, (BYTE *) Tcl_DStringValue(&data), &length); } Tcl_DStringFree(&buf); RegCloseKey(key); if (result != ERROR_SUCCESS) { Tcl_AppendStringsToObj(resultPtr, "unable to get value \"", Tcl_GetString(valueNameObj), "\" from key \"", Tcl_GetString(keyNameObj), "\": ", NULL); AppendSystemError(interp, result); Tcl_DStringFree(&data); return TCL_ERROR; } /* * If the data is a 32-bit quantity, store it as an integer object. If it * is a multi-string, store it as a list of strings. For null-terminated * strings, append up the to first null. Otherwise, store it as a binary * string. */ if (type == REG_DWORD || type == REG_DWORD_BIG_ENDIAN) { Tcl_SetIntObj(resultPtr, (int) ConvertDWORD(type, *((DWORD*) Tcl_DStringValue(&data)))); } else if (type == REG_MULTI_SZ) { char *p = Tcl_DStringValue(&data); char *end = Tcl_DStringValue(&data) + length; /* * Multistrings are stored as an array of null-terminated strings, * terminated by two null characters. Also do a bounds check in * case we get bogus data. */ while (p < end && ((regWinProcs->useWide) ? *((Tcl_UniChar *)p) : *p) != 0) { Tcl_WinTCharToUtf((TCHAR *) p, -1, &buf); Tcl_ListObjAppendElement(interp, resultPtr, Tcl_NewStringObj(Tcl_DStringValue(&buf), Tcl_DStringLength(&buf))); if (regWinProcs->useWide) { while (*((Tcl_UniChar *)p)++ != 0) {} } else { while (*p++ != '\0') {} } Tcl_DStringFree(&buf); } } else if ((type == REG_SZ) || (type == REG_EXPAND_SZ)) { Tcl_WinTCharToUtf((TCHAR *) Tcl_DStringValue(&data), -1, &buf); Tcl_SetStringObj(resultPtr, Tcl_DStringValue(&buf), Tcl_DStringLength(&buf)); Tcl_DStringFree(&buf); } else { /* * Save binary data as a byte array. */ Tcl_SetByteArrayObj(resultPtr, Tcl_DStringValue(&data), (int) length); } Tcl_DStringFree(&data); return result;}/* *---------------------------------------------------------------------- * * GetValueNames -- * * This function enumerates the values of the a given key. If * the optional pattern is supplied, then only value names that * match the pattern will be returned. * * Results: * Returns the list of value names in the result object of the * interpreter, or an error message on failure. * * Side effects: * None. * *---------------------------------------------------------------------- */static intGetValueNames( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *keyNameObj, /* Key to enumerate. */ Tcl_Obj *patternObj) /* Optional match pattern. */{ HKEY key; Tcl_Obj *resultPtr; DWORD index, size, maxSize, result; Tcl_DString buffer, ds; char *pattern, *name; /* * Attempt to open the key for enumeration. */ if (OpenKey(interp, keyNameObj, KEY_QUERY_VALUE, 0, &key) != TCL_OK) { return TCL_ERROR; } resultPtr = Tcl_GetObjResult(interp); /* * Query the key to determine the appropriate buffer size to hold the * largest value name plus the terminating null. */ result = (*regWinProcs->regQueryInfoKeyProc)(key, NULL, NULL, NULL, NULL, NULL, NULL, &index, &maxSize, NULL, NULL, NULL); if (result != ERROR_SUCCESS) { Tcl_AppendStringsToObj(resultPtr, "unable to query key \"", Tcl_GetString(keyNameObj), "\": ", NULL); AppendSystemError(interp, result); RegCloseKey(key); result = TCL_ERROR; goto done; } maxSize++; Tcl_DStringInit(&buffer); Tcl_DStringSetLength(&buffer, (int) ((regWinProcs->useWide) ? maxSize*2 : maxSize)); index = 0; result = TCL_OK; if (patternObj) { pattern = Tcl_GetString(patternObj); } else { pattern = NULL; } /* * Enumerate the values under the given subkey until we get an error, * indicating the end of the list. Note that we need to reset size * after each iteration because RegEnumValue smashes the old value. */ size = maxSize; while ((*regWinProcs->regEnumValueProc)(key, index, Tcl_DStringValue(&buffer), &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { if (regWinProcs->useWide) { size *= 2; } Tcl_WinTCharToUtf((TCHAR *) Tcl_DStringValue(&buffer), (int) size, &ds); name = Tcl_DStringValue(&ds); if (!pattern || Tcl_StringMatch(name, pattern)) { result = Tcl_ListObjAppendElement(interp, resultPtr, Tcl_NewStringObj(name, Tcl_DStringLength(&ds))); if (result != TCL_OK) { Tcl_DStringFree(&ds); break; } } Tcl_DStringFree(&ds); index++; size = maxSize; } Tcl_DStringFree(&buffer); done: RegCloseKey(key); return result;}/* *---------------------------------------------------------------------- * * OpenKey -- * * This function opens the specified key. This function is a * simple wrapper around ParseKeyName and OpenSubKey. * * Results: * Returns the opened key in the keyPtr argument and a Tcl * result code. * * Side effects: * None. * *---------------------------------------------------------------------- */static intOpenKey( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *keyNameObj, /* Key to open. */ REGSAM mode, /* Access mode. */ int flags, /* 0 or REG_CREATE. */ HKEY *keyPtr) /* Returned HKEY. */{ char *keyName, *buffer, *hostName; int length; HKEY rootKey; DWORD result; keyName = Tcl_GetStringFromObj(keyNameObj, &length); buffer = ckalloc((unsigned int) length + 1); strcpy(buffer, keyName); result = ParseKeyName(interp, buffer, &hostName, &rootKey, &keyName); if (result == TCL_OK) { result = OpenSubKey(hostName, rootKey, keyName, mode, flags, keyPtr); if (result != ERROR_SUCCESS) { Tcl_Obj *resultPtr = Tcl_GetObjResult(interp); Tcl_AppendToObj(resultPtr, "unable to open key: ", -1); AppendSystemError(interp, result); result = TCL_ERROR; } else { result = TCL_OK; } } ckfree(buffer); return result;}/* *---------------------------------------------------------------------- * * OpenSubKey -- * * This function opens a given subkey of a root key on the * specified host. * * Results: * Returns the opened key in the keyPtr and a Windows error code * as the return value. * * Side effects: * None. * *---------------------------------------------------------------------- */static DWORDOpenSubKey( char *hostName, /* Host to access, or NULL for local. */ HKEY rootKey, /* Root registry key. */ char *keyName, /* Subkey name. */ REGSAM mode, /* Access mode. */ int flags, /* 0 or REG_CREATE. */ HKEY *keyPtr) /* Returned HKEY. */{ DWORD result; Tcl_DString buf; /* * Attempt to open the root key on a remote host if necessary. */ if (hostName) { hostName = (char *) Tcl_WinUtfToTChar(hostName, -1, &buf); result = (*regWinProcs->regConnectRegistryProc)(hostName, rootKey, &rootKey); Tcl_DStringFree(&buf); if (result != ERROR_SUCCESS) { return result; } } /* * Now open the specified key with the requested permissions. Note * that this key must be closed by the caller. */ keyName = (char *) Tcl_WinUtfToTChar(keyName, -1, &buf); if (flags & REG_CREATE) { DWORD create; result = (*regWinProcs->regCreateKeyExProc)(rootKey, keyName, 0, "", REG_OPTION_NON_VOLATILE, mode, NULL, keyPtr, &create); } else { if (rootKey == HKEY_PERFORMANCE_DATA) { /* * Here we fudge it for this special root key. * See MSDN for more info on HKEY_PERFORMANCE_DATA and * the peculiarities surrounding it */ *keyPtr = HKEY_PERFORMANCE_DATA;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -