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;
}