2 * Performance Data Helper (pdh.dll)
4 * Copyright 2007 Andrey Turkin
5 * Copyright 2007 Hans Leidekker
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define NONAMELESSUNION
38 #include "wine/debug.h"
39 #include "wine/heap.h"
40 #include "wine/list.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(pdh
);
44 static CRITICAL_SECTION pdh_handle_cs
;
45 static CRITICAL_SECTION_DEBUG pdh_handle_cs_debug
=
48 { &pdh_handle_cs_debug
.ProcessLocksList
,
49 &pdh_handle_cs_debug
.ProcessLocksList
},
50 0, 0, { (DWORD_PTR
)(__FILE__
": pdh_handle_cs") }
52 static CRITICAL_SECTION pdh_handle_cs
= { &pdh_handle_cs_debug
, -1, 0, 0, 0, 0 };
54 static inline WCHAR
*pdh_strdup( const WCHAR
*src
)
58 if (!src
) return NULL
;
59 if ((dst
= heap_alloc( (lstrlenW( src
) + 1) * sizeof(WCHAR
) ))) lstrcpyW( dst
, src
);
63 static inline WCHAR
*pdh_strdup_aw( const char *src
)
68 if (!src
) return NULL
;
69 len
= MultiByteToWideChar( CP_ACP
, 0, src
, -1, NULL
, 0 );
70 if ((dst
= heap_alloc( len
* sizeof(WCHAR
) ))) MultiByteToWideChar( CP_ACP
, 0, src
, -1, dst
, len
);
74 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
76 TRACE("(0x%p, %d, %p)\n",hinstDLL
,fdwReason
,lpvReserved
);
79 case DLL_WINE_PREATTACH
:
80 return FALSE
; /* prefer native version */
81 case DLL_PROCESS_ATTACH
:
82 DisableThreadLibraryCalls(hinstDLL
);
84 case DLL_PROCESS_DETACH
:
85 if (lpvReserved
) break;
86 DeleteCriticalSection(&pdh_handle_cs
);
102 DWORD magic
; /* signature */
103 struct list entry
; /* list entry */
104 WCHAR
*path
; /* identifier */
105 DWORD type
; /* counter type */
106 DWORD status
; /* update status */
107 LONG scale
; /* scale factor */
108 LONG defaultscale
; /* default scale factor */
109 DWORD_PTR user
; /* user data */
110 DWORD_PTR queryuser
; /* query user data */
111 LONGLONG base
; /* samples per second */
112 FILETIME stamp
; /* time stamp */
113 void (CALLBACK
*collect
)( struct counter
* ); /* collect callback */
114 union value one
; /* first value */
115 union value two
; /* second value */
118 #define PDH_MAGIC_COUNTER 0x50444831 /* 'PDH1' */
120 static struct counter
*create_counter( void )
122 struct counter
*counter
;
124 if ((counter
= heap_alloc_zero( sizeof(struct counter
) )))
126 counter
->magic
= PDH_MAGIC_COUNTER
;
132 static void destroy_counter( struct counter
*counter
)
135 heap_free( counter
->path
);
136 heap_free( counter
);
139 #define PDH_MAGIC_QUERY 0x50444830 /* 'PDH0' */
143 DWORD magic
; /* signature */
144 DWORD_PTR user
; /* user data */
145 HANDLE thread
; /* collect thread */
146 DWORD interval
; /* collect interval */
147 HANDLE wait
; /* wait event */
148 HANDLE stop
; /* stop event */
149 struct list counters
; /* counter list */
152 static struct query
*create_query( void )
156 if ((query
= heap_alloc_zero( sizeof(struct query
) )))
158 query
->magic
= PDH_MAGIC_QUERY
;
159 list_init( &query
->counters
);
165 static void destroy_query( struct query
*query
)
173 DWORD index
; /* name index */
174 const WCHAR
*path
; /* identifier */
175 void (CALLBACK
*collect
)( struct counter
* ); /* collect callback */
176 DWORD type
; /* counter type */
177 LONG scale
; /* default scale factor */
178 LONGLONG base
; /* samples per second */
181 static const WCHAR path_processor_time
[] =
182 {'\\','P','r','o','c','e','s','s','o','r','(','_','T','o','t','a','l',')',
183 '\\','%',' ','P','r','o','c','e','s','s','o','r',' ','T','i','m','e',0};
184 static const WCHAR path_processor
[] =
185 {'\\','P','r','o','c','e','s','s','o','r',0};
186 static const WCHAR path_uptime
[] =
187 {'\\','S','y','s','t','e','m', '\\', 'S','y','s','t','e','m',' ','U','p',' ','T','i','m','e',0};
189 static void CALLBACK
collect_processor_time( struct counter
*counter
)
191 counter
->two
.largevalue
= 500000; /* FIXME */
192 counter
->status
= PDH_CSTATUS_VALID_DATA
;
195 static void CALLBACK
collect_uptime( struct counter
*counter
)
197 counter
->two
.largevalue
= GetTickCount64();
198 counter
->status
= PDH_CSTATUS_VALID_DATA
;
201 #define TYPE_PROCESSOR_TIME \
202 (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | PERF_TIMER_100NS | PERF_DELTA_COUNTER | \
203 PERF_INVERSE_COUNTER | PERF_DISPLAY_PERCENT)
205 #define TYPE_UPTIME \
206 (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_ELAPSED | PERF_OBJECT_TIMER | PERF_DISPLAY_SECONDS)
208 /* counter source registry */
209 static const struct source counter_sources
[] =
211 { 6, path_processor_time
, collect_processor_time
, TYPE_PROCESSOR_TIME
, -5, 10000000 },
212 { 238, path_processor
, NULL
, 0, 0, 0 },
213 { 674, path_uptime
, collect_uptime
, TYPE_UPTIME
, -3, 1000 }
216 static BOOL
is_local_machine( const WCHAR
*name
, DWORD len
)
218 WCHAR buf
[MAX_COMPUTERNAME_LENGTH
+ 1];
219 DWORD buflen
= ARRAY_SIZE(buf
);
221 if (!GetComputerNameW( buf
, &buflen
)) return FALSE
;
222 return len
== buflen
&& !_wcsnicmp( name
, buf
, buflen
);
225 static BOOL
pdh_match_path( LPCWSTR fullpath
, LPCWSTR path
)
229 if (path
[0] == '\\' && path
[1] == '\\' && (p
= wcschr( path
+ 2, '\\' )) &&
230 is_local_machine( path
+ 2, p
- path
- 2 ))
234 if (wcschr( path
, '\\' )) p
= fullpath
;
235 else p
= wcsrchr( fullpath
, '\\' ) + 1;
236 return !wcscmp( p
, path
);
239 /***********************************************************************
240 * PdhAddCounterA (PDH.@)
242 PDH_STATUS WINAPI
PdhAddCounterA( PDH_HQUERY query
, LPCSTR path
,
243 DWORD_PTR userdata
, PDH_HCOUNTER
*counter
)
248 TRACE("%p %s %lx %p\n", query
, debugstr_a(path
), userdata
, counter
);
250 if (!path
) return PDH_INVALID_ARGUMENT
;
252 if (!(pathW
= pdh_strdup_aw( path
)))
253 return PDH_MEMORY_ALLOCATION_FAILURE
;
255 ret
= PdhAddCounterW( query
, pathW
, userdata
, counter
);
261 /***********************************************************************
262 * PdhAddCounterW (PDH.@)
264 PDH_STATUS WINAPI
PdhAddCounterW( PDH_HQUERY hquery
, LPCWSTR path
,
265 DWORD_PTR userdata
, PDH_HCOUNTER
*hcounter
)
267 struct query
*query
= hquery
;
268 struct counter
*counter
;
271 TRACE("%p %s %lx %p\n", hquery
, debugstr_w(path
), userdata
, hcounter
);
273 if (!path
|| !hcounter
) return PDH_INVALID_ARGUMENT
;
275 EnterCriticalSection( &pdh_handle_cs
);
276 if (!query
|| query
->magic
!= PDH_MAGIC_QUERY
)
278 LeaveCriticalSection( &pdh_handle_cs
);
279 return PDH_INVALID_HANDLE
;
283 for (i
= 0; i
< ARRAY_SIZE(counter_sources
); i
++)
285 if (pdh_match_path( counter_sources
[i
].path
, path
))
287 if ((counter
= create_counter()))
289 counter
->path
= pdh_strdup( counter_sources
[i
].path
);
290 counter
->collect
= counter_sources
[i
].collect
;
291 counter
->type
= counter_sources
[i
].type
;
292 counter
->defaultscale
= counter_sources
[i
].scale
;
293 counter
->base
= counter_sources
[i
].base
;
294 counter
->queryuser
= query
->user
;
295 counter
->user
= userdata
;
297 list_add_tail( &query
->counters
, &counter
->entry
);
300 LeaveCriticalSection( &pdh_handle_cs
);
301 return ERROR_SUCCESS
;
303 LeaveCriticalSection( &pdh_handle_cs
);
304 return PDH_MEMORY_ALLOCATION_FAILURE
;
307 LeaveCriticalSection( &pdh_handle_cs
);
308 return PDH_CSTATUS_NO_COUNTER
;
311 /***********************************************************************
312 * PdhAddEnglishCounterA (PDH.@)
314 PDH_STATUS WINAPI
PdhAddEnglishCounterA( PDH_HQUERY query
, LPCSTR path
,
315 DWORD_PTR userdata
, PDH_HCOUNTER
*counter
)
317 TRACE("%p %s %lx %p\n", query
, debugstr_a(path
), userdata
, counter
);
319 if (!query
) return PDH_INVALID_ARGUMENT
;
320 return PdhAddCounterA( query
, path
, userdata
, counter
);
323 /***********************************************************************
324 * PdhAddEnglishCounterW (PDH.@)
326 PDH_STATUS WINAPI
PdhAddEnglishCounterW( PDH_HQUERY query
, LPCWSTR path
,
327 DWORD_PTR userdata
, PDH_HCOUNTER
*counter
)
329 TRACE("%p %s %lx %p\n", query
, debugstr_w(path
), userdata
, counter
);
331 if (!query
) return PDH_INVALID_ARGUMENT
;
332 return PdhAddCounterW( query
, path
, userdata
, counter
);
335 /* caller must hold counter lock */
336 static PDH_STATUS
format_value( struct counter
*counter
, DWORD format
, union value
*raw1
,
337 union value
*raw2
, PDH_FMT_COUNTERVALUE
*value
)
341 factor
= counter
->scale
? counter
->scale
: counter
->defaultscale
;
342 if (format
& PDH_FMT_LONG
)
344 if (format
& PDH_FMT_1000
) value
->u
.longValue
= raw2
->longvalue
* 1000;
345 else value
->u
.longValue
= raw2
->longvalue
* pow( 10, factor
);
347 else if (format
& PDH_FMT_LARGE
)
349 if (format
& PDH_FMT_1000
) value
->u
.largeValue
= raw2
->largevalue
* 1000;
350 else value
->u
.largeValue
= raw2
->largevalue
* pow( 10, factor
);
352 else if (format
& PDH_FMT_DOUBLE
)
354 if (format
& PDH_FMT_1000
) value
->u
.doubleValue
= raw2
->doublevalue
* 1000;
355 else value
->u
.doubleValue
= raw2
->doublevalue
* pow( 10, factor
);
359 WARN("unknown format %x\n", format
);
360 return PDH_INVALID_ARGUMENT
;
362 return ERROR_SUCCESS
;
365 /***********************************************************************
366 * PdhCalculateCounterFromRawValue (PDH.@)
368 PDH_STATUS WINAPI
PdhCalculateCounterFromRawValue( PDH_HCOUNTER handle
, DWORD format
,
369 PPDH_RAW_COUNTER raw1
, PPDH_RAW_COUNTER raw2
,
370 PPDH_FMT_COUNTERVALUE value
)
373 struct counter
*counter
= handle
;
375 TRACE("%p 0x%08x %p %p %p\n", handle
, format
, raw1
, raw2
, value
);
377 if (!value
) return PDH_INVALID_ARGUMENT
;
379 EnterCriticalSection( &pdh_handle_cs
);
380 if (!counter
|| counter
->magic
!= PDH_MAGIC_COUNTER
)
382 LeaveCriticalSection( &pdh_handle_cs
);
383 return PDH_INVALID_HANDLE
;
386 ret
= format_value( counter
, format
, (union value
*)&raw1
->SecondValue
,
387 (union value
*)&raw2
->SecondValue
, value
);
389 LeaveCriticalSection( &pdh_handle_cs
);
394 /***********************************************************************
395 * PdhCloseQuery (PDH.@)
397 PDH_STATUS WINAPI
PdhCloseQuery( PDH_HQUERY handle
)
399 struct query
*query
= handle
;
400 struct list
*item
, *next
;
402 TRACE("%p\n", handle
);
404 EnterCriticalSection( &pdh_handle_cs
);
405 if (!query
|| query
->magic
!= PDH_MAGIC_QUERY
)
407 LeaveCriticalSection( &pdh_handle_cs
);
408 return PDH_INVALID_HANDLE
;
413 HANDLE thread
= query
->thread
;
414 SetEvent( query
->stop
);
415 LeaveCriticalSection( &pdh_handle_cs
);
417 WaitForSingleObject( thread
, INFINITE
);
419 EnterCriticalSection( &pdh_handle_cs
);
420 if (query
->magic
!= PDH_MAGIC_QUERY
)
422 LeaveCriticalSection( &pdh_handle_cs
);
423 return ERROR_SUCCESS
;
425 CloseHandle( query
->stop
);
426 CloseHandle( query
->thread
);
427 query
->thread
= NULL
;
430 LIST_FOR_EACH_SAFE( item
, next
, &query
->counters
)
432 struct counter
*counter
= LIST_ENTRY( item
, struct counter
, entry
);
434 list_remove( &counter
->entry
);
435 destroy_counter( counter
);
438 destroy_query( query
);
440 LeaveCriticalSection( &pdh_handle_cs
);
441 return ERROR_SUCCESS
;
444 /* caller must hold query lock */
445 static void collect_query_data( struct query
*query
)
449 LIST_FOR_EACH( item
, &query
->counters
)
452 struct counter
*counter
= LIST_ENTRY( item
, struct counter
, entry
);
454 counter
->collect( counter
);
456 GetLocalTime( &time
);
457 SystemTimeToFileTime( &time
, &counter
->stamp
);
461 /***********************************************************************
462 * PdhCollectQueryData (PDH.@)
464 PDH_STATUS WINAPI
PdhCollectQueryData( PDH_HQUERY handle
)
466 struct query
*query
= handle
;
468 TRACE("%p\n", handle
);
470 EnterCriticalSection( &pdh_handle_cs
);
471 if (!query
|| query
->magic
!= PDH_MAGIC_QUERY
)
473 LeaveCriticalSection( &pdh_handle_cs
);
474 return PDH_INVALID_HANDLE
;
477 if (list_empty( &query
->counters
))
479 LeaveCriticalSection( &pdh_handle_cs
);
483 collect_query_data( query
);
485 LeaveCriticalSection( &pdh_handle_cs
);
486 return ERROR_SUCCESS
;
489 static DWORD CALLBACK
collect_query_thread( void *arg
)
491 struct query
*query
= arg
;
492 DWORD interval
= query
->interval
;
493 HANDLE stop
= query
->stop
;
497 if (WaitForSingleObject( stop
, interval
) != WAIT_TIMEOUT
) ExitThread( 0 );
499 EnterCriticalSection( &pdh_handle_cs
);
500 if (query
->magic
!= PDH_MAGIC_QUERY
)
502 LeaveCriticalSection( &pdh_handle_cs
);
503 ExitThread( PDH_INVALID_HANDLE
);
506 collect_query_data( query
);
508 if (!SetEvent( query
->wait
))
510 LeaveCriticalSection( &pdh_handle_cs
);
513 LeaveCriticalSection( &pdh_handle_cs
);
517 /***********************************************************************
518 * PdhCollectQueryDataEx (PDH.@)
520 PDH_STATUS WINAPI
PdhCollectQueryDataEx( PDH_HQUERY handle
, DWORD interval
, HANDLE event
)
523 struct query
*query
= handle
;
525 TRACE("%p %d %p\n", handle
, interval
, event
);
527 EnterCriticalSection( &pdh_handle_cs
);
528 if (!query
|| query
->magic
!= PDH_MAGIC_QUERY
)
530 LeaveCriticalSection( &pdh_handle_cs
);
531 return PDH_INVALID_HANDLE
;
533 if (list_empty( &query
->counters
))
535 LeaveCriticalSection( &pdh_handle_cs
);
540 HANDLE thread
= query
->thread
;
541 SetEvent( query
->stop
);
542 LeaveCriticalSection( &pdh_handle_cs
);
544 WaitForSingleObject( thread
, INFINITE
);
546 EnterCriticalSection( &pdh_handle_cs
);
547 if (query
->magic
!= PDH_MAGIC_QUERY
)
549 LeaveCriticalSection( &pdh_handle_cs
);
550 return PDH_INVALID_HANDLE
;
552 CloseHandle( query
->thread
);
553 query
->thread
= NULL
;
555 else if (!(query
->stop
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
)))
557 ret
= GetLastError();
558 LeaveCriticalSection( &pdh_handle_cs
);
562 query
->interval
= interval
* 1000;
563 if (!(query
->thread
= CreateThread( NULL
, 0, collect_query_thread
, query
, 0, NULL
)))
565 ret
= GetLastError();
566 CloseHandle( query
->stop
);
568 LeaveCriticalSection( &pdh_handle_cs
);
572 LeaveCriticalSection( &pdh_handle_cs
);
573 return ERROR_SUCCESS
;
576 /***********************************************************************
577 * PdhCollectQueryDataWithTime (PDH.@)
579 PDH_STATUS WINAPI
PdhCollectQueryDataWithTime( PDH_HQUERY handle
, LONGLONG
*timestamp
)
581 struct query
*query
= handle
;
582 struct counter
*counter
;
585 TRACE("%p %p\n", handle
, timestamp
);
587 if (!timestamp
) return PDH_INVALID_ARGUMENT
;
589 EnterCriticalSection( &pdh_handle_cs
);
590 if (!query
|| query
->magic
!= PDH_MAGIC_QUERY
)
592 LeaveCriticalSection( &pdh_handle_cs
);
593 return PDH_INVALID_HANDLE
;
595 if (list_empty( &query
->counters
))
597 LeaveCriticalSection( &pdh_handle_cs
);
601 collect_query_data( query
);
603 item
= list_head( &query
->counters
);
604 counter
= LIST_ENTRY( item
, struct counter
, entry
);
606 *timestamp
= ((LONGLONG
)counter
->stamp
.dwHighDateTime
<< 32) | counter
->stamp
.dwLowDateTime
;
608 LeaveCriticalSection( &pdh_handle_cs
);
609 return ERROR_SUCCESS
;
612 /***********************************************************************
613 * PdhExpandWildCardPathA (PDH.@)
615 PDH_STATUS WINAPI
PdhExpandWildCardPathA( LPCSTR szDataSource
, LPCSTR szWildCardPath
, LPSTR mszExpandedPathList
, LPDWORD pcchPathListLength
, DWORD dwFlags
)
617 FIXME("%s, %s, %p, %p, 0x%x: stub\n", debugstr_a(szDataSource
), debugstr_a(szWildCardPath
), mszExpandedPathList
, pcchPathListLength
, dwFlags
);
618 return PDH_NOT_IMPLEMENTED
;
621 /***********************************************************************
622 * PdhExpandWildCardPathW (PDH.@)
624 PDH_STATUS WINAPI
PdhExpandWildCardPathW( LPCWSTR szDataSource
, LPCWSTR szWildCardPath
, LPWSTR mszExpandedPathList
, LPDWORD pcchPathListLength
, DWORD dwFlags
)
626 FIXME("%s, %s, %p, %p, 0x%x: stub\n", debugstr_w(szDataSource
), debugstr_w(szWildCardPath
), mszExpandedPathList
, pcchPathListLength
, dwFlags
);
627 return PDH_NOT_IMPLEMENTED
;
630 /***********************************************************************
631 * PdhExpandCounterPathA (PDH.@)
633 PDH_STATUS WINAPI
PdhExpandCounterPathA( LPCSTR szWildCardPath
, LPSTR mszExpandedPathList
, LPDWORD pcchPathListLength
)
635 FIXME("%s, %p, %p: stub\n", debugstr_a(szWildCardPath
), mszExpandedPathList
, pcchPathListLength
);
636 return PdhExpandWildCardPathA(NULL
, szWildCardPath
, mszExpandedPathList
, pcchPathListLength
, 0);
639 /***********************************************************************
640 * PdhExpandCounterPathW (PDH.@)
642 PDH_STATUS WINAPI
PdhExpandCounterPathW( LPCWSTR szWildCardPath
, LPWSTR mszExpandedPathList
, LPDWORD pcchPathListLength
)
644 FIXME("%s, %p, %p: stub\n", debugstr_w(szWildCardPath
), mszExpandedPathList
, pcchPathListLength
);
645 return PdhExpandWildCardPathW(NULL
, szWildCardPath
, mszExpandedPathList
, pcchPathListLength
, 0);
648 /***********************************************************************
649 * PdhGetCounterInfoA (PDH.@)
651 PDH_STATUS WINAPI
PdhGetCounterInfoA( PDH_HCOUNTER handle
, BOOLEAN text
, LPDWORD size
, PPDH_COUNTER_INFO_A info
)
653 struct counter
*counter
= handle
;
655 TRACE("%p %d %p %p\n", handle
, text
, size
, info
);
657 EnterCriticalSection( &pdh_handle_cs
);
658 if (!counter
|| counter
->magic
!= PDH_MAGIC_COUNTER
)
660 LeaveCriticalSection( &pdh_handle_cs
);
661 return PDH_INVALID_HANDLE
;
665 LeaveCriticalSection( &pdh_handle_cs
);
666 return PDH_INVALID_ARGUMENT
;
668 if (*size
< sizeof(PDH_COUNTER_INFO_A
))
670 *size
= sizeof(PDH_COUNTER_INFO_A
);
671 LeaveCriticalSection( &pdh_handle_cs
);
672 return PDH_MORE_DATA
;
675 memset( info
, 0, sizeof(PDH_COUNTER_INFO_A
) );
677 info
->dwType
= counter
->type
;
678 info
->CStatus
= counter
->status
;
679 info
->lScale
= counter
->scale
;
680 info
->lDefaultScale
= counter
->defaultscale
;
681 info
->dwUserData
= counter
->user
;
682 info
->dwQueryUserData
= counter
->queryuser
;
684 *size
= sizeof(PDH_COUNTER_INFO_A
);
686 LeaveCriticalSection( &pdh_handle_cs
);
687 return ERROR_SUCCESS
;
690 /***********************************************************************
691 * PdhGetCounterInfoW (PDH.@)
693 PDH_STATUS WINAPI
PdhGetCounterInfoW( PDH_HCOUNTER handle
, BOOLEAN text
, LPDWORD size
, PPDH_COUNTER_INFO_W info
)
695 struct counter
*counter
= handle
;
697 TRACE("%p %d %p %p\n", handle
, text
, size
, info
);
699 EnterCriticalSection( &pdh_handle_cs
);
700 if (!counter
|| counter
->magic
!= PDH_MAGIC_COUNTER
)
702 LeaveCriticalSection( &pdh_handle_cs
);
703 return PDH_INVALID_HANDLE
;
707 LeaveCriticalSection( &pdh_handle_cs
);
708 return PDH_INVALID_ARGUMENT
;
710 if (*size
< sizeof(PDH_COUNTER_INFO_W
))
712 *size
= sizeof(PDH_COUNTER_INFO_W
);
713 LeaveCriticalSection( &pdh_handle_cs
);
714 return PDH_MORE_DATA
;
717 memset( info
, 0, sizeof(PDH_COUNTER_INFO_W
) );
719 info
->dwType
= counter
->type
;
720 info
->CStatus
= counter
->status
;
721 info
->lScale
= counter
->scale
;
722 info
->lDefaultScale
= counter
->defaultscale
;
723 info
->dwUserData
= counter
->user
;
724 info
->dwQueryUserData
= counter
->queryuser
;
726 *size
= sizeof(PDH_COUNTER_INFO_W
);
728 LeaveCriticalSection( &pdh_handle_cs
);
729 return ERROR_SUCCESS
;
732 /***********************************************************************
733 * PdhGetCounterTimeBase (PDH.@)
735 PDH_STATUS WINAPI
PdhGetCounterTimeBase( PDH_HCOUNTER handle
, LONGLONG
*base
)
737 struct counter
*counter
= handle
;
739 TRACE("%p %p\n", handle
, base
);
741 if (!base
) return PDH_INVALID_ARGUMENT
;
743 EnterCriticalSection( &pdh_handle_cs
);
744 if (!counter
|| counter
->magic
!= PDH_MAGIC_COUNTER
)
746 LeaveCriticalSection( &pdh_handle_cs
);
747 return PDH_INVALID_HANDLE
;
750 *base
= counter
->base
;
752 LeaveCriticalSection( &pdh_handle_cs
);
753 return ERROR_SUCCESS
;
756 /***********************************************************************
757 * PdhGetDllVersion (PDH.@)
759 PDH_STATUS WINAPI
PdhGetDllVersion( LPDWORD version
)
762 return PDH_INVALID_ARGUMENT
;
764 *version
= PDH_VERSION
;
766 return ERROR_SUCCESS
;
769 /***********************************************************************
770 * PdhGetFormattedCounterValue (PDH.@)
772 PDH_STATUS WINAPI
PdhGetFormattedCounterValue( PDH_HCOUNTER handle
, DWORD format
,
773 LPDWORD type
, PPDH_FMT_COUNTERVALUE value
)
776 struct counter
*counter
= handle
;
778 TRACE("%p %x %p %p\n", handle
, format
, type
, value
);
780 if (!value
) return PDH_INVALID_ARGUMENT
;
782 EnterCriticalSection( &pdh_handle_cs
);
783 if (!counter
|| counter
->magic
!= PDH_MAGIC_COUNTER
)
785 LeaveCriticalSection( &pdh_handle_cs
);
786 return PDH_INVALID_HANDLE
;
790 LeaveCriticalSection( &pdh_handle_cs
);
791 return PDH_INVALID_DATA
;
793 if (!(ret
= format_value( counter
, format
, &counter
->one
, &counter
->two
, value
)))
795 value
->CStatus
= ERROR_SUCCESS
;
796 if (type
) *type
= counter
->type
;
799 LeaveCriticalSection( &pdh_handle_cs
);
803 /***********************************************************************
804 * PdhGetRawCounterValue (PDH.@)
806 PDH_STATUS WINAPI
PdhGetRawCounterValue( PDH_HCOUNTER handle
, LPDWORD type
,
807 PPDH_RAW_COUNTER value
)
809 struct counter
*counter
= handle
;
811 TRACE("%p %p %p\n", handle
, type
, value
);
813 if (!value
) return PDH_INVALID_ARGUMENT
;
815 EnterCriticalSection( &pdh_handle_cs
);
816 if (!counter
|| counter
->magic
!= PDH_MAGIC_COUNTER
)
818 LeaveCriticalSection( &pdh_handle_cs
);
819 return PDH_INVALID_HANDLE
;
822 value
->CStatus
= counter
->status
;
823 value
->TimeStamp
.dwLowDateTime
= counter
->stamp
.dwLowDateTime
;
824 value
->TimeStamp
.dwHighDateTime
= counter
->stamp
.dwHighDateTime
;
825 value
->FirstValue
= counter
->one
.largevalue
;
826 value
->SecondValue
= counter
->two
.largevalue
;
827 value
->MultiCount
= 1; /* FIXME */
829 if (type
) *type
= counter
->type
;
831 LeaveCriticalSection( &pdh_handle_cs
);
832 return ERROR_SUCCESS
;
835 /***********************************************************************
836 * PdhLookupPerfIndexByNameA (PDH.@)
838 PDH_STATUS WINAPI
PdhLookupPerfIndexByNameA( LPCSTR machine
, LPCSTR name
, LPDWORD index
)
841 WCHAR
*machineW
= NULL
;
844 TRACE("%s %s %p\n", debugstr_a(machine
), debugstr_a(name
), index
);
846 if (!name
) return PDH_INVALID_ARGUMENT
;
848 if (machine
&& !(machineW
= pdh_strdup_aw( machine
))) return PDH_MEMORY_ALLOCATION_FAILURE
;
850 if (!(nameW
= pdh_strdup_aw( name
)))
851 return PDH_MEMORY_ALLOCATION_FAILURE
;
853 ret
= PdhLookupPerfIndexByNameW( machineW
, nameW
, index
);
856 heap_free( machineW
);
860 /***********************************************************************
861 * PdhLookupPerfIndexByNameW (PDH.@)
863 PDH_STATUS WINAPI
PdhLookupPerfIndexByNameW( LPCWSTR machine
, LPCWSTR name
, LPDWORD index
)
867 TRACE("%s %s %p\n", debugstr_w(machine
), debugstr_w(name
), index
);
869 if (!name
|| !index
) return PDH_INVALID_ARGUMENT
;
873 FIXME("remote machine not supported\n");
874 return PDH_CSTATUS_NO_MACHINE
;
876 for (i
= 0; i
< ARRAY_SIZE(counter_sources
); i
++)
878 if (pdh_match_path( counter_sources
[i
].path
, name
))
880 *index
= counter_sources
[i
].index
;
881 return ERROR_SUCCESS
;
884 return PDH_STRING_NOT_FOUND
;
887 /***********************************************************************
888 * PdhLookupPerfNameByIndexA (PDH.@)
890 PDH_STATUS WINAPI
PdhLookupPerfNameByIndexA( LPCSTR machine
, DWORD index
, LPSTR buffer
, LPDWORD size
)
893 WCHAR
*machineW
= NULL
;
894 WCHAR bufferW
[PDH_MAX_COUNTER_NAME
];
895 DWORD sizeW
= ARRAY_SIZE(bufferW
);
897 TRACE("%s %d %p %p\n", debugstr_a(machine
), index
, buffer
, size
);
899 if (!buffer
|| !size
) return PDH_INVALID_ARGUMENT
;
901 if (machine
&& !(machineW
= pdh_strdup_aw( machine
))) return PDH_MEMORY_ALLOCATION_FAILURE
;
903 if (!(ret
= PdhLookupPerfNameByIndexW( machineW
, index
, bufferW
, &sizeW
)))
905 int required
= WideCharToMultiByte( CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
907 if (*size
< required
) ret
= PDH_MORE_DATA
;
908 else WideCharToMultiByte( CP_ACP
, 0, bufferW
, -1, buffer
, required
, NULL
, NULL
);
911 heap_free( machineW
);
915 /***********************************************************************
916 * PdhLookupPerfNameByIndexW (PDH.@)
918 PDH_STATUS WINAPI
PdhLookupPerfNameByIndexW( LPCWSTR machine
, DWORD index
, LPWSTR buffer
, LPDWORD size
)
923 TRACE("%s %d %p %p\n", debugstr_w(machine
), index
, buffer
, size
);
927 FIXME("remote machine not supported\n");
928 return PDH_CSTATUS_NO_MACHINE
;
931 if (!buffer
|| !size
) return PDH_INVALID_ARGUMENT
;
932 if (!index
) return ERROR_SUCCESS
;
934 for (i
= 0; i
< ARRAY_SIZE(counter_sources
); i
++)
936 if (counter_sources
[i
].index
== index
)
938 WCHAR
*p
= wcsrchr( counter_sources
[i
].path
, '\\' ) + 1;
939 unsigned int required
= lstrlenW( p
) + 1;
941 if (*size
< required
) ret
= PDH_MORE_DATA
;
944 lstrcpyW( buffer
, p
);
951 return PDH_INVALID_ARGUMENT
;
954 /***********************************************************************
955 * PdhOpenQueryA (PDH.@)
957 PDH_STATUS WINAPI
PdhOpenQueryA( LPCSTR source
, DWORD_PTR userdata
, PDH_HQUERY
*query
)
960 WCHAR
*sourceW
= NULL
;
962 TRACE("%s %lx %p\n", debugstr_a(source
), userdata
, query
);
964 if (source
&& !(sourceW
= pdh_strdup_aw( source
))) return PDH_MEMORY_ALLOCATION_FAILURE
;
966 ret
= PdhOpenQueryW( sourceW
, userdata
, query
);
967 heap_free( sourceW
);
972 /***********************************************************************
973 * PdhOpenQueryW (PDH.@)
975 PDH_STATUS WINAPI
PdhOpenQueryW( LPCWSTR source
, DWORD_PTR userdata
, PDH_HQUERY
*handle
)
979 TRACE("%s %lx %p\n", debugstr_w(source
), userdata
, handle
);
981 if (!handle
) return PDH_INVALID_ARGUMENT
;
985 FIXME("log file data source not supported\n");
986 return PDH_INVALID_ARGUMENT
;
988 if ((query
= create_query()))
990 query
->user
= userdata
;
993 return ERROR_SUCCESS
;
995 return PDH_MEMORY_ALLOCATION_FAILURE
;
998 /***********************************************************************
999 * PdhRemoveCounter (PDH.@)
1001 PDH_STATUS WINAPI
PdhRemoveCounter( PDH_HCOUNTER handle
)
1003 struct counter
*counter
= handle
;
1005 TRACE("%p\n", handle
);
1007 EnterCriticalSection( &pdh_handle_cs
);
1008 if (!counter
|| counter
->magic
!= PDH_MAGIC_COUNTER
)
1010 LeaveCriticalSection( &pdh_handle_cs
);
1011 return PDH_INVALID_HANDLE
;
1014 list_remove( &counter
->entry
);
1015 destroy_counter( counter
);
1017 LeaveCriticalSection( &pdh_handle_cs
);
1018 return ERROR_SUCCESS
;
1021 /***********************************************************************
1022 * PdhSetCounterScaleFactor (PDH.@)
1024 PDH_STATUS WINAPI
PdhSetCounterScaleFactor( PDH_HCOUNTER handle
, LONG factor
)
1026 struct counter
*counter
= handle
;
1028 TRACE("%p\n", handle
);
1030 EnterCriticalSection( &pdh_handle_cs
);
1031 if (!counter
|| counter
->magic
!= PDH_MAGIC_COUNTER
)
1033 LeaveCriticalSection( &pdh_handle_cs
);
1034 return PDH_INVALID_HANDLE
;
1036 if (factor
< PDH_MIN_SCALE
|| factor
> PDH_MAX_SCALE
)
1038 LeaveCriticalSection( &pdh_handle_cs
);
1039 return PDH_INVALID_ARGUMENT
;
1042 counter
->scale
= factor
;
1044 LeaveCriticalSection( &pdh_handle_cs
);
1045 return ERROR_SUCCESS
;
1048 /***********************************************************************
1049 * PdhValidatePathA (PDH.@)
1051 PDH_STATUS WINAPI
PdhValidatePathA( LPCSTR path
)
1056 TRACE("%s\n", debugstr_a(path
));
1058 if (!path
) return PDH_INVALID_ARGUMENT
;
1059 if (!(pathW
= pdh_strdup_aw( path
))) return PDH_MEMORY_ALLOCATION_FAILURE
;
1061 ret
= PdhValidatePathW( pathW
);
1067 static PDH_STATUS
validate_path( LPCWSTR path
)
1069 if (!path
|| !*path
) return PDH_INVALID_ARGUMENT
;
1070 if (*path
++ != '\\' || !wcschr( path
, '\\' )) return PDH_CSTATUS_BAD_COUNTERNAME
;
1071 return ERROR_SUCCESS
;
1074 /***********************************************************************
1075 * PdhValidatePathW (PDH.@)
1077 PDH_STATUS WINAPI
PdhValidatePathW( LPCWSTR path
)
1082 TRACE("%s\n", debugstr_w(path
));
1084 if ((ret
= validate_path( path
))) return ret
;
1086 for (i
= 0; i
< ARRAY_SIZE(counter_sources
); i
++)
1087 if (pdh_match_path( counter_sources
[i
].path
, path
)) return ERROR_SUCCESS
;
1089 return PDH_CSTATUS_NO_COUNTER
;
1092 /***********************************************************************
1093 * PdhVbAddCounter (PDH.@)
1095 PDH_STATUS WINAPI
PdhVbAddCounter( PDH_HQUERY query
, LPCSTR path
, PDH_HCOUNTER
*counter
)
1097 FIXME("%p, %s, %p: stub!\n", query
, debugstr_a(path
), counter
);
1099 if (!path
) return PDH_INVALID_ARGUMENT
;
1101 return PDH_NOT_IMPLEMENTED
;
1104 /***********************************************************************
1105 * PdhValidatePathExA (PDH.@)
1107 PDH_STATUS WINAPI
PdhValidatePathExA( PDH_HLOG source
, LPCSTR path
)
1109 TRACE("%p %s\n", source
, debugstr_a(path
));
1113 FIXME("log file data source not supported\n");
1114 return ERROR_SUCCESS
;
1116 return PdhValidatePathA( path
);
1119 /***********************************************************************
1120 * PdhValidatePathExW (PDH.@)
1122 PDH_STATUS WINAPI
PdhValidatePathExW( PDH_HLOG source
, LPCWSTR path
)
1124 TRACE("%p %s\n", source
, debugstr_w(path
));
1128 FIXME("log file data source not supported\n");
1129 return ERROR_SUCCESS
;
1131 return PdhValidatePathW( path
);
1134 /***********************************************************************
1135 * PdhMakeCounterPathA (PDH.@)
1137 PDH_STATUS WINAPI
PdhMakeCounterPathA( PDH_COUNTER_PATH_ELEMENTS_A
*e
, LPSTR buffer
,
1138 LPDWORD buflen
, DWORD flags
)
1140 PDH_STATUS ret
= PDH_MEMORY_ALLOCATION_FAILURE
;
1141 PDH_COUNTER_PATH_ELEMENTS_W eW
;
1145 TRACE("%p %p %p 0x%08x\n", e
, buffer
, buflen
, flags
);
1147 if (!e
|| !buflen
) return PDH_INVALID_ARGUMENT
;
1149 memset( &eW
, 0, sizeof(eW
) );
1150 if (e
->szMachineName
&& !(eW
.szMachineName
= pdh_strdup_aw( e
->szMachineName
))) goto done
;
1151 if (e
->szObjectName
&& !(eW
.szObjectName
= pdh_strdup_aw( e
->szObjectName
))) goto done
;
1152 if (e
->szInstanceName
&& !(eW
.szInstanceName
= pdh_strdup_aw( e
->szInstanceName
))) goto done
;
1153 if (e
->szParentInstance
&& !(eW
.szParentInstance
= pdh_strdup_aw( e
->szParentInstance
))) goto done
;
1154 if (e
->szCounterName
&& !(eW
.szCounterName
= pdh_strdup_aw( e
->szCounterName
))) goto done
;
1155 eW
.dwInstanceIndex
= e
->dwInstanceIndex
;
1158 ret
= PdhMakeCounterPathW( &eW
, NULL
, &buflenW
, flags
);
1159 if (ret
== PDH_MORE_DATA
)
1161 if ((bufferW
= heap_alloc( buflenW
* sizeof(WCHAR
) )))
1163 if (!(ret
= PdhMakeCounterPathW( &eW
, bufferW
, &buflenW
, flags
)))
1165 int len
= WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
1166 if (*buflen
>= len
) WideCharToMultiByte(CP_ACP
, 0, bufferW
, -1, buffer
, *buflen
, NULL
, NULL
);
1167 else ret
= PDH_MORE_DATA
;
1170 heap_free( bufferW
);
1173 ret
= PDH_MEMORY_ALLOCATION_FAILURE
;
1177 heap_free( eW
.szMachineName
);
1178 heap_free( eW
.szObjectName
);
1179 heap_free( eW
.szInstanceName
);
1180 heap_free( eW
.szParentInstance
);
1181 heap_free( eW
.szCounterName
);
1185 /***********************************************************************
1186 * PdhMakeCounterPathW (PDH.@)
1188 PDH_STATUS WINAPI
PdhMakeCounterPathW( PDH_COUNTER_PATH_ELEMENTS_W
*e
, LPWSTR buffer
,
1189 LPDWORD buflen
, DWORD flags
)
1191 static const WCHAR bslash
[] = {'\\',0};
1192 static const WCHAR fslash
[] = {'/',0};
1193 static const WCHAR lparen
[] = {'(',0};
1194 static const WCHAR rparen
[] = {')',0};
1195 static const WCHAR fmt
[] = {'#','%','u',0};
1197 WCHAR path
[PDH_MAX_COUNTER_NAME
], instance
[12];
1198 PDH_STATUS ret
= ERROR_SUCCESS
;
1201 TRACE("%p %p %p 0x%08x\n", e
, buffer
, buflen
, flags
);
1203 if (flags
) FIXME("unimplemented flags 0x%08x\n", flags
);
1205 if (!e
|| !e
->szCounterName
|| !e
->szObjectName
|| !buflen
)
1206 return PDH_INVALID_ARGUMENT
;
1209 if (e
->szMachineName
)
1211 lstrcatW(path
, bslash
);
1212 lstrcatW(path
, bslash
);
1213 lstrcatW(path
, e
->szMachineName
);
1215 lstrcatW(path
, bslash
);
1216 lstrcatW(path
, e
->szObjectName
);
1217 if (e
->szInstanceName
)
1219 lstrcatW(path
, lparen
);
1220 if (e
->szParentInstance
)
1222 lstrcatW(path
, e
->szParentInstance
);
1223 lstrcatW(path
, fslash
);
1225 lstrcatW(path
, e
->szInstanceName
);
1226 swprintf(instance
, fmt
, e
->dwInstanceIndex
);
1227 lstrcatW(path
, instance
);
1228 lstrcatW(path
, rparen
);
1230 lstrcatW(path
, bslash
);
1231 lstrcatW(path
, e
->szCounterName
);
1233 len
= lstrlenW(path
) + 1;
1234 if (*buflen
>= len
) lstrcpyW(buffer
, path
);
1235 else ret
= PDH_MORE_DATA
;
1240 /***********************************************************************
1241 * PdhEnumObjectItemsA (PDH.@)
1243 PDH_STATUS WINAPI
PdhEnumObjectItemsA(LPCSTR szDataSource
, LPCSTR szMachineName
, LPCSTR szObjectName
,
1244 LPSTR mszCounterList
, LPDWORD pcchCounterListLength
, LPSTR mszInstanceList
,
1245 LPDWORD pcchInstanceListLength
, DWORD dwDetailLevel
, DWORD dwFlags
)
1247 FIXME("%s, %s, %s, %p, %p, %p, %p, %d, 0x%x: stub\n", debugstr_a(szDataSource
), debugstr_a(szMachineName
),
1248 debugstr_a(szObjectName
), mszCounterList
, pcchCounterListLength
, mszInstanceList
,
1249 pcchInstanceListLength
, dwDetailLevel
, dwFlags
);
1251 return PDH_NOT_IMPLEMENTED
;
1254 /***********************************************************************
1255 * PdhEnumObjectItemsW (PDH.@)
1257 PDH_STATUS WINAPI
PdhEnumObjectItemsW(LPCWSTR szDataSource
, LPCWSTR szMachineName
, LPCWSTR szObjectName
,
1258 LPWSTR mszCounterList
, LPDWORD pcchCounterListLength
, LPWSTR mszInstanceList
,
1259 LPDWORD pcchInstanceListLength
, DWORD dwDetailLevel
, DWORD dwFlags
)
1261 FIXME("%s, %s, %s, %p, %p, %p, %p, %d, 0x%x: stub\n", debugstr_w(szDataSource
), debugstr_w(szMachineName
),
1262 debugstr_w(szObjectName
), mszCounterList
, pcchCounterListLength
, mszInstanceList
,
1263 pcchInstanceListLength
, dwDetailLevel
, dwFlags
);
1265 return PDH_NOT_IMPLEMENTED
;
1268 /***********************************************************************
1269 * PdhSetDefaultRealTimeDataSource (PDH.@)
1271 PDH_STATUS WINAPI
PdhSetDefaultRealTimeDataSource( DWORD source
)
1273 FIXME("%u\n", source
);
1274 return ERROR_SUCCESS
;
1277 /***********************************************************************
1278 * PdhGetLogFileTypeA (PDH.@)
1280 PDH_STATUS WINAPI
PdhGetLogFileTypeA(const char *log
, DWORD
*type
)
1282 FIXME("%s, %p: stub\n", debugstr_a(log
), type
);
1283 return PDH_NOT_IMPLEMENTED
;
1286 /***********************************************************************
1287 * PdhGetLogFileTypeW (PDH.@)
1289 PDH_STATUS WINAPI
PdhGetLogFileTypeW(const WCHAR
*log
, DWORD
*type
)
1291 FIXME("%s, %p: stub\n", debugstr_w(log
), type
);
1292 return PDH_NOT_IMPLEMENTED
;
1295 /***********************************************************************
1296 * PdhBindInputDataSourceA (PDH.@)
1298 PDH_STATUS WINAPI
PdhBindInputDataSourceA(PDH_HLOG
*source
, const char *filenamelist
)
1300 FIXME("%p %s: stub\n", source
, debugstr_a(filenamelist
));
1301 return PDH_NOT_IMPLEMENTED
;
1304 /***********************************************************************
1305 * PdhBindInputDataSourceW (PDH.@)
1307 PDH_STATUS WINAPI
PdhBindInputDataSourceW(PDH_HLOG
*source
, const WCHAR
*filenamelist
)
1309 FIXME("%p %s: stub\n", source
, debugstr_w(filenamelist
));
1310 return PDH_NOT_IMPLEMENTED
;