In this example, the provider handles one dynamic key, under which there are 2 values. This provider will handle both values. The provider is keeping track of the value lengths instead of the registry. Note there is a static number (2) of values under this dynamic key. If the number of values under a dynamic key will change, then the key must be deleted and readded in order to do so.
The path of the dynamic key in this example is HKEY_DYN_DATA\Keyname1\Keyname2. There are two values under this key. One value is called "First Valuename", and the other is called "Second Valuename".
/***************************************************************************** * * (C) Copyright MICROSOFT Corp., 1994-1995 * *****************************************************************************/ #include <vmm.h> #include <vxdwraps.h> #include <vmmreg.h> #define MODULE_NAME "Dynamic Keys example" #define LEN 100 #define DYNKEY_PATH "Keyname1\\Keyname2" // This path is passed to RegCreateDynKey. // The registry will create Keyname1 (if it does not exist) and Keyname2; the provider // will only be queried for values under Keyname2. #define REGVAL_DATA1 "First Valuename" #define REGVAL_DATA2 "Second Valuename" #pragma VxD_PAGEABLE_CODE_SEG #pragma VxD_PAGEABLE_DATA_SEG // Structure for registry value context pointers. // This allows quick return of data for our dynamic registry key. // NOTE: This structure is being used as the value context because this sample has values // with varying lengths. If this were not the case, // PROVIDER_KEEPS_VALUE_LENGTH could be set, and the value pointer // itself used as the value context. typedef struct { PVOID pData; // Pointer to the data PUINT pcbData; // Pointer to the size of the data } REGVAL_CONTEXT, *PREGVAL_CONTEXT; DWORD fData1; DWORD cbfData1 = sizeof(fData1); char szData2[LEN + 1]; unsigned cbData2; // Assign values to data1 and data2. These are of course not normally static // values - they would change dynamically. However, they are being set here in // order to complete this example. fData1= 100; szData2 = "This is the string for the second value"; // declarations used below const REGVAL_CONTEXT rvcData1 = {&fData1, &cbfData1}; const REGVAL_CONTEXT rvcData2 = {szData2, &cbData2}; // RegKeyHandler - The handler function that must be defined in your VxD VMMREGRET __cdecl RegKeyHandler( PVOID pvKeyContext, PVALCONTEXT pValueContext, DWORD cValueContext, PBYTE pbBuffer, DWORD *pcbBuffer, DWORD fFlags) { VMMREGRET status = 0; PVALCONTEXT pvcCurrent; DWORD cbBufRemaining; // Save the input buffer size and initialize the return buffer size assert(pcbBuffer != NULL); cbBufRemaining = *pcbBuffer; *pcbBuffer = 0; // Since this function handles only one key, the key context is unused assert(pvKeyContext == NULL); // Walk the list of requested values, filling them in the buffer if // there's room. for (pvcCurrent = pValueContext; cValueContext > 0; pvcCurrent++, cValueContext--) { PREGVAL_CONTEXT prvcCurrent = pvcCurrent->value_context; pvcCurrent->valuelen = *prvcCurrent->pcbData; if (cbBufRemaining >= (DWORD) pvcCurrent->valuelen) { // value fits, copy it in memcpy(pbBuffer, prvcCurrent->pData, pvcCurrent->valuelen); *pcbBuffer += pvcCurrent->valuelen; pvcCurrent->val_buff_ptr = pbBuffer; ((PBYTE) pbBuffer) += pvcCurrent->valuelen; cbBufRemaining -= pvcCurrent->valuelen; } else { pvcCurrent->val_buff_ptr = NULL; status = ERROR_MORE_DATA; } } return status; } // *** Init code and data is below here *** #pragma VxD_INIT_CODE_SEG #pragma VxD_INIT_DATA_SEG // This structure is used as the 3rd parameter to RegCreateDynKey struct provider_info RegKeyHandlerInfo = { RegKeyHandler, // pointer to the VxD handler function for query of one value RegKeyHandler, // pointer to the VxD handler function for query of multiple values NULL, // Should be NULL for Win95; reserved for future pointer to Win32 handler fn NULL, // Should be NULL for Win95; reserved for future pointer to Win32 handler fn PROVIDER_KEEPS_VALUE_LENGTH, // Provider will keep track of value lengths NULL // Key context; not used in this example since handler only manages 1 key }; // A Pvalue struct that is passed as 4th parameter to RegCreateDynKey PVALUE RegKeyValueInfo[] = { {REGVAL_DATA1, sizeof(DWORD), (PVOID) &rvcData1, REG_BINARY}, {REGVAL_DATA2, 0, (PVOID) &rvcData2, REG_SZ}, }; #define RegKeyValueCount (sizeof(RegKeyValueInfo) / sizeof(*RegKeyValueInfo)) int __stdcall CreateDynamicKey(void) { // Note: We never delete the key VMMHKEY hkeyDynamicConfig; int uStatus; cbData2 = strlen(szData2) + 1; if (uStatus = _RegCreateDynKey(DYNKEY_PATH, NULL, // No key context is needed &RegKeyHandlerInfo, RegKeyValueInfo, RegKeyValueCount, &hkeyDynamicConfig)) { #ifdef DEBUG Out_Debug_String(MODULE_NAME ": Cannot create dynamic registry key " DYNKEY_PATH "\r\n"); #endif return uStatus; } // We're never going to use this key, so we can close it // BUG - The dyn-key code relies on this being kept open, so we leave it open //_RegCloseKey(hkeyDynamicConfig); return 0; }