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 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 the Enumerating Subkeys section of this topic 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 the Enumerating Data Items section of this topic for details and example code that enumerates data items.

Enumerating Subkeys

The following C++ example uses the EnumKeys method to enumerate the subkeys of the W3SVC key, including all keys for the individual virtual servers on the local machine. This example also uses the Active Template Library (ATL) 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 file. 
#include "iiscnfg.h"  // MD_ & IIS_MD_ #defines header file.
#include "atlBase.h"  // ATL support header file.
  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 bounds 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 specify which data items are to be enumerated when that structure is passed into the EnumData method.

The following C++ 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 code.

#define UNICODE 
#define INITGUID 
#include "iadmw.h"  // COM Interface header file. 
#include "iiscnfg.h"  // MD_ & IIS_MD_ #defines header file.
#include "atlBase.h"  // ATL support header file.
  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 bounds 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;