📄 tclwinreg.c
字号:
* * 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; /* * Attempt to open the root key on a remote host if necessary. */ if (hostName) { result = RegConnectRegistry(hostName, rootKey, &rootKey); 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. */ if (flags & REG_CREATE) { DWORD create; result = RegCreateKeyEx(rootKey, keyName, 0, "", REG_OPTION_NON_VOLATILE, mode, NULL, keyPtr, &create); } else { result = RegOpenKeyEx(rootKey, keyName, 0, mode, keyPtr); } /* * Be sure to close the root key since we are done with it now. */ if (hostName) { RegCloseKey(rootKey); } return result; }/* *---------------------------------------------------------------------- * * ParseKeyName -- * * This function parses a key name into the host, root, and subkey * parts. * * Results: * The pointers to the start of the host and subkey names are * returned in the hostNamePtr and keyNamePtr variables. The * specified root HKEY is returned in rootKeyPtr. Returns * a standard Tcl result. * * * Side effects: * Modifies the name string by inserting nulls. * *---------------------------------------------------------------------- */static intParseKeyName( Tcl_Interp *interp, /* Current interpreter. */ char *name, char **hostNamePtr, HKEY *rootKeyPtr, char **keyNamePtr){ char *rootName; int result, index; Tcl_Obj *rootObj, *resultPtr = Tcl_GetObjResult(interp); /* * Split the key into host and root portions. */ *hostNamePtr = *keyNamePtr = rootName = NULL; if (name[0] == '\\') { if (name[1] == '\\') { *hostNamePtr = name; for (rootName = name+2; *rootName != '\0'; rootName++) { if (*rootName == '\\') { *rootName++ = '\0'; break; } } } } else { rootName = name; } if (!rootName) { Tcl_AppendStringsToObj(resultPtr, "bad key \"", name, "\": must start with a valid root", NULL); return TCL_ERROR; } /* * Split the root into root and subkey portions. */ for (*keyNamePtr = rootName; **keyNamePtr != '\0'; (*keyNamePtr)++) { if (**keyNamePtr == '\\') { **keyNamePtr = '\0'; (*keyNamePtr)++; break; } } /* * Look for a matching root name. */ rootObj = Tcl_NewStringObj(rootName, -1); result = Tcl_GetIndexFromObj(interp, rootObj, rootKeyNames, "root name", TCL_EXACT, &index); Tcl_DecrRefCount(rootObj); if (result != TCL_OK) { return TCL_ERROR; } *rootKeyPtr = rootKeys[index]; return TCL_OK;}/* *---------------------------------------------------------------------- * * RecursiveDeleteKey -- * * This function recursively deletes all the keys below a starting * key. Although Windows 95 does this automatically, we still need * to do this for Windows NT. * * Results: * Returns a Windows error code. * * Side effects: * Deletes all of the keys and values below the given key. * *---------------------------------------------------------------------- */static DWORDRecursiveDeleteKey( HKEY startKey, /* Parent of key to be deleted. */ char *keyName) /* Name of key to be deleted. */{ DWORD result, subKeyLength; Tcl_DString subkey; HKEY hKey; /* * Do not allow NULL or empty key name. */ if (!keyName || lstrlen(keyName) == '\0') { return ERROR_BADKEY; } result = RegOpenKeyEx(startKey, keyName, 0, KEY_ENUMERATE_SUB_KEYS | DELETE | KEY_QUERY_VALUE, &hKey); if (result != ERROR_SUCCESS) { return result; } result = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, &subKeyLength, NULL, NULL, NULL, NULL, NULL, NULL); subKeyLength++; if (result != ERROR_SUCCESS) { return result; } Tcl_DStringInit(&subkey); Tcl_DStringSetLength(&subkey, subKeyLength); while (result == ERROR_SUCCESS) { /* * Always get index 0 because key deletion changes ordering. */ subKeyLength = Tcl_DStringLength(&subkey); result=RegEnumKeyEx(hKey, 0, Tcl_DStringValue(&subkey), &subKeyLength, NULL, NULL, NULL, NULL); if (result == ERROR_NO_MORE_ITEMS) { result = RegDeleteKey(startKey, keyName); break; } else if (result == ERROR_SUCCESS) { result = RecursiveDeleteKey(hKey, Tcl_DStringValue(&subkey)); } } Tcl_DStringFree(&subkey); RegCloseKey(hKey); return result;}/* *---------------------------------------------------------------------- * * SetValue -- * * This function sets the contents of a registry value. If * the key or value does not exist, it will be created. If it * does exist, then the data and type will be replaced. * * Results: * Returns a normal Tcl result. * * Side effects: * May create new keys or values. * *---------------------------------------------------------------------- */static intSetValue( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *keyNameObj, /* Name of key. */ Tcl_Obj *valueNameObj, /* Name of value to set. */ Tcl_Obj *dataObj, /* Data to be written. */ Tcl_Obj *typeObj) /* Type of data to be written. */{ DWORD type, result; HKEY key; int length; char *valueName; Tcl_Obj *resultPtr; if (typeObj == NULL) { type = REG_SZ; } else if (Tcl_GetIndexFromObj(interp, typeObj, typeNames, "type", 0, (int *) &type) != TCL_OK) { if (Tcl_GetIntFromObj(NULL, typeObj, (int*) &type) != TCL_OK) { return TCL_ERROR; } Tcl_ResetResult(interp); } if (OpenKey(interp, keyNameObj, KEY_ALL_ACCESS, 1, &key) != TCL_OK) { return TCL_ERROR; } valueName = Tcl_GetStringFromObj(valueNameObj, &length); resultPtr = Tcl_GetObjResult(interp); if (type == REG_DWORD || type == REG_DWORD_BIG_ENDIAN) { DWORD value; if (Tcl_GetIntFromObj(interp, dataObj, (int*) &value) != TCL_OK) { RegCloseKey(key); return TCL_ERROR; } value = ConvertDWORD(type, value); result = RegSetValueEx(key, valueName, 0, type, (BYTE*) &value, sizeof(DWORD)); } else if (type == REG_MULTI_SZ) { Tcl_DString data; int objc, i; Tcl_Obj **objv; char *element; if (Tcl_ListObjGetElements(interp, dataObj, &objc, &objv) != TCL_OK) { RegCloseKey(key); return TCL_ERROR; } /* * Append the elements as null terminated strings. Note that * we must not assume the length of the string in case there are * embedded nulls, which aren't allowed in REG_MULTI_SZ values. */ Tcl_DStringInit(&data); for (i = 0; i < objc; i++) { element = Tcl_GetStringFromObj(objv[i], NULL); Tcl_DStringAppend(&data, element, -1); Tcl_DStringSetLength(&data, Tcl_DStringLength(&data)+1); } result = RegSetValueEx(key, valueName, 0, type, (LPBYTE) Tcl_DStringValue(&data), (DWORD) (Tcl_DStringLength(&data)+1)); Tcl_DStringFree(&data); } else { char *data = Tcl_GetStringFromObj(dataObj, &length); /* * Include the null in the length if we are storing a null terminated * string. Note that we also need to call strlen to find the first * null so we don't pass bad data to the registry. */ if (type == REG_SZ || type == REG_EXPAND_SZ) { length = strlen(data) + 1; } result = RegSetValueEx(key, valueName, 0, type, (LPBYTE)data, length); } RegCloseKey(key); if (result != ERROR_SUCCESS) { Tcl_AppendToObj(resultPtr, "unable to set value: ", -1); AppendSystemError(interp, result); return TCL_ERROR; } return TCL_OK;}/* *---------------------------------------------------------------------- * * AppendSystemError -- * * This routine formats a Windows system error message and places * it into the interpreter result. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */static voidAppendSystemError( Tcl_Interp *interp, /* Current interpreter. */ DWORD error) /* Result code from error. */{ int length; char *msgbuf, id[10]; Tcl_Obj *resultPtr = Tcl_GetObjResult(interp); sprintf(id, "%d", error); length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&msgbuf, 0, NULL); if (length == 0) { if (error == ERROR_CALL_NOT_IMPLEMENTED) { msgbuf = "function not supported under Win32s"; } else { msgbuf = id; } } else { /* * Trim the trailing CR/LF from the system message. */ if (msgbuf[length-1] == '\n') { msgbuf[--length] = 0; } if (msgbuf[length-1] == '\r') { msgbuf[--length] = 0; } } Tcl_SetErrorCode(interp, "WINDOWS", id, msgbuf, (char *) NULL); Tcl_AppendToObj(resultPtr, msgbuf, -1); if (length != 0) { LocalFree(msgbuf); }}/* *---------------------------------------------------------------------- * * ConvertDWORD -- * * This function determines whether a DWORD needs to be byte * swapped, and returns the appropriately swapped value. * * Results: * Returns a converted DWORD. * * Side effects: * None. * *---------------------------------------------------------------------- */static DWORDConvertDWORD( DWORD type, /* Either REG_DWORD or REG_DWORD_BIG_ENDIAN */ DWORD value) /* The value to be converted. */{ DWORD order = 1; DWORD localType; /* * Check to see if the low bit is in the first byte. */ localType = (*((char*)(&order)) == 1) ? REG_DWORD : REG_DWORD_BIG_ENDIAN; return (type != localType) ? SWAPLONG(value) : value;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -