pdh: Implement PdhMakeCounterPathA/W.

Hans Leidekker hans at codeweavers.com
Fri May 8 04:17:15 CDT 2009


Fixes http://bugs.winehq.org/show_bug.cgi?id=18388

 -Hans

diff --git a/dlls/pdh/pdh.spec b/dlls/pdh/pdh.spec
index 0e1ea84..135692f 100644
--- a/dlls/pdh/pdh.spec
+++ b/dlls/pdh/pdh.spec
@@ -79,8 +79,8 @@
 @ stdcall PdhLookupPerfIndexByNameW(wstr wstr ptr)
 @ stdcall PdhLookupPerfNameByIndexA(str long ptr ptr)
 @ stdcall PdhLookupPerfNameByIndexW(wstr long ptr ptr)
-@ stub PdhMakeCounterPathA
-@ stub PdhMakeCounterPathW
+@ stdcall PdhMakeCounterPathA(ptr ptr ptr long)
+@ stdcall PdhMakeCounterPathW(ptr ptr ptr long)
 @ stub PdhOpenLogA
 @ stub PdhOpenLogW
 @ stdcall PdhOpenQuery(wstr long ptr) PdhOpenQueryW
diff --git a/dlls/pdh/pdh_main.c b/dlls/pdh/pdh_main.c
index 4a32cf5..8e91caf 100644
--- a/dlls/pdh/pdh_main.c
+++ b/dlls/pdh/pdh_main.c
@@ -1061,6 +1061,110 @@ PDH_STATUS WINAPI PdhValidatePathExW( PDH_HLOG source, LPCWSTR path )
 }
 
 /***********************************************************************
+ *              PdhMakeCounterPathA   (PDH.@)
+ */
+PDH_STATUS WINAPI PdhMakeCounterPathA( PDH_COUNTER_PATH_ELEMENTS_A *e, LPSTR buffer,
+                                       LPDWORD buflen, DWORD flags )
+{
+    PDH_STATUS ret = PDH_MEMORY_ALLOCATION_FAILURE;
+    PDH_COUNTER_PATH_ELEMENTS_W eW;
+    WCHAR *bufferW;
+    DWORD buflenW;
+
+    TRACE("%p %p %p 0x%08x\n", e, buffer, buflen, flags);
+
+    if (!e || !buflen) return PDH_INVALID_ARGUMENT;
+
+    memset( &eW, 0, sizeof(eW) );
+    if (e->szMachineName    && !(eW.szMachineName    = pdh_strdup_aw( e->szMachineName ))) goto done;
+    if (e->szObjectName     && !(eW.szObjectName     = pdh_strdup_aw( e->szObjectName ))) goto done;
+    if (e->szInstanceName   && !(eW.szInstanceName   = pdh_strdup_aw( e->szInstanceName ))) goto done;
+    if (e->szParentInstance && !(eW.szParentInstance = pdh_strdup_aw( e->szParentInstance ))) goto done;
+    if (e->szCounterName    && !(eW.szCounterName    = pdh_strdup_aw( e->szCounterName ))) goto done;
+    eW.dwInstanceIndex = e->dwInstanceIndex;
+
+    buflenW = 0;
+    ret = PdhMakeCounterPathW( &eW, NULL, &buflenW, flags );
+    if (ret == PDH_MORE_DATA)
+    {
+        if ((bufferW = heap_alloc( buflenW * sizeof(WCHAR) )))
+        {
+            if (!(ret = PdhMakeCounterPathW( &eW, bufferW, &buflenW, flags )))
+            {
+                int len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
+                if (*buflen >= len) WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, *buflen, NULL, NULL);
+                else ret = PDH_MORE_DATA;
+                *buflen = len;
+            }
+            heap_free( bufferW );
+        }
+    }
+
+done:
+    heap_free( eW.szMachineName );
+    heap_free( eW.szObjectName );
+    heap_free( eW.szInstanceName );
+    heap_free( eW.szParentInstance );
+    heap_free( eW.szCounterName );
+    return ret;
+}
+
+/***********************************************************************
+ *              PdhMakeCounterPathW   (PDH.@)
+ */
+PDH_STATUS WINAPI PdhMakeCounterPathW( PDH_COUNTER_PATH_ELEMENTS_W *e, LPWSTR buffer,
+                                       LPDWORD buflen, DWORD flags )
+{
+    static const WCHAR bslash[] = {'\\',0};
+    static const WCHAR fslash[] = {'/',0};
+    static const WCHAR lparen[] = {'(',0};
+    static const WCHAR rparen[] = {')',0};
+    static const WCHAR fmt[]    = {'#','%','u',0};
+
+    WCHAR path[PDH_MAX_COUNTER_NAME], instance[12];
+    PDH_STATUS ret = ERROR_SUCCESS;
+    DWORD len;
+
+    TRACE("%p %p %p 0x%08x\n", e, buffer, buflen, flags);
+
+    if (flags) FIXME("unimplemented flags 0x%08x\n", flags);
+
+    if (!e || !e->szCounterName || !e->szObjectName || !buflen)
+        return PDH_INVALID_ARGUMENT;
+
+    path[0] = 0;
+    if (e->szMachineName)
+    {
+        strcatW(path, bslash);
+        strcatW(path, bslash);
+        strcatW(path, e->szMachineName);
+    }
+    strcatW(path, bslash);
+    strcatW(path, e->szObjectName);
+    if (e->szInstanceName)
+    {
+        strcatW(path, lparen);
+        if (e->szParentInstance)
+        {
+            strcatW(path, e->szParentInstance);
+            strcatW(path, fslash);
+        }
+        strcatW(path, e->szInstanceName);
+        sprintfW(instance, fmt, e->dwInstanceIndex);
+        strcatW(path, instance);
+        strcatW(path, rparen);
+    }
+    strcatW(path, bslash);
+    strcatW(path, e->szCounterName);
+
+    len = strlenW(path) + 1;
+    if (*buflen >= len) strcpyW(buffer, path);
+    else ret = PDH_MORE_DATA;
+    *buflen = len;
+    return ret;
+}
+
+/***********************************************************************
  *              PdhEnumObjectItemsA   (PDH.@)
  */
 PDH_STATUS WINAPI PdhEnumObjectItemsA(LPCSTR szDataSource, LPCSTR szMachineName, LPCSTR szObjectName,
diff --git a/dlls/pdh/tests/pdh.c b/dlls/pdh/tests/pdh.c
index 4b7c562..cd03bcb 100644
--- a/dlls/pdh/tests/pdh.c
+++ b/dlls/pdh/tests/pdh.c
@@ -837,6 +837,103 @@ static void test_PdhCollectQueryDataEx(void)
     ok(status == ERROR_SUCCESS, "PdhCloseQuery failed 0x%08x\n", status);
 }
 
+static void test_PdhMakeCounterPathA(void)
+{
+    PDH_STATUS ret;
+    PDH_COUNTER_PATH_ELEMENTS_A e;
+    char buffer[1024];
+    DWORD buflen;
+
+    ret = PdhMakeCounterPathA(NULL, NULL, NULL, 0);
+    ok(ret == PDH_INVALID_ARGUMENT, "PdhMakeCounterPathA failed 0x%08x\n", ret);
+
+    buflen = 0;
+    ret = PdhMakeCounterPathA(NULL, NULL, &buflen, 0);
+    ok(ret == PDH_INVALID_ARGUMENT, "PdhMakeCounterPathA failed 0x%08x\n", ret);
+
+    buflen = 0;
+    ret = PdhMakeCounterPathA(NULL, buffer, &buflen, 0);
+    ok(ret == PDH_INVALID_ARGUMENT, "PdhMakeCounterPathA failed 0x%08x\n", ret);
+
+    buflen = sizeof(buffer);
+    memset(&e, 0, sizeof(e));
+    ret = PdhMakeCounterPathA(&e, buffer, &buflen, 0);
+    ok(ret == PDH_INVALID_ARGUMENT, "PdhMakeCounterPathA failed 0x%08x\n", ret);
+
+    buffer[0] = 0;
+    buflen = sizeof(buffer);
+    e.szMachineName = (char *)"machine";
+    ret = PdhMakeCounterPathA(&e, buffer, &buflen, 0);
+    ok(ret == PDH_INVALID_ARGUMENT, "PdhMakeCounterPathA failed 0x%08x\n", ret);
+    ok(!strcmp(buffer, ""), "expected \"machine\" got %s\n", buffer);
+
+    buffer[0] = 0;
+    buflen = sizeof(buffer);
+    e.szObjectName = (char *)"object";
+    ret = PdhMakeCounterPathA(&e, buffer, &buflen, 0);
+    ok(ret == PDH_INVALID_ARGUMENT, "PdhMakeCounterPathA failed 0x%08x\n", ret);
+    ok(!strcmp(buffer, ""), "expected \"machine\" got %s\n", buffer);
+
+    buffer[0] = 0;
+    buflen = sizeof(buffer);
+    e.szInstanceName = (char *)"instance";
+    ret = PdhMakeCounterPathA(&e, buffer, &buflen, 0);
+    ok(ret == PDH_INVALID_ARGUMENT, "PdhMakeCounterPathA failed 0x%08x\n", ret);
+    ok(!strcmp(buffer, ""), "expected \"machine\" got %s\n", buffer);
+
+    buffer[0] = 0;
+    buflen = sizeof(buffer);
+    e.szParentInstance = (char *)"parent";
+    ret = PdhMakeCounterPathA(&e, buffer, &buflen, 0);
+    ok(ret == PDH_INVALID_ARGUMENT, "PdhMakeCounterPathA failed 0x%08x\n", ret);
+    ok(!strcmp(buffer, ""), "expected \"machine\" got %s\n", buffer);
+
+    buffer[0] = 0;
+    buflen = sizeof(buffer);
+    e.dwInstanceIndex = 1;
+    ret = PdhMakeCounterPathA(&e, buffer, &buflen, 0);
+    ok(ret == PDH_INVALID_ARGUMENT, "PdhMakeCounterPathA failed 0x%08x\n", ret);
+    ok(!strcmp(buffer, ""), "expected \"machine\" got %s\n", buffer);
+
+    buffer[0] = 0;
+    buflen = sizeof(buffer);
+    e.szCounterName = (char *)"counter";
+    ret = PdhMakeCounterPathA(&e, buffer, &buflen, 0);
+    ok(ret == ERROR_SUCCESS, "PdhMakeCounterPathA failed 0x%08x\n", ret);
+    ok(!strcmp(buffer, "\\\\machine\\object(parent/instance#1)\\counter"),
+       "expected \"\\\\machine\\object(parent/instance#1)\\counter\" got %s\n", buffer);
+
+    buffer[0] = 0;
+    buflen = sizeof(buffer);
+    e.szParentInstance = NULL;
+    ret = PdhMakeCounterPathA(&e, buffer, &buflen, 0);
+    ok(ret == ERROR_SUCCESS, "PdhMakeCounterPathA failed 0x%08x\n", ret);
+    ok(!strcmp(buffer, "\\\\machine\\object(instance#1)\\counter"),
+       "expected \"\\\\machine\\object(instance#1)\\counter\" got %s\n", buffer);
+
+    buffer[0] = 0;
+    buflen = sizeof(buffer);
+    e.szInstanceName = NULL;
+    ret = PdhMakeCounterPathA(&e, buffer, &buflen, 0);
+    ok(ret == ERROR_SUCCESS, "PdhMakeCounterPathA failed 0x%08x\n", ret);
+    ok(!strcmp(buffer, "\\\\machine\\object\\counter"),
+       "expected \"\\\\machine\\object\\counter\" got %s\n", buffer);
+
+    buffer[0] = 0;
+    buflen = sizeof(buffer);
+    e.szMachineName = NULL;
+    ret = PdhMakeCounterPathA(&e, buffer, &buflen, 0);
+    ok(ret == ERROR_SUCCESS, "PdhMakeCounterPathA failed 0x%08x\n", ret);
+    ok(!strcmp(buffer, "\\object\\counter"),
+       "expected \"\\object\\counter\" got %s\n", buffer);
+
+    buffer[0] = 0;
+    buflen = sizeof(buffer);
+    e.szObjectName = NULL;
+    ret = PdhMakeCounterPathA(&e, buffer, &buflen, 0);
+    ok(ret == PDH_INVALID_ARGUMENT, "PdhMakeCounterPathA failed 0x%08x\n", ret);
+}
+
 START_TEST(pdh)
 {
     if (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH)
@@ -877,4 +974,5 @@ START_TEST(pdh)
     if (pPdhValidatePathExW) test_PdhValidatePathExW();
 
     test_PdhCollectQueryDataEx();
+    test_PdhMakeCounterPathA();
 }
diff --git a/include/pdh.h b/include/pdh.h
index 082f5cc..d79241b 100644
--- a/include/pdh.h
+++ b/include/pdh.h
@@ -190,6 +190,9 @@ PDH_STATUS WINAPI PdhLookupPerfIndexByNameW(LPCWSTR, LPCWSTR, LPDWORD);
 PDH_STATUS WINAPI PdhLookupPerfNameByIndexA(LPCSTR, DWORD, LPSTR, LPDWORD);
 PDH_STATUS WINAPI PdhLookupPerfNameByIndexW(LPCWSTR, DWORD, LPWSTR, LPDWORD);
 #define    PdhLookupPerfNameByIndex WINELIB_NAME_AW(PdhLookupPerfNameByIndex)
+PDH_STATUS WINAPI PdhMakeCounterPathA(PDH_COUNTER_PATH_ELEMENTS_A *, LPSTR, LPDWORD, DWORD);
+PDH_STATUS WINAPI PdhMakeCounterPathW(PDH_COUNTER_PATH_ELEMENTS_W *, LPWSTR, LPDWORD, DWORD);
+#define    PdhMakeCounterPath WINELIB_NAME_AW(PdhMakeCounterPath)
 PDH_STATUS WINAPI PdhOpenQueryA(LPCSTR, DWORD_PTR, PDH_HQUERY *);
 PDH_STATUS WINAPI PdhOpenQueryW(LPCWSTR, DWORD_PTR, PDH_HQUERY *);
 #define    PdhOpenQuery WINELIB_NAME_AW(PdhOpenQuery)



More information about the wine-patches mailing list