// ************************************************************************** // // Copyright (c) 2001 Microsoft Corporation, All Rights Reserved // // File: PathParser.cpp // // Description: // WMI Path Parser Sample. // This sample shows how to use the Path Parser. It takes a path as a command // line argument and passes it off to the parser to be parsed and then uses various // functions to get pieces of the path. // // History: // // ************************************************************************** #include #include #include #include #include //*************************************************************************** // // DumpServerName // // Purpose: Dumps the server name // //*************************************************************************** void DumpServerName(IWbemPath * pParser) { HRESULT hr; // One could safely assume a maximum server name, but for the sake of example, // the code will call GetServer in order to determine how long of name is needed, then // do the allocation, then get the name and finally dump it. DWORD dwSize = 0; hr = pParser->GetServer(&dwSize, NULL); if(FAILED(hr) || dwSize == 0) return; // nothing here, just return WCHAR * pServer = new WCHAR[dwSize]; if(pServer) { hr = pParser->GetServer(&dwSize, pServer); if(FAILED(hr)) printf("\nUnexpected failure, hr = 0x%x", hr); else printf("\nThe server name is <%S>", pServer); delete [] pServer; } } //*************************************************************************** // // DumpNamespaces // // Purpose: Dumps the name spaces // //*************************************************************************** void DumpNamespaces(IWbemPath * pParser) { HRESULT hr; // first get the number of namespaces ULONG lCnt; hr = pParser->GetNamespaceCount(&lCnt); if(FAILED(hr)) { printf("\nGetNamespaceCount failed, hr = 0x%x", hr); return; } for(ULONG dwCnt = 0; dwCnt < lCnt; dwCnt++) { if(dwCnt == 0) printf("\nNamespaces="); else printf(","); // first determine the necessary buffer size DWORD dwSize = 0; hr = pParser->GetNamespaceAt(dwCnt, &dwSize, NULL); if(FAILED(hr) || dwSize == 0) { printf("\nGetNamespaceAt failed, hr = 0x%x", hr); return; } WCHAR * pNamespace = new WCHAR[dwSize]; if(pNamespace) { hr = pParser->GetNamespaceAt(dwCnt, &dwSize, pNamespace); if(FAILED(hr)) printf("\nGetNamespaceAt failed for index %d, sc = 0x%x", dwCnt, hr); else printf("%S", pNamespace); delete [] pNamespace; } } } //*************************************************************************** // // DumpClassName // // Purpose: Dumps the class name // //*************************************************************************** void DumpClassName(IWbemPath * pParser) { HRESULT hr; // One could safely assume a maximum class name, but for the sake of example, // the code will call GetClassName in order to determine how long of name is needed, then // do the allocation, then get the name and finally dump it. DWORD dwSize = 0; hr = pParser->GetClassName(&dwSize, NULL); if(FAILED(hr) || dwSize == 0) return; // nothing here, just return WCHAR * pClassName = new WCHAR[dwSize]; if(pClassName) { hr = pParser->GetClassName(&dwSize, pClassName); if(FAILED(hr)) printf("\nUnexpected failure, hr = 0x%x", hr); else printf("\nThe class name is <%S>", pClassName); delete [] pClassName; } } //*************************************************************************** // // DumpKeyList // // Purpose: Dumps out the keys // //*************************************************************************** void DumpKeyList(IWbemPath * pParser) { HRESULT hr; IWbemPathKeyList * pKeyList = NULL; hr = pParser->GetKeyList(&pKeyList); if(FAILED(hr) || pKeyList == NULL) { printf("\nNULL KEY LIST *****************"); return; } unsigned long uNumKey; hr = pKeyList->GetCount(&uNumKey); if(FAILED(hr)) { printf("\nGetCount failed, hr = 0x%x", hr); return; } printf("\nThe key count is %d", uNumKey); // check for the special case of a singleton. In this case, the path does not have a named key and the // value is "@" if(uNumKey == 0) { ULONGLONG uResponse; hr = pKeyList->GetInfo(0, &uResponse); if(SUCCEEDED(hr) && (uResponse & WBEMPATH_INFO_CONTAINS_SINGLETON)) { printf("\nPath is a singleton"); return; } } // for the sake of clarity, this example assumes a maximum name size of 256. Normally, an application would // take one of two approaches; First, it could just allocate a buffer the size of the text used in the SetText // call and assume that is sufficient for the largest piece. Second, it can call GetKey2 will a NULL pointer // to the name buffer and find out how large it needs to be, as is done in the DumpClassName and // DumpServer routines. WCHAR wName[256]; for(DWORD uKeyIx = 0; uKeyIx < uNumKey ; uKeyIx++) { ULONG uKeyType; DWORD dwSize = 256; VARIANT var, var2; VariantInit(&var); VariantInit(&var2); hr = pKeyList->GetKey2(uKeyIx, 0, &dwSize, wName, &var, &uKeyType); if(FAILED(hr)) { printf("\nGetKey2 failed, index = %d, hr = 0x%x", uKeyIx, hr); } else { // here we use Variant change type as a convenient string conversion routine. hr = VariantChangeType(&var2, &var, 0, VT_BSTR); if(SUCCEEDED(hr)) { printf("\nKey %d, has name <%S>, type %d, value <%S>", uKeyIx, wName, uKeyType, var2.bstrVal); VariantClear(&var2); } else printf("\nVariantChangeType failed, hr = 0x%x", hr); VariantClear(&var); } } } //*************************************************************************** // // ParseAndDump // // Purpose: Does the actual parse, and dumps information // //*************************************************************************** void ParseAndDump(IWbemPath * pParser, WCHAR * pwcPath) { HRESULT hr; printf("\nAttempting to parse string <%S>", pwcPath); hr = pParser->SetText(WBEMPATH_CREATE_ACCEPT_ALL, pwcPath); if(FAILED(hr)) { printf("\nParse failed, return code is 0x%x", hr); return; } DumpServerName(pParser); DumpNamespaces(pParser); DumpClassName(pParser); DumpKeyList(pParser); } //*************************************************************************** // // main // // Purpose: Program entry point. It checks the argument, converts it to unicode, // initializes Com, and creates the parser. // //*************************************************************************** int main(int iArgCnt, char ** argv) { // First argument is the is the path. If not present, dump out a usage message. if(iArgCnt < 2) { printf("\nUsage: PathParser " "\nExample: PathParser \\\\MyServer\\root\\default:stdregprov=@" "\nor PathParser \\\\MyServer\\root\\default:stdregprov.key=\\\"hello\\\"" "\nor PathParser \\\\MyServer\\root\\default:stdregprov.key=23" ); return 1; } // Convert to unicode int iLen = strlen(argv[1]); WCHAR * pwcPath = new WCHAR[iLen+1]; if(pwcPath == NULL) { printf("\nFailed due to lack of memory"); return 1; } mbstowcs(pwcPath, argv[1], iLen + 1); // Initialize COM and create the path parser object HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED); if(SUCCEEDED(hr)) { IWbemPath *pParser = NULL; hr = CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER, IID_IWbemPath, (LPVOID *) &pParser); if(SUCCEEDED(hr)) { ParseAndDump(pParser, pwcPath); pParser->Release(); } else printf("\nCoCreateInstance of CLSID_WbemDefPath, return is 0x%x", hr); CoUninitialize(); } delete [] pwcPath; printf("\nTerminating normally"); return 0; }