Enumerating Keys and Data

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.

Enumerating Subkeys

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

Enumerating Data Items

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;