You can use the EnumKeys method to enumerate the subkeys of a key. The name of one subkey is returned per each enumeration call. ERROR_NO_MORE_ITEMS is returned after the last subkey has been enumerated. To get a total count of the subkeys associated with a key, you can increment the index parameter of the method. See Enumerating Subkeys for details and example code that enumerates keys.
Similarly, you can use the EnumData method to enumerate the data elements of a key. One data item is enumerated per call, but unlike enumerating keys, the EnumData method returns the data as well as the data identifier. ERROR_NO_MORE_ITEMS is returned after the last data item has been enumerated. To get a total count of the data items associated with a key, you must increment the index parameter of the method. See Enumerating Data Items for details and example code that enumerates data items.
The following example uses the EnumKeys method to enumerate the number of virtual Web servers defined on the local machine. This example also uses the Active Template Library to demonstrate smart pointers. Smart pointers perform the normal COM QueryInterface, AddRef and Release calls automatically.
#define UNICODE
#define INITGUID
#include "iadmw.h" // COM Interface header
#include "iiscnfg.h" // MD_ & IIS_MD_ #defines
#include "atlBase.h" // ATL support
HRESULT hRes = 0;
DWORD indx = 0;
METADATA_HANDLE MyHandle;
WCHAR SubKeyName[METADATA_MAX_NAME_LEN];
CComPtr <IMSAdminBase> pIMeta;
hRes = CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL,
IID_IMSAdminBase, (void **) &pIMeta);
if (FAILED(hRes))
return;
//get a handle to the local machine
hRes = pIMeta->OpenKey(METADATA_MASTER_ROOT_HANDLE, TEXT("/LM"), METADATA_PERMISSION_READ, 20, &MyHandle);
//loop until there are no more subkeys
while (SUCCEEDED(hRes)){
//enumerate the subkeys of the World Wide Web service
hRes = pIMeta->EnumKeys(MyHandle, TEXT("/W3SVC"), SubKeyName, indx);
if (SUCCEEDED(hRes)) {
//store the virtual server names in an array for future use
//Note: declare a suitable array of names and add
// array bound checking
wcscpy (names[indx],SubKeyName);
}
//increment the index
indx++;
}
//release the handle
pIMeta->CloseKey(MyHandle);
The EnumData method returns the entire data entry, so you must pass in a METADATA_RECORD structure to receive the data. The values that are set for the METADATA_RECORD members when that structure is passed into the EnumData method specify which data items are to be enumerated.
The following example enumerates all of the server-related data entries of the first virtual Web server, including any inherited data. This is an example only, and does not include all appropriate error handling.
#define UNICODE
#define INITGUID
#include "iadmw.h" // COM Interface header
#include "iiscnfg.h" // MD_ & IIS_MD_ #defines
#include "atlBase.h" // ATL support
HRESULT hRes = 0;
DWORD indx = 0;
METADATA_HANDLE MyHandle;
METADATA_RECORD MyRecord;
DWORD dwBufLen = ORIGINAL_BUFFER_SIZE;
DWORD dwReqBufLen = 0;
PBYTE pbBuffer = new BYTE[dwBufLen];
CComPtr <IMSAdminBase> pIMeta;
hRes = CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL,
IID_IMSAdminBase, (void **) &pIMeta);
if (FAILED(hRes))
return;
//get a handle to the Web service
hRes = pIMeta->OpenKey(METADATA_MASTER_ROOT_HANDLE, TEXT("/LM/W3SVC"), METADATA_PERMISSION_READ, 20, &MyHandle);
if (SUCCEEDED(hRes)) {
//loop until there are no more data items
while (SUCCEEDED(hRes)){
//initialize the input structure,
//the values specify what kind of data to enumerate
MyRecord.dwMDAttributes = METADATA_INHERIT;
MyRecord.dwMDUserType = IIS_MD_UT_SERVER;
MyRecord.dwMDDataType = ALL_METADATA;
MyRecord.dwMDDataLen = dwBufLen;
MyRecord.pbMDData = pbBuffer;
//enumerate the data of the first virtual Web server
//checking to ensure that the data returned does not
//overflow the buffer
hRes = pIMeta->EnumData(MyHandle, TEXT("/1"), &MyRecord, indx, &dwReqBufLen);
if (hres == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER)) {
delete [] (pbBuffer);
pbBuffer = new BYTE[dwReqBufLen];
dwBufLen = dwReqBufLen;
MyRecord->dwMDDataLen = dwReqBufLen;
MyRecord->pbMDData = pbBuffer;
hRes = pIMeta->EnumData(MyHandle, TEXT("/1"), &MyRecord, indx, &dwReqBufLen);
}
if (SUCCEEDED(hRes)) {
//store the data identifiers in an array for future use
//Note: declare a suitable DWORD array for names and add
// array bound checking
data[indx] = MyRecord->dwMDIdentifier;
// Additional code needed to store other data fields.
}
//increment the index
indx++;
} // end while
//release the handle and buffer
pIMeta->CloseKey(MyHandle);
} // end if pIMeta->OpenKey Succeeded
delete pbBuffer;