ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pdh_main.c
Go to the documentation of this file.
00001 /*
00002  * Performance Data Helper (pdh.dll)
00003  *
00004  * Copyright 2007 Andrey Turkin
00005  * Copyright 2007 Hans Leidekker
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #include <stdarg.h>
00023 #include <math.h>
00024 
00025 #define NONAMELESSUNION
00026 #define NONAMELESSSTRUCT
00027 #include "windef.h"
00028 #include "winbase.h"
00029 
00030 #include "pdh.h"
00031 #include "pdhmsg.h"
00032 #include "winperf.h"
00033 
00034 #include "wine/debug.h"
00035 #include "wine/list.h"
00036 #include "wine/unicode.h"
00037 
00038 WINE_DEFAULT_DEBUG_CHANNEL(pdh);
00039 
00040 static CRITICAL_SECTION pdh_handle_cs;
00041 static CRITICAL_SECTION_DEBUG pdh_handle_cs_debug =
00042 {
00043     0, 0, &pdh_handle_cs,
00044     { &pdh_handle_cs_debug.ProcessLocksList,
00045       &pdh_handle_cs_debug.ProcessLocksList },
00046       0, 0, { (DWORD_PTR)(__FILE__ ": pdh_handle_cs") }
00047 };
00048 static CRITICAL_SECTION pdh_handle_cs = { &pdh_handle_cs_debug, -1, 0, 0, 0, 0 };
00049 
00050 static inline void *heap_alloc( SIZE_T size )
00051 {
00052     return HeapAlloc( GetProcessHeap(), 0, size );
00053 }
00054 
00055 static inline void *heap_alloc_zero( SIZE_T size )
00056 {
00057     return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
00058 }
00059 
00060 static inline void heap_free( LPVOID mem )
00061 {
00062     HeapFree( GetProcessHeap(), 0, mem );
00063 }
00064 
00065 static inline WCHAR *pdh_strdup( const WCHAR *src )
00066 {
00067     WCHAR *dst;
00068 
00069     if (!src) return NULL;
00070     if ((dst = heap_alloc( (strlenW( src ) + 1) * sizeof(WCHAR) ))) strcpyW( dst, src );
00071     return dst;
00072 }
00073 
00074 static inline WCHAR *pdh_strdup_aw( const char *src )
00075 {
00076     int len;
00077     WCHAR *dst;
00078 
00079     if (!src) return NULL;
00080     len = MultiByteToWideChar( CP_ACP, 0, src, -1, NULL, 0 );
00081     if ((dst = heap_alloc( len * sizeof(WCHAR) ))) MultiByteToWideChar( CP_ACP, 0, src, -1, dst, len );
00082     return dst;
00083 }
00084 
00085 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
00086 {
00087     TRACE("(0x%p, %d, %p)\n",hinstDLL,fdwReason,lpvReserved);
00088 
00089     if (fdwReason == DLL_WINE_PREATTACH) return FALSE;    /* prefer native version */
00090 
00091     if (fdwReason == DLL_PROCESS_ATTACH)
00092     {
00093         DisableThreadLibraryCalls( hinstDLL );
00094     }
00095 
00096     return TRUE;
00097 }
00098 
00099 union value
00100 {
00101     LONG     longvalue;
00102     double   doublevalue;
00103     LONGLONG largevalue;
00104 };
00105 
00106 struct counter
00107 {
00108     DWORD           magic;                          /* signature */
00109     struct list     entry;                          /* list entry */
00110     WCHAR          *path;                           /* identifier */
00111     DWORD           type;                           /* counter type */
00112     DWORD           status;                         /* update status */
00113     LONG            scale;                          /* scale factor */
00114     LONG            defaultscale;                   /* default scale factor */
00115     DWORD_PTR       user;                           /* user data */
00116     DWORD_PTR       queryuser;                      /* query user data */
00117     LONGLONG        base;                           /* samples per second */
00118     FILETIME        stamp;                          /* time stamp */
00119     void (CALLBACK *collect)( struct counter * );   /* collect callback */
00120     union value     one;                            /* first value */
00121     union value     two;                            /* second value */
00122 };
00123 
00124 #define PDH_MAGIC_COUNTER   0x50444831 /* 'PDH1' */
00125 
00126 static struct counter *create_counter( void )
00127 {
00128     struct counter *counter;
00129 
00130     if ((counter = heap_alloc_zero( sizeof(struct counter) )))
00131     {
00132         counter->magic = PDH_MAGIC_COUNTER;
00133         return counter;
00134     }
00135     return NULL;
00136 }
00137 
00138 static void destroy_counter( struct counter *counter )
00139 {
00140     counter->magic = 0;
00141     heap_free( counter->path );
00142     heap_free( counter );
00143 }
00144 
00145 #define PDH_MAGIC_QUERY     0x50444830 /* 'PDH0' */
00146 
00147 struct query
00148 {
00149     DWORD       magic;      /* signature */
00150     DWORD_PTR   user;       /* user data */
00151     HANDLE      thread;     /* collect thread */
00152     DWORD       interval;   /* collect interval */
00153     HANDLE      wait;       /* wait event */
00154     HANDLE      stop;       /* stop event */
00155     struct list counters;   /* counter list */
00156 };
00157 
00158 static struct query *create_query( void )
00159 {
00160     struct query *query;
00161 
00162     if ((query = heap_alloc_zero( sizeof(struct query) )))
00163     {
00164         query->magic = PDH_MAGIC_QUERY;
00165         list_init( &query->counters );
00166         return query;
00167     }
00168     return NULL;
00169 }
00170 
00171 static void destroy_query( struct query *query )
00172 {
00173     query->magic = 0;
00174     heap_free( query );
00175 }
00176 
00177 struct source
00178 {
00179     DWORD           index;                          /* name index */
00180     const WCHAR    *path;                           /* identifier */
00181     void (CALLBACK *collect)( struct counter * );   /* collect callback */
00182     DWORD           type;                           /* counter type */
00183     LONG            scale;                          /* default scale factor */
00184     LONGLONG        base;                           /* samples per second */
00185 };
00186 
00187 static const WCHAR path_processor_time[] =
00188     {'\\','P','r','o','c','e','s','s','o','r','(','_','T','o','t','a','l',')',
00189      '\\','%',' ','P','r','o','c','e','s','s','o','r',' ','T','i','m','e',0};
00190 static const WCHAR path_uptime[] =
00191     {'\\','S','y','s','t','e','m', '\\', 'S','y','s','t','e','m',' ','U','p',' ','T','i','m','e',0};
00192 
00193 static void CALLBACK collect_processor_time( struct counter *counter )
00194 {
00195     counter->two.largevalue = 500000; /* FIXME */
00196     counter->status = PDH_CSTATUS_VALID_DATA;
00197 }
00198 
00199 static void CALLBACK collect_uptime( struct counter *counter )
00200 {
00201     counter->two.largevalue = GetTickCount64();
00202     counter->status = PDH_CSTATUS_VALID_DATA;
00203 }
00204 
00205 #define TYPE_PROCESSOR_TIME \
00206     (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | PERF_TIMER_100NS | PERF_DELTA_COUNTER | \
00207      PERF_INVERSE_COUNTER | PERF_DISPLAY_PERCENT)
00208 
00209 #define TYPE_UPTIME \
00210     (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_ELAPSED | PERF_OBJECT_TIMER | PERF_DISPLAY_SECONDS)
00211 
00212 /* counter source registry */
00213 static const struct source counter_sources[] =
00214 {
00215     { 6,    path_processor_time,    collect_processor_time,     TYPE_PROCESSOR_TIME,    -5,     10000000 },
00216     { 674,  path_uptime,            collect_uptime,             TYPE_UPTIME,            -3,     1000 }
00217 };
00218 
00219 static BOOL pdh_match_path( LPCWSTR fullpath, LPCWSTR path )
00220 {
00221     const WCHAR *p;
00222 
00223     if (strchrW( path, '\\')) p = fullpath;
00224     else p = strrchrW( fullpath, '\\' ) + 1;
00225     if (strcmpW( p, path )) return FALSE;
00226     return TRUE;
00227 }
00228 
00229 /***********************************************************************
00230  *              PdhAddCounterA   (PDH.@)
00231  */
00232 PDH_STATUS WINAPI PdhAddCounterA( PDH_HQUERY query, LPCSTR path,
00233                                   DWORD_PTR userdata, PDH_HCOUNTER *counter )
00234 {
00235     PDH_STATUS ret;
00236     WCHAR *pathW;
00237 
00238     TRACE("%p %s %lx %p\n", query, debugstr_a(path), userdata, counter);
00239 
00240     if (!path) return PDH_INVALID_ARGUMENT;
00241 
00242     if (!(pathW = pdh_strdup_aw( path )))
00243         return PDH_MEMORY_ALLOCATION_FAILURE;
00244 
00245     ret = PdhAddCounterW( query, pathW, userdata, counter );
00246 
00247     heap_free( pathW );
00248     return ret;
00249 }
00250 
00251 /***********************************************************************
00252  *              PdhAddCounterW   (PDH.@)
00253  */
00254 PDH_STATUS WINAPI PdhAddCounterW( PDH_HQUERY hquery, LPCWSTR path,
00255                                   DWORD_PTR userdata, PDH_HCOUNTER *hcounter )
00256 {
00257     struct query *query = hquery;
00258     struct counter *counter;
00259     unsigned int i;
00260 
00261     TRACE("%p %s %lx %p\n", hquery, debugstr_w(path), userdata, hcounter);
00262 
00263     if (!path  || !hcounter) return PDH_INVALID_ARGUMENT;
00264 
00265     EnterCriticalSection( &pdh_handle_cs );
00266     if (!query || query->magic != PDH_MAGIC_QUERY)
00267     {
00268         LeaveCriticalSection( &pdh_handle_cs );
00269         return PDH_INVALID_HANDLE;
00270     }
00271 
00272     *hcounter = NULL;
00273     for (i = 0; i < sizeof(counter_sources) / sizeof(counter_sources[0]); i++)
00274     {
00275         if (pdh_match_path( counter_sources[i].path, path ))
00276         {
00277             if ((counter = create_counter()))
00278             {
00279                 counter->path         = pdh_strdup( counter_sources[i].path );
00280                 counter->collect      = counter_sources[i].collect;
00281                 counter->type         = counter_sources[i].type;
00282                 counter->defaultscale = counter_sources[i].scale;
00283                 counter->base         = counter_sources[i].base;
00284                 counter->queryuser    = query->user;
00285                 counter->user         = userdata;
00286 
00287                 list_add_tail( &query->counters, &counter->entry );
00288                 *hcounter = counter;
00289 
00290                 LeaveCriticalSection( &pdh_handle_cs );
00291                 return ERROR_SUCCESS;
00292             }
00293             LeaveCriticalSection( &pdh_handle_cs );
00294             return PDH_MEMORY_ALLOCATION_FAILURE;
00295         }
00296     }
00297     LeaveCriticalSection( &pdh_handle_cs );
00298     return PDH_CSTATUS_NO_COUNTER;
00299 }
00300 
00301 /***********************************************************************
00302  *              PdhAddEnglishCounterA   (PDH.@)
00303  */
00304 PDH_STATUS WINAPI PdhAddEnglishCounterA( PDH_HQUERY query, LPCSTR path,
00305                                          DWORD_PTR userdata, PDH_HCOUNTER *counter )
00306 {
00307     TRACE("%p %s %lx %p\n", query, debugstr_a(path), userdata, counter);
00308 
00309     if (!query) return PDH_INVALID_ARGUMENT;
00310     return PdhAddCounterA( query, path, userdata, counter );
00311 }
00312 
00313 /***********************************************************************
00314  *              PdhAddEnglishCounterW   (PDH.@)
00315  */
00316 PDH_STATUS WINAPI PdhAddEnglishCounterW( PDH_HQUERY query, LPCWSTR path,
00317                                          DWORD_PTR userdata, PDH_HCOUNTER *counter )
00318 {
00319     TRACE("%p %s %lx %p\n", query, debugstr_w(path), userdata, counter);
00320 
00321     if (!query) return PDH_INVALID_ARGUMENT;
00322     return PdhAddCounterW( query, path, userdata, counter );
00323 }
00324 
00325 /* caller must hold counter lock */
00326 static PDH_STATUS format_value( struct counter *counter, DWORD format, union value *raw1,
00327                                 union value *raw2, PDH_FMT_COUNTERVALUE *value )
00328 {
00329     LONG factor;
00330 
00331     factor = counter->scale ? counter->scale : counter->defaultscale;
00332     if (format & PDH_FMT_LONG)
00333     {
00334         if (format & PDH_FMT_1000) value->u.longValue = raw2->longvalue * 1000;
00335         else value->u.longValue = raw2->longvalue * pow( 10, factor );
00336     }
00337     else if (format & PDH_FMT_LARGE)
00338     {
00339         if (format & PDH_FMT_1000) value->u.largeValue = raw2->largevalue * 1000;
00340         else value->u.largeValue = raw2->largevalue * pow( 10, factor );
00341     }
00342     else if (format & PDH_FMT_DOUBLE)
00343     {
00344         if (format & PDH_FMT_1000) value->u.doubleValue = raw2->doublevalue * 1000;
00345         else value->u.doubleValue = raw2->doublevalue * pow( 10, factor );
00346     }
00347     else
00348     {
00349         WARN("unknown format %x\n", format);
00350         return PDH_INVALID_ARGUMENT;
00351     }
00352     return ERROR_SUCCESS;
00353 }
00354 
00355 /***********************************************************************
00356  *              PdhCalculateCounterFromRawValue   (PDH.@)
00357  */
00358 PDH_STATUS WINAPI PdhCalculateCounterFromRawValue( PDH_HCOUNTER handle, DWORD format,
00359                                                    PPDH_RAW_COUNTER raw1, PPDH_RAW_COUNTER raw2,
00360                                                    PPDH_FMT_COUNTERVALUE value )
00361 {
00362     PDH_STATUS ret;
00363     struct counter *counter = handle;
00364 
00365     TRACE("%p 0x%08x %p %p %p\n", handle, format, raw1, raw2, value);
00366 
00367     if (!value) return PDH_INVALID_ARGUMENT;
00368 
00369     EnterCriticalSection( &pdh_handle_cs );
00370     if (!counter || counter->magic != PDH_MAGIC_COUNTER)
00371     {
00372         LeaveCriticalSection( &pdh_handle_cs );
00373         return PDH_INVALID_HANDLE;
00374     }
00375 
00376     ret = format_value( counter, format, (union value *)&raw1->SecondValue,
00377                                          (union value *)&raw2->SecondValue, value );
00378 
00379     LeaveCriticalSection( &pdh_handle_cs );
00380     return ret;
00381 }
00382 
00383 
00384 /***********************************************************************
00385  *              PdhCloseQuery   (PDH.@)
00386  */
00387 PDH_STATUS WINAPI PdhCloseQuery( PDH_HQUERY handle )
00388 {
00389     struct query *query = handle;
00390     struct list *item, *next;
00391 
00392     TRACE("%p\n", handle);
00393 
00394     EnterCriticalSection( &pdh_handle_cs );
00395     if (!query || query->magic != PDH_MAGIC_QUERY)
00396     {
00397         LeaveCriticalSection( &pdh_handle_cs );
00398         return PDH_INVALID_HANDLE;
00399     }
00400 
00401     if (query->thread)
00402     {
00403         HANDLE thread = query->thread;
00404         SetEvent( query->stop );
00405         LeaveCriticalSection( &pdh_handle_cs );
00406 
00407         WaitForSingleObject( thread, INFINITE );
00408 
00409         EnterCriticalSection( &pdh_handle_cs );
00410         if (query->magic != PDH_MAGIC_QUERY)
00411         {
00412             LeaveCriticalSection( &pdh_handle_cs );
00413             return ERROR_SUCCESS;
00414         }
00415         CloseHandle( query->stop );
00416         CloseHandle( query->thread );
00417         query->thread = NULL;
00418     }
00419 
00420     LIST_FOR_EACH_SAFE( item, next, &query->counters )
00421     {
00422         struct counter *counter = LIST_ENTRY( item, struct counter, entry );
00423 
00424         list_remove( &counter->entry );
00425         destroy_counter( counter );
00426     }
00427 
00428     destroy_query( query );
00429 
00430     LeaveCriticalSection( &pdh_handle_cs );
00431     return ERROR_SUCCESS;
00432 }
00433 
00434 /* caller must hold query lock */
00435 static void collect_query_data( struct query *query )
00436 {
00437     struct list *item;
00438 
00439     LIST_FOR_EACH( item, &query->counters )
00440     {
00441         SYSTEMTIME time;
00442         struct counter *counter = LIST_ENTRY( item, struct counter, entry );
00443 
00444         counter->collect( counter );
00445 
00446         GetLocalTime( &time );
00447         SystemTimeToFileTime( &time, &counter->stamp );
00448     }
00449 }
00450 
00451 /***********************************************************************
00452  *              PdhCollectQueryData   (PDH.@)
00453  */
00454 PDH_STATUS WINAPI PdhCollectQueryData( PDH_HQUERY handle )
00455 {
00456     struct query *query = handle;
00457 
00458     TRACE("%p\n", handle);
00459 
00460     EnterCriticalSection( &pdh_handle_cs );
00461     if (!query || query->magic != PDH_MAGIC_QUERY)
00462     {
00463         LeaveCriticalSection( &pdh_handle_cs );
00464         return PDH_INVALID_HANDLE;
00465     }
00466 
00467     if (list_empty( &query->counters ))
00468     {
00469         LeaveCriticalSection( &pdh_handle_cs );
00470         return PDH_NO_DATA;
00471     }
00472 
00473     collect_query_data( query );
00474 
00475     LeaveCriticalSection( &pdh_handle_cs );
00476     return ERROR_SUCCESS;
00477 }
00478 
00479 static DWORD CALLBACK collect_query_thread( void *arg )
00480 {
00481     struct query *query = arg;
00482     DWORD interval = query->interval;
00483     HANDLE stop = query->stop;
00484 
00485     for (;;)
00486     {
00487         if (WaitForSingleObject( stop, interval ) != WAIT_TIMEOUT) ExitThread( 0 );
00488 
00489         EnterCriticalSection( &pdh_handle_cs );
00490         if (query->magic != PDH_MAGIC_QUERY)
00491         {
00492             LeaveCriticalSection( &pdh_handle_cs );
00493             ExitThread( PDH_INVALID_HANDLE );
00494         }
00495 
00496         collect_query_data( query );
00497 
00498         if (!SetEvent( query->wait ))
00499         {
00500             LeaveCriticalSection( &pdh_handle_cs );
00501             ExitThread( 0 );
00502         }
00503         LeaveCriticalSection( &pdh_handle_cs );
00504     }
00505 }
00506 
00507 /***********************************************************************
00508  *              PdhCollectQueryDataEx   (PDH.@)
00509  */
00510 PDH_STATUS WINAPI PdhCollectQueryDataEx( PDH_HQUERY handle, DWORD interval, HANDLE event )
00511 {
00512     PDH_STATUS ret;
00513     struct query *query = handle;
00514 
00515     TRACE("%p %d %p\n", handle, interval, event);
00516 
00517     EnterCriticalSection( &pdh_handle_cs );
00518     if (!query || query->magic != PDH_MAGIC_QUERY)
00519     {
00520         LeaveCriticalSection( &pdh_handle_cs );
00521         return PDH_INVALID_HANDLE;
00522     }
00523     if (list_empty( &query->counters ))
00524     {
00525         LeaveCriticalSection( &pdh_handle_cs );
00526         return PDH_NO_DATA;
00527     }
00528     if (query->thread)
00529     {
00530         HANDLE thread = query->thread;
00531         SetEvent( query->stop );
00532         LeaveCriticalSection( &pdh_handle_cs );
00533 
00534         WaitForSingleObject( thread, INFINITE );
00535 
00536         EnterCriticalSection( &pdh_handle_cs );
00537         if (query->magic != PDH_MAGIC_QUERY)
00538         {
00539             LeaveCriticalSection( &pdh_handle_cs );
00540             return PDH_INVALID_HANDLE;
00541         }
00542         CloseHandle( query->thread );
00543         query->thread = NULL;
00544     }
00545     else if (!(query->stop = CreateEventW( NULL, FALSE, FALSE, NULL )))
00546     {
00547         ret = GetLastError();
00548         LeaveCriticalSection( &pdh_handle_cs );
00549         return ret;
00550     }
00551     query->wait = event;
00552     query->interval = interval * 1000;
00553     if (!(query->thread = CreateThread( NULL, 0, collect_query_thread, query, 0, NULL )))
00554     {
00555         ret = GetLastError();
00556         CloseHandle( query->stop );
00557 
00558         LeaveCriticalSection( &pdh_handle_cs );
00559         return ret;
00560     }
00561 
00562     LeaveCriticalSection( &pdh_handle_cs );
00563     return ERROR_SUCCESS;
00564 }
00565 
00566 /***********************************************************************
00567  *              PdhCollectQueryDataWithTime   (PDH.@)
00568  */
00569 PDH_STATUS WINAPI PdhCollectQueryDataWithTime( PDH_HQUERY handle, LONGLONG *timestamp )
00570 {
00571     struct query *query = handle;
00572     struct counter *counter;
00573     struct list *item;
00574 
00575     TRACE("%p %p\n", handle, timestamp);
00576 
00577     if (!timestamp) return PDH_INVALID_ARGUMENT;
00578 
00579     EnterCriticalSection( &pdh_handle_cs );
00580     if (!query || query->magic != PDH_MAGIC_QUERY)
00581     {
00582         LeaveCriticalSection( &pdh_handle_cs );
00583         return PDH_INVALID_HANDLE;
00584     }
00585     if (list_empty( &query->counters ))
00586     {
00587         LeaveCriticalSection( &pdh_handle_cs );
00588         return PDH_NO_DATA;
00589     }
00590 
00591     collect_query_data( query );
00592 
00593     item = list_head( &query->counters );
00594     counter = LIST_ENTRY( item, struct counter, entry );
00595 
00596     *timestamp = ((LONGLONG)counter->stamp.dwHighDateTime << 32) | counter->stamp.dwLowDateTime;
00597 
00598     LeaveCriticalSection( &pdh_handle_cs );
00599     return ERROR_SUCCESS;
00600 }
00601 
00602 /***********************************************************************
00603  *              PdhExpandWildCardPathA   (PDH.@)
00604  */
00605 PDH_STATUS WINAPI PdhExpandWildCardPathA( LPCSTR szDataSource, LPCSTR szWildCardPath, LPSTR mszExpandedPathList, LPDWORD pcchPathListLength, DWORD dwFlags )
00606 {
00607     FIXME("%s, %s, %p, %p, 0x%x: stub\n", debugstr_a(szDataSource), debugstr_a(szWildCardPath), mszExpandedPathList, pcchPathListLength, dwFlags);
00608     return PDH_NOT_IMPLEMENTED;
00609 }
00610 
00611 /***********************************************************************
00612  *              PdhExpandWildCardPathW   (PDH.@)
00613  */
00614 PDH_STATUS WINAPI PdhExpandWildCardPathW( LPCWSTR szDataSource, LPCWSTR szWildCardPath, LPWSTR mszExpandedPathList, LPDWORD pcchPathListLength, DWORD dwFlags )
00615 {
00616     FIXME("%s, %s, %p, %p, 0x%x: stub\n", debugstr_w(szDataSource), debugstr_w(szWildCardPath), mszExpandedPathList, pcchPathListLength, dwFlags);
00617     return PDH_NOT_IMPLEMENTED;
00618 }
00619 
00620 /***********************************************************************
00621  *              PdhGetCounterInfoA   (PDH.@)
00622  */
00623 PDH_STATUS WINAPI PdhGetCounterInfoA( PDH_HCOUNTER handle, BOOLEAN text, LPDWORD size, PPDH_COUNTER_INFO_A info )
00624 {
00625     struct counter *counter = handle;
00626 
00627     TRACE("%p %d %p %p\n", handle, text, size, info);
00628 
00629     EnterCriticalSection( &pdh_handle_cs );
00630     if (!counter || counter->magic != PDH_MAGIC_COUNTER)
00631     {
00632         LeaveCriticalSection( &pdh_handle_cs );
00633         return PDH_INVALID_HANDLE;
00634     }
00635     if (!size)
00636     {
00637         LeaveCriticalSection( &pdh_handle_cs );
00638         return PDH_INVALID_ARGUMENT;
00639     }
00640     if (*size < sizeof(PDH_COUNTER_INFO_A))
00641     {
00642         *size = sizeof(PDH_COUNTER_INFO_A);
00643         LeaveCriticalSection( &pdh_handle_cs );
00644         return PDH_MORE_DATA;
00645     }
00646 
00647     memset( info, 0, sizeof(PDH_COUNTER_INFO_A) );
00648 
00649     info->dwType          = counter->type;
00650     info->CStatus         = counter->status;
00651     info->lScale          = counter->scale;
00652     info->lDefaultScale   = counter->defaultscale;
00653     info->dwUserData      = counter->user;
00654     info->dwQueryUserData = counter->queryuser;
00655 
00656     *size = sizeof(PDH_COUNTER_INFO_A);
00657 
00658     LeaveCriticalSection( &pdh_handle_cs );
00659     return ERROR_SUCCESS;
00660 }
00661 
00662 /***********************************************************************
00663  *              PdhGetCounterInfoW   (PDH.@)
00664  */
00665 PDH_STATUS WINAPI PdhGetCounterInfoW( PDH_HCOUNTER handle, BOOLEAN text, LPDWORD size, PPDH_COUNTER_INFO_W info )
00666 {
00667     struct counter *counter = handle;
00668 
00669     TRACE("%p %d %p %p\n", handle, text, size, info);
00670 
00671     EnterCriticalSection( &pdh_handle_cs );
00672     if (!counter || counter->magic != PDH_MAGIC_COUNTER)
00673     {
00674         LeaveCriticalSection( &pdh_handle_cs );
00675         return PDH_INVALID_HANDLE;
00676     }
00677     if (!size)
00678     {
00679         LeaveCriticalSection( &pdh_handle_cs );
00680         return PDH_INVALID_ARGUMENT;
00681     }
00682     if (*size < sizeof(PDH_COUNTER_INFO_W))
00683     {
00684         *size = sizeof(PDH_COUNTER_INFO_W);
00685         LeaveCriticalSection( &pdh_handle_cs );
00686         return PDH_MORE_DATA;
00687     }
00688 
00689     memset( info, 0, sizeof(PDH_COUNTER_INFO_W) );
00690 
00691     info->dwType          = counter->type;
00692     info->CStatus         = counter->status;
00693     info->lScale          = counter->scale;
00694     info->lDefaultScale   = counter->defaultscale;
00695     info->dwUserData      = counter->user;
00696     info->dwQueryUserData = counter->queryuser;
00697 
00698     *size = sizeof(PDH_COUNTER_INFO_W);
00699 
00700     LeaveCriticalSection( &pdh_handle_cs );
00701     return ERROR_SUCCESS;
00702 }
00703 
00704 /***********************************************************************
00705  *              PdhGetCounterTimeBase   (PDH.@)
00706  */
00707 PDH_STATUS WINAPI PdhGetCounterTimeBase( PDH_HCOUNTER handle, LONGLONG *base )
00708 {
00709     struct counter *counter = handle;
00710 
00711     TRACE("%p %p\n", handle, base);
00712 
00713     if (!base) return PDH_INVALID_ARGUMENT;
00714 
00715     EnterCriticalSection( &pdh_handle_cs );
00716     if (!counter || counter->magic != PDH_MAGIC_COUNTER)
00717     {
00718         LeaveCriticalSection( &pdh_handle_cs );
00719         return PDH_INVALID_HANDLE;
00720     }
00721 
00722     *base = counter->base;
00723 
00724     LeaveCriticalSection( &pdh_handle_cs );
00725     return ERROR_SUCCESS;
00726 }
00727 
00728 /***********************************************************************
00729  *              PdhGetDllVersion   (PDH.@)
00730  */
00731 PDH_STATUS WINAPI PdhGetDllVersion( LPDWORD version )
00732 {
00733     if (!version)
00734         return PDH_INVALID_ARGUMENT;
00735 
00736     *version = PDH_VERSION;
00737 
00738     return ERROR_SUCCESS;
00739 }
00740 
00741 /***********************************************************************
00742  *              PdhGetFormattedCounterValue   (PDH.@)
00743  */
00744 PDH_STATUS WINAPI PdhGetFormattedCounterValue( PDH_HCOUNTER handle, DWORD format,
00745                                                LPDWORD type, PPDH_FMT_COUNTERVALUE value )
00746 {
00747     PDH_STATUS ret;
00748     struct counter *counter = handle;
00749 
00750     TRACE("%p %x %p %p\n", handle, format, type, value);
00751 
00752     if (!value) return PDH_INVALID_ARGUMENT;
00753 
00754     EnterCriticalSection( &pdh_handle_cs );
00755     if (!counter || counter->magic != PDH_MAGIC_COUNTER)
00756     {
00757         LeaveCriticalSection( &pdh_handle_cs );
00758         return PDH_INVALID_HANDLE;
00759     }
00760     if (counter->status)
00761     {
00762         LeaveCriticalSection( &pdh_handle_cs );
00763         return PDH_INVALID_DATA;
00764     }
00765     if (!(ret = format_value( counter, format, &counter->one, &counter->two, value )))
00766     {
00767         value->CStatus = ERROR_SUCCESS;
00768         if (type) *type = counter->type;
00769     }
00770 
00771     LeaveCriticalSection( &pdh_handle_cs );
00772     return ret;
00773 }
00774 
00775 /***********************************************************************
00776  *              PdhGetRawCounterValue   (PDH.@)
00777  */
00778 PDH_STATUS WINAPI PdhGetRawCounterValue( PDH_HCOUNTER handle, LPDWORD type,
00779                                          PPDH_RAW_COUNTER value )
00780 {
00781     struct counter *counter = handle;
00782 
00783     TRACE("%p %p %p\n", handle, type, value);
00784 
00785     if (!value) return PDH_INVALID_ARGUMENT;
00786 
00787     EnterCriticalSection( &pdh_handle_cs );
00788     if (!counter || counter->magic != PDH_MAGIC_COUNTER)
00789     {
00790         LeaveCriticalSection( &pdh_handle_cs );
00791         return PDH_INVALID_HANDLE;
00792     }
00793 
00794     value->CStatus                  = counter->status;
00795     value->TimeStamp.dwLowDateTime  = counter->stamp.dwLowDateTime;
00796     value->TimeStamp.dwHighDateTime = counter->stamp.dwHighDateTime;
00797     value->FirstValue               = counter->one.largevalue;
00798     value->SecondValue              = counter->two.largevalue;
00799     value->MultiCount               = 1; /* FIXME */
00800 
00801     if (type) *type = counter->type;
00802 
00803     LeaveCriticalSection( &pdh_handle_cs );
00804     return ERROR_SUCCESS;
00805 }
00806 
00807 /***********************************************************************
00808  *              PdhLookupPerfIndexByNameA   (PDH.@)
00809  */
00810 PDH_STATUS WINAPI PdhLookupPerfIndexByNameA( LPCSTR machine, LPCSTR name, LPDWORD index )
00811 {
00812     PDH_STATUS ret;
00813     WCHAR *machineW = NULL;
00814     WCHAR *nameW;
00815 
00816     TRACE("%s %s %p\n", debugstr_a(machine), debugstr_a(name), index);
00817 
00818     if (!name) return PDH_INVALID_ARGUMENT;
00819 
00820     if (machine && !(machineW = pdh_strdup_aw( machine ))) return PDH_MEMORY_ALLOCATION_FAILURE;
00821 
00822     if (!(nameW = pdh_strdup_aw( name )))
00823         return PDH_MEMORY_ALLOCATION_FAILURE;
00824 
00825     ret = PdhLookupPerfIndexByNameW( machineW, nameW, index );
00826 
00827     heap_free( nameW );
00828     heap_free( machineW );
00829     return ret;
00830 }
00831 
00832 /***********************************************************************
00833  *              PdhLookupPerfIndexByNameW   (PDH.@)
00834  */
00835 PDH_STATUS WINAPI PdhLookupPerfIndexByNameW( LPCWSTR machine, LPCWSTR name, LPDWORD index )
00836 {
00837     unsigned int i;
00838 
00839     TRACE("%s %s %p\n", debugstr_w(machine), debugstr_w(name), index);
00840 
00841     if (!name || !index) return PDH_INVALID_ARGUMENT;
00842 
00843     if (machine)
00844     {
00845         FIXME("remote machine not supported\n");
00846         return PDH_CSTATUS_NO_MACHINE;
00847     }
00848     for (i = 0; i < sizeof(counter_sources) / sizeof(counter_sources[0]); i++)
00849     {
00850         if (pdh_match_path( counter_sources[i].path, name ))
00851         {
00852             *index = counter_sources[i].index;
00853             return ERROR_SUCCESS;
00854         }
00855     }
00856     return PDH_STRING_NOT_FOUND;
00857 }
00858 
00859 /***********************************************************************
00860  *              PdhLookupPerfNameByIndexA   (PDH.@)
00861  */
00862 PDH_STATUS WINAPI PdhLookupPerfNameByIndexA( LPCSTR machine, DWORD index, LPSTR buffer, LPDWORD size )
00863 {
00864     PDH_STATUS ret;
00865     WCHAR *machineW = NULL;
00866     WCHAR bufferW[PDH_MAX_COUNTER_NAME];
00867     DWORD sizeW = sizeof(bufferW) / sizeof(WCHAR);
00868 
00869     TRACE("%s %d %p %p\n", debugstr_a(machine), index, buffer, size);
00870 
00871     if (!buffer || !size) return PDH_INVALID_ARGUMENT;
00872 
00873     if (machine && !(machineW = pdh_strdup_aw( machine ))) return PDH_MEMORY_ALLOCATION_FAILURE;
00874 
00875     if (!(ret = PdhLookupPerfNameByIndexW( machineW, index, bufferW, &sizeW )))
00876     {
00877         int required = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL );
00878 
00879         if (size && *size < required) ret = PDH_MORE_DATA;
00880         else WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, required, NULL, NULL );
00881         if (size) *size = required;
00882     }
00883     heap_free( machineW );
00884     return ret;
00885 }
00886 
00887 /***********************************************************************
00888  *              PdhLookupPerfNameByIndexW   (PDH.@)
00889  */
00890 PDH_STATUS WINAPI PdhLookupPerfNameByIndexW( LPCWSTR machine, DWORD index, LPWSTR buffer, LPDWORD size )
00891 {
00892     PDH_STATUS ret;
00893     unsigned int i;
00894 
00895     TRACE("%s %d %p %p\n", debugstr_w(machine), index, buffer, size);
00896 
00897     if (machine)
00898     {
00899         FIXME("remote machine not supported\n");
00900         return PDH_CSTATUS_NO_MACHINE;
00901     }
00902 
00903     if (!buffer || !size) return PDH_INVALID_ARGUMENT;
00904     if (!index) return ERROR_SUCCESS;
00905 
00906     for (i = 0; i < sizeof(counter_sources) / sizeof(counter_sources[0]); i++)
00907     {
00908         if (counter_sources[i].index == index)
00909         {
00910             WCHAR *p = strrchrW( counter_sources[i].path, '\\' ) + 1;
00911             unsigned int required = strlenW( p ) + 1;
00912 
00913             if (*size < required) ret = PDH_MORE_DATA;
00914             else
00915             {
00916                 strcpyW( buffer, p );
00917                 ret = ERROR_SUCCESS;
00918             }
00919             *size = required;
00920             return ret;
00921         }
00922     }
00923     return PDH_INVALID_ARGUMENT;
00924 }
00925 
00926 /***********************************************************************
00927  *              PdhOpenQueryA   (PDH.@)
00928  */
00929 PDH_STATUS WINAPI PdhOpenQueryA( LPCSTR source, DWORD_PTR userdata, PDH_HQUERY *query )
00930 {
00931     PDH_STATUS ret;
00932     WCHAR *sourceW = NULL;
00933 
00934     TRACE("%s %lx %p\n", debugstr_a(source), userdata, query);
00935 
00936     if (source && !(sourceW = pdh_strdup_aw( source ))) return PDH_MEMORY_ALLOCATION_FAILURE;
00937 
00938     ret = PdhOpenQueryW( sourceW, userdata, query );
00939     heap_free( sourceW );
00940 
00941     return ret;
00942 }
00943 
00944 /***********************************************************************
00945  *              PdhOpenQueryW   (PDH.@)
00946  */
00947 PDH_STATUS WINAPI PdhOpenQueryW( LPCWSTR source, DWORD_PTR userdata, PDH_HQUERY *handle )
00948 {
00949     struct query *query;
00950 
00951     TRACE("%s %lx %p\n", debugstr_w(source), userdata, handle);
00952 
00953     if (!handle) return PDH_INVALID_ARGUMENT;
00954 
00955     if (source)
00956     {
00957         FIXME("log file data source not supported\n");
00958         return PDH_INVALID_ARGUMENT;
00959     }
00960     if ((query = create_query()))
00961     {
00962         query->user = userdata;
00963         *handle = query;
00964 
00965         return ERROR_SUCCESS;
00966     }
00967     return PDH_MEMORY_ALLOCATION_FAILURE;
00968 }
00969 
00970 /***********************************************************************
00971  *              PdhRemoveCounter   (PDH.@)
00972  */
00973 PDH_STATUS WINAPI PdhRemoveCounter( PDH_HCOUNTER handle )
00974 {
00975     struct counter *counter = handle;
00976 
00977     TRACE("%p\n", handle);
00978 
00979     EnterCriticalSection( &pdh_handle_cs );
00980     if (!counter || counter->magic != PDH_MAGIC_COUNTER)
00981     {
00982         LeaveCriticalSection( &pdh_handle_cs );
00983         return PDH_INVALID_HANDLE;
00984     }
00985 
00986     list_remove( &counter->entry );
00987     destroy_counter( counter );
00988 
00989     LeaveCriticalSection( &pdh_handle_cs );
00990     return ERROR_SUCCESS;
00991 }
00992 
00993 /***********************************************************************
00994  *              PdhSetCounterScaleFactor   (PDH.@)
00995  */
00996 PDH_STATUS WINAPI PdhSetCounterScaleFactor( PDH_HCOUNTER handle, LONG factor )
00997 {
00998     struct counter *counter = handle;
00999 
01000     TRACE("%p\n", handle);
01001 
01002     EnterCriticalSection( &pdh_handle_cs );
01003     if (!counter || counter->magic != PDH_MAGIC_COUNTER)
01004     {
01005         LeaveCriticalSection( &pdh_handle_cs );
01006         return PDH_INVALID_HANDLE;
01007     }
01008     if (factor < PDH_MIN_SCALE || factor > PDH_MAX_SCALE)
01009     {
01010         LeaveCriticalSection( &pdh_handle_cs );
01011         return PDH_INVALID_ARGUMENT;
01012     }
01013 
01014     counter->scale = factor;
01015 
01016     LeaveCriticalSection( &pdh_handle_cs );
01017     return ERROR_SUCCESS;
01018 }
01019 
01020 /***********************************************************************
01021  *              PdhValidatePathA   (PDH.@)
01022  */
01023 PDH_STATUS WINAPI PdhValidatePathA( LPCSTR path )
01024 {
01025     PDH_STATUS ret;
01026     WCHAR *pathW;
01027 
01028     TRACE("%s\n", debugstr_a(path));
01029 
01030     if (!path) return PDH_INVALID_ARGUMENT;
01031     if (!(pathW = pdh_strdup_aw( path ))) return PDH_MEMORY_ALLOCATION_FAILURE;
01032 
01033     ret = PdhValidatePathW( pathW );
01034 
01035     heap_free( pathW );
01036     return ret;
01037 }
01038 
01039 static PDH_STATUS validate_path( LPCWSTR path )
01040 {
01041     if (!path || !*path) return PDH_INVALID_ARGUMENT;
01042     if (*path++ != '\\' || !strchrW( path, '\\' )) return PDH_CSTATUS_BAD_COUNTERNAME;
01043     return ERROR_SUCCESS;
01044  }
01045 
01046 /***********************************************************************
01047  *              PdhValidatePathW   (PDH.@)
01048  */
01049 PDH_STATUS WINAPI PdhValidatePathW( LPCWSTR path )
01050 {
01051     PDH_STATUS ret;
01052     unsigned int i;
01053 
01054     TRACE("%s\n", debugstr_w(path));
01055 
01056     if ((ret = validate_path( path ))) return ret;
01057 
01058     for (i = 0; i < sizeof(counter_sources) / sizeof(counter_sources[0]); i++)
01059         if (pdh_match_path( counter_sources[i].path, path )) return ERROR_SUCCESS;
01060 
01061     return PDH_CSTATUS_NO_COUNTER;
01062 }
01063 
01064 /***********************************************************************
01065  *              PdhValidatePathExA   (PDH.@)
01066  */
01067 PDH_STATUS WINAPI PdhValidatePathExA( PDH_HLOG source, LPCSTR path )
01068 {
01069     TRACE("%p %s\n", source, debugstr_a(path));
01070 
01071     if (source)
01072     {
01073         FIXME("log file data source not supported\n");
01074         return ERROR_SUCCESS;
01075     }
01076     return PdhValidatePathA( path );
01077 }
01078 
01079 /***********************************************************************
01080  *              PdhValidatePathExW   (PDH.@)
01081  */
01082 PDH_STATUS WINAPI PdhValidatePathExW( PDH_HLOG source, LPCWSTR path )
01083 {
01084     TRACE("%p %s\n", source, debugstr_w(path));
01085 
01086     if (source)
01087     {
01088         FIXME("log file data source not supported\n");
01089         return ERROR_SUCCESS;
01090     }
01091     return PdhValidatePathW( path );
01092 }
01093 
01094 /***********************************************************************
01095  *              PdhMakeCounterPathA   (PDH.@)
01096  */
01097 PDH_STATUS WINAPI PdhMakeCounterPathA( PDH_COUNTER_PATH_ELEMENTS_A *e, LPSTR buffer,
01098                                        LPDWORD buflen, DWORD flags )
01099 {
01100     PDH_STATUS ret = PDH_MEMORY_ALLOCATION_FAILURE;
01101     PDH_COUNTER_PATH_ELEMENTS_W eW;
01102     WCHAR *bufferW;
01103     DWORD buflenW;
01104 
01105     TRACE("%p %p %p 0x%08x\n", e, buffer, buflen, flags);
01106 
01107     if (!e || !buflen) return PDH_INVALID_ARGUMENT;
01108 
01109     memset( &eW, 0, sizeof(eW) );
01110     if (e->szMachineName    && !(eW.szMachineName    = pdh_strdup_aw( e->szMachineName ))) goto done;
01111     if (e->szObjectName     && !(eW.szObjectName     = pdh_strdup_aw( e->szObjectName ))) goto done;
01112     if (e->szInstanceName   && !(eW.szInstanceName   = pdh_strdup_aw( e->szInstanceName ))) goto done;
01113     if (e->szParentInstance && !(eW.szParentInstance = pdh_strdup_aw( e->szParentInstance ))) goto done;
01114     if (e->szCounterName    && !(eW.szCounterName    = pdh_strdup_aw( e->szCounterName ))) goto done;
01115     eW.dwInstanceIndex = e->dwInstanceIndex;
01116 
01117     buflenW = 0;
01118     ret = PdhMakeCounterPathW( &eW, NULL, &buflenW, flags );
01119     if (ret == PDH_MORE_DATA)
01120     {
01121         if ((bufferW = heap_alloc( buflenW * sizeof(WCHAR) )))
01122         {
01123             if (!(ret = PdhMakeCounterPathW( &eW, bufferW, &buflenW, flags )))
01124             {
01125                 int len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
01126                 if (*buflen >= len) WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, *buflen, NULL, NULL);
01127                 else ret = PDH_MORE_DATA;
01128                 *buflen = len;
01129             }
01130             heap_free( bufferW );
01131         }
01132         else
01133             ret = PDH_MEMORY_ALLOCATION_FAILURE;
01134     }
01135 
01136 done:
01137     heap_free( eW.szMachineName );
01138     heap_free( eW.szObjectName );
01139     heap_free( eW.szInstanceName );
01140     heap_free( eW.szParentInstance );
01141     heap_free( eW.szCounterName );
01142     return ret;
01143 }
01144 
01145 /***********************************************************************
01146  *              PdhMakeCounterPathW   (PDH.@)
01147  */
01148 PDH_STATUS WINAPI PdhMakeCounterPathW( PDH_COUNTER_PATH_ELEMENTS_W *e, LPWSTR buffer,
01149                                        LPDWORD buflen, DWORD flags )
01150 {
01151     static const WCHAR bslash[] = {'\\',0};
01152     static const WCHAR fslash[] = {'/',0};
01153     static const WCHAR lparen[] = {'(',0};
01154     static const WCHAR rparen[] = {')',0};
01155     static const WCHAR fmt[]    = {'#','%','u',0};
01156 
01157     WCHAR path[PDH_MAX_COUNTER_NAME], instance[12];
01158     PDH_STATUS ret = ERROR_SUCCESS;
01159     DWORD len;
01160 
01161     TRACE("%p %p %p 0x%08x\n", e, buffer, buflen, flags);
01162 
01163     if (flags) FIXME("unimplemented flags 0x%08x\n", flags);
01164 
01165     if (!e || !e->szCounterName || !e->szObjectName || !buflen)
01166         return PDH_INVALID_ARGUMENT;
01167 
01168     path[0] = 0;
01169     if (e->szMachineName)
01170     {
01171         strcatW(path, bslash);
01172         strcatW(path, bslash);
01173         strcatW(path, e->szMachineName);
01174     }
01175     strcatW(path, bslash);
01176     strcatW(path, e->szObjectName);
01177     if (e->szInstanceName)
01178     {
01179         strcatW(path, lparen);
01180         if (e->szParentInstance)
01181         {
01182             strcatW(path, e->szParentInstance);
01183             strcatW(path, fslash);
01184         }
01185         strcatW(path, e->szInstanceName);
01186         sprintfW(instance, fmt, e->dwInstanceIndex);
01187         strcatW(path, instance);
01188         strcatW(path, rparen);
01189     }
01190     strcatW(path, bslash);
01191     strcatW(path, e->szCounterName);
01192 
01193     len = strlenW(path) + 1;
01194     if (*buflen >= len) strcpyW(buffer, path);
01195     else ret = PDH_MORE_DATA;
01196     *buflen = len;
01197     return ret;
01198 }
01199 
01200 /***********************************************************************
01201  *              PdhEnumObjectItemsA   (PDH.@)
01202  */
01203 PDH_STATUS WINAPI PdhEnumObjectItemsA(LPCSTR szDataSource, LPCSTR szMachineName, LPCSTR szObjectName,
01204                                       LPSTR mszCounterList, LPDWORD pcchCounterListLength, LPSTR mszInstanceList,
01205                                       LPDWORD pcchInstanceListLength, DWORD dwDetailLevel, DWORD dwFlags)
01206 {
01207     FIXME("%s, %s, %s, %p, %p, %p, %p, %d, 0x%x: stub\n", debugstr_a(szDataSource), debugstr_a(szMachineName),
01208          debugstr_a(szObjectName), mszCounterList, pcchCounterListLength, mszInstanceList,
01209          pcchInstanceListLength, dwDetailLevel, dwFlags);
01210 
01211     return PDH_NOT_IMPLEMENTED;
01212 }
01213 
01214 /***********************************************************************
01215  *              PdhEnumObjectItemsW   (PDH.@)
01216  */
01217 PDH_STATUS WINAPI PdhEnumObjectItemsW(LPCWSTR szDataSource, LPCWSTR szMachineName, LPCWSTR szObjectName,
01218                                       LPWSTR mszCounterList, LPDWORD pcchCounterListLength, LPWSTR mszInstanceList,
01219                                       LPDWORD pcchInstanceListLength, DWORD dwDetailLevel, DWORD dwFlags)
01220 {
01221     FIXME("%s, %s, %s, %p, %p, %p, %p, %d, 0x%x: stub\n", debugstr_w(szDataSource), debugstr_w(szMachineName),
01222          debugstr_w(szObjectName), mszCounterList, pcchCounterListLength, mszInstanceList,
01223          pcchInstanceListLength, dwDetailLevel, dwFlags);
01224 
01225     return PDH_NOT_IMPLEMENTED;
01226 }
01227 
01228 /***********************************************************************
01229  *              PdhSetDefaultRealTimeDataSource   (PDH.@)
01230  */
01231 PDH_STATUS WINAPI PdhSetDefaultRealTimeDataSource( DWORD source )
01232 {
01233     FIXME("%u\n", source);
01234     return ERROR_SUCCESS;
01235 }

Generated on Sat May 26 2012 04:24:28 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.