hidclass.sys: Return STATUS_INVALID_USER_BUFFER if buffer_len is 0.
[wine.git] / dlls / pdh / pdh_main.c
blob3840b9d0288fa3ae941eba21db779c78d4152910
1 /*
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
22 #include <stdarg.h>
23 #include <math.h>
25 #define NONAMELESSUNION
27 #include "windef.h"
28 #include "winbase.h"
30 #include "pdh.h"
31 #include "pdhmsg.h"
32 #include "winperf.h"
34 #include "wine/debug.h"
35 #include "wine/heap.h"
36 #include "wine/list.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(pdh);
40 static CRITICAL_SECTION pdh_handle_cs;
41 static CRITICAL_SECTION_DEBUG pdh_handle_cs_debug =
43 0, 0, &pdh_handle_cs,
44 { &pdh_handle_cs_debug.ProcessLocksList,
45 &pdh_handle_cs_debug.ProcessLocksList },
46 0, 0, { (DWORD_PTR)(__FILE__ ": pdh_handle_cs") }
48 static CRITICAL_SECTION pdh_handle_cs = { &pdh_handle_cs_debug, -1, 0, 0, 0, 0 };
50 static inline WCHAR *pdh_strdup( const WCHAR *src )
52 WCHAR *dst;
54 if (!src) return NULL;
55 if ((dst = heap_alloc( (lstrlenW( src ) + 1) * sizeof(WCHAR) ))) lstrcpyW( dst, src );
56 return dst;
59 static inline WCHAR *pdh_strdup_aw( const char *src )
61 int len;
62 WCHAR *dst;
64 if (!src) return NULL;
65 len = MultiByteToWideChar( CP_ACP, 0, src, -1, NULL, 0 );
66 if ((dst = heap_alloc( len * sizeof(WCHAR) ))) MultiByteToWideChar( CP_ACP, 0, src, -1, dst, len );
67 return dst;
70 union value
72 LONG longvalue;
73 double doublevalue;
74 LONGLONG largevalue;
77 struct counter
79 DWORD magic; /* signature */
80 struct list entry; /* list entry */
81 WCHAR *path; /* identifier */
82 DWORD type; /* counter type */
83 DWORD status; /* update status */
84 LONG scale; /* scale factor */
85 LONG defaultscale; /* default scale factor */
86 DWORD_PTR user; /* user data */
87 DWORD_PTR queryuser; /* query user data */
88 LONGLONG base; /* samples per second */
89 FILETIME stamp; /* time stamp */
90 void (CALLBACK *collect)( struct counter * ); /* collect callback */
91 union value one; /* first value */
92 union value two; /* second value */
95 #define PDH_MAGIC_COUNTER 0x50444831 /* 'PDH1' */
97 static struct counter *create_counter( void )
99 struct counter *counter;
101 if ((counter = heap_alloc_zero( sizeof(struct counter) )))
103 counter->magic = PDH_MAGIC_COUNTER;
104 return counter;
106 return NULL;
109 static void destroy_counter( struct counter *counter )
111 counter->magic = 0;
112 heap_free( counter->path );
113 heap_free( counter );
116 #define PDH_MAGIC_QUERY 0x50444830 /* 'PDH0' */
118 struct query
120 DWORD magic; /* signature */
121 DWORD_PTR user; /* user data */
122 HANDLE thread; /* collect thread */
123 DWORD interval; /* collect interval */
124 HANDLE wait; /* wait event */
125 HANDLE stop; /* stop event */
126 struct list counters; /* counter list */
129 static struct query *create_query( void )
131 struct query *query;
133 if ((query = heap_alloc_zero( sizeof(struct query) )))
135 query->magic = PDH_MAGIC_QUERY;
136 list_init( &query->counters );
137 return query;
139 return NULL;
142 static void destroy_query( struct query *query )
144 query->magic = 0;
145 heap_free( query );
148 struct source
150 DWORD index; /* name index */
151 const WCHAR *path; /* identifier */
152 void (CALLBACK *collect)( struct counter * ); /* collect callback */
153 DWORD type; /* counter type */
154 LONG scale; /* default scale factor */
155 LONGLONG base; /* samples per second */
158 static void CALLBACK collect_processor_time( struct counter *counter )
160 counter->two.largevalue = 500000; /* FIXME */
161 counter->status = PDH_CSTATUS_VALID_DATA;
164 static void CALLBACK collect_uptime( struct counter *counter )
166 counter->two.largevalue = GetTickCount64();
167 counter->status = PDH_CSTATUS_VALID_DATA;
170 #define TYPE_PROCESSOR_TIME \
171 (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | PERF_TIMER_100NS | PERF_DELTA_COUNTER | \
172 PERF_INVERSE_COUNTER | PERF_DISPLAY_PERCENT)
174 #define TYPE_UPTIME \
175 (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_ELAPSED | PERF_OBJECT_TIMER | PERF_DISPLAY_SECONDS)
177 /* counter source registry */
178 static const struct source counter_sources[] =
180 { 6, L"\\Processor(_Total)\\% Processor Time", collect_processor_time, TYPE_PROCESSOR_TIME, -5, 10000000 },
181 { 674, L"\\System\\System Up Time", collect_uptime, TYPE_UPTIME, -3, 1000 }
184 static BOOL is_local_machine( const WCHAR *name, DWORD len )
186 WCHAR buf[MAX_COMPUTERNAME_LENGTH + 1];
187 DWORD buflen = ARRAY_SIZE(buf);
189 if (!GetComputerNameW( buf, &buflen )) return FALSE;
190 return len == buflen && !wcsnicmp( name, buf, buflen );
193 static BOOL pdh_match_path( LPCWSTR fullpath, LPCWSTR path )
195 const WCHAR *p;
197 if (path[0] == '\\' && path[1] == '\\' && (p = wcschr( path + 2, '\\' )) &&
198 is_local_machine( path + 2, p - path - 2 ))
200 path += p - path;
202 if (wcschr( path, '\\' )) p = fullpath;
203 else p = wcsrchr( fullpath, '\\' ) + 1;
204 return !wcscmp( p, path );
207 /***********************************************************************
208 * PdhAddCounterA (PDH.@)
210 PDH_STATUS WINAPI PdhAddCounterA( PDH_HQUERY query, LPCSTR path,
211 DWORD_PTR userdata, PDH_HCOUNTER *counter )
213 PDH_STATUS ret;
214 WCHAR *pathW;
216 TRACE("%p %s %lx %p\n", query, debugstr_a(path), userdata, counter);
218 if (!path) return PDH_INVALID_ARGUMENT;
220 if (!(pathW = pdh_strdup_aw( path )))
221 return PDH_MEMORY_ALLOCATION_FAILURE;
223 ret = PdhAddCounterW( query, pathW, userdata, counter );
225 heap_free( pathW );
226 return ret;
229 /***********************************************************************
230 * PdhAddCounterW (PDH.@)
232 PDH_STATUS WINAPI PdhAddCounterW( PDH_HQUERY hquery, LPCWSTR path,
233 DWORD_PTR userdata, PDH_HCOUNTER *hcounter )
235 struct query *query = hquery;
236 struct counter *counter;
237 unsigned int i;
239 TRACE("%p %s %lx %p\n", hquery, debugstr_w(path), userdata, hcounter);
241 if (!path || !hcounter) return PDH_INVALID_ARGUMENT;
243 EnterCriticalSection( &pdh_handle_cs );
244 if (!query || query->magic != PDH_MAGIC_QUERY)
246 LeaveCriticalSection( &pdh_handle_cs );
247 return PDH_INVALID_HANDLE;
250 *hcounter = NULL;
251 for (i = 0; i < ARRAY_SIZE(counter_sources); i++)
253 if (pdh_match_path( counter_sources[i].path, path ))
255 if ((counter = create_counter()))
257 counter->path = pdh_strdup( counter_sources[i].path );
258 counter->collect = counter_sources[i].collect;
259 counter->type = counter_sources[i].type;
260 counter->defaultscale = counter_sources[i].scale;
261 counter->base = counter_sources[i].base;
262 counter->queryuser = query->user;
263 counter->user = userdata;
265 list_add_tail( &query->counters, &counter->entry );
266 *hcounter = counter;
268 LeaveCriticalSection( &pdh_handle_cs );
269 return ERROR_SUCCESS;
271 LeaveCriticalSection( &pdh_handle_cs );
272 return PDH_MEMORY_ALLOCATION_FAILURE;
275 LeaveCriticalSection( &pdh_handle_cs );
276 return PDH_CSTATUS_NO_COUNTER;
279 /***********************************************************************
280 * PdhAddEnglishCounterA (PDH.@)
282 PDH_STATUS WINAPI PdhAddEnglishCounterA( PDH_HQUERY query, LPCSTR path,
283 DWORD_PTR userdata, PDH_HCOUNTER *counter )
285 TRACE("%p %s %lx %p\n", query, debugstr_a(path), userdata, counter);
287 if (!counter) return PDH_INVALID_ARGUMENT;
288 if (!query) return PDH_INVALID_HANDLE;
289 return PdhAddCounterA( query, path, userdata, counter );
292 /***********************************************************************
293 * PdhAddEnglishCounterW (PDH.@)
295 PDH_STATUS WINAPI PdhAddEnglishCounterW( PDH_HQUERY query, LPCWSTR path,
296 DWORD_PTR userdata, PDH_HCOUNTER *counter )
298 TRACE("%p %s %lx %p\n", query, debugstr_w(path), userdata, counter);
300 if (!counter) return PDH_INVALID_ARGUMENT;
301 if (!query) return PDH_INVALID_HANDLE;
302 return PdhAddCounterW( query, path, userdata, counter );
305 /* caller must hold counter lock */
306 static PDH_STATUS format_value( struct counter *counter, DWORD format, union value *raw1,
307 union value *raw2, PDH_FMT_COUNTERVALUE *value )
309 LONG factor;
311 factor = counter->scale ? counter->scale : counter->defaultscale;
312 if (format & PDH_FMT_LONG)
314 if (format & PDH_FMT_1000) value->u.longValue = raw2->longvalue * 1000;
315 else value->u.longValue = raw2->longvalue * pow( 10, factor );
317 else if (format & PDH_FMT_LARGE)
319 if (format & PDH_FMT_1000) value->u.largeValue = raw2->largevalue * 1000;
320 else value->u.largeValue = raw2->largevalue * pow( 10, factor );
322 else if (format & PDH_FMT_DOUBLE)
324 if (format & PDH_FMT_1000) value->u.doubleValue = raw2->doublevalue * 1000;
325 else value->u.doubleValue = raw2->doublevalue * pow( 10, factor );
327 else
329 WARN("unknown format %x\n", format);
330 return PDH_INVALID_ARGUMENT;
332 return ERROR_SUCCESS;
335 /***********************************************************************
336 * PdhCalculateCounterFromRawValue (PDH.@)
338 PDH_STATUS WINAPI PdhCalculateCounterFromRawValue( PDH_HCOUNTER handle, DWORD format,
339 PPDH_RAW_COUNTER raw1, PPDH_RAW_COUNTER raw2,
340 PPDH_FMT_COUNTERVALUE value )
342 PDH_STATUS ret;
343 struct counter *counter = handle;
345 TRACE("%p 0x%08x %p %p %p\n", handle, format, raw1, raw2, value);
347 if (!value) return PDH_INVALID_ARGUMENT;
349 EnterCriticalSection( &pdh_handle_cs );
350 if (!counter || counter->magic != PDH_MAGIC_COUNTER)
352 LeaveCriticalSection( &pdh_handle_cs );
353 return PDH_INVALID_HANDLE;
356 ret = format_value( counter, format, (union value *)&raw1->SecondValue,
357 (union value *)&raw2->SecondValue, value );
359 LeaveCriticalSection( &pdh_handle_cs );
360 return ret;
364 /***********************************************************************
365 * PdhCloseQuery (PDH.@)
367 PDH_STATUS WINAPI PdhCloseQuery( PDH_HQUERY handle )
369 struct query *query = handle;
370 struct list *item, *next;
372 TRACE("%p\n", handle);
374 EnterCriticalSection( &pdh_handle_cs );
375 if (!query || query->magic != PDH_MAGIC_QUERY)
377 LeaveCriticalSection( &pdh_handle_cs );
378 return PDH_INVALID_HANDLE;
381 if (query->thread)
383 HANDLE thread = query->thread;
384 SetEvent( query->stop );
385 LeaveCriticalSection( &pdh_handle_cs );
387 WaitForSingleObject( thread, INFINITE );
389 EnterCriticalSection( &pdh_handle_cs );
390 if (query->magic != PDH_MAGIC_QUERY)
392 LeaveCriticalSection( &pdh_handle_cs );
393 return ERROR_SUCCESS;
395 CloseHandle( query->stop );
396 CloseHandle( query->thread );
397 query->thread = NULL;
400 LIST_FOR_EACH_SAFE( item, next, &query->counters )
402 struct counter *counter = LIST_ENTRY( item, struct counter, entry );
404 list_remove( &counter->entry );
405 destroy_counter( counter );
408 destroy_query( query );
410 LeaveCriticalSection( &pdh_handle_cs );
411 return ERROR_SUCCESS;
414 /* caller must hold query lock */
415 static void collect_query_data( struct query *query )
417 struct list *item;
419 LIST_FOR_EACH( item, &query->counters )
421 SYSTEMTIME time;
422 struct counter *counter = LIST_ENTRY( item, struct counter, entry );
424 counter->collect( counter );
426 GetLocalTime( &time );
427 SystemTimeToFileTime( &time, &counter->stamp );
431 /***********************************************************************
432 * PdhCollectQueryData (PDH.@)
434 PDH_STATUS WINAPI PdhCollectQueryData( PDH_HQUERY handle )
436 struct query *query = handle;
438 TRACE("%p\n", handle);
440 EnterCriticalSection( &pdh_handle_cs );
441 if (!query || query->magic != PDH_MAGIC_QUERY)
443 LeaveCriticalSection( &pdh_handle_cs );
444 return PDH_INVALID_HANDLE;
447 if (list_empty( &query->counters ))
449 LeaveCriticalSection( &pdh_handle_cs );
450 return PDH_NO_DATA;
453 collect_query_data( query );
455 LeaveCriticalSection( &pdh_handle_cs );
456 return ERROR_SUCCESS;
459 static DWORD CALLBACK collect_query_thread( void *arg )
461 struct query *query = arg;
462 DWORD interval = query->interval;
463 HANDLE stop = query->stop;
465 for (;;)
467 if (WaitForSingleObject( stop, interval ) != WAIT_TIMEOUT) ExitThread( 0 );
469 EnterCriticalSection( &pdh_handle_cs );
470 if (query->magic != PDH_MAGIC_QUERY)
472 LeaveCriticalSection( &pdh_handle_cs );
473 ExitThread( PDH_INVALID_HANDLE );
476 collect_query_data( query );
478 if (!SetEvent( query->wait ))
480 LeaveCriticalSection( &pdh_handle_cs );
481 ExitThread( 0 );
483 LeaveCriticalSection( &pdh_handle_cs );
487 /***********************************************************************
488 * PdhCollectQueryDataEx (PDH.@)
490 PDH_STATUS WINAPI PdhCollectQueryDataEx( PDH_HQUERY handle, DWORD interval, HANDLE event )
492 PDH_STATUS ret;
493 struct query *query = handle;
495 TRACE("%p %d %p\n", handle, interval, event);
497 EnterCriticalSection( &pdh_handle_cs );
498 if (!query || query->magic != PDH_MAGIC_QUERY)
500 LeaveCriticalSection( &pdh_handle_cs );
501 return PDH_INVALID_HANDLE;
503 if (list_empty( &query->counters ))
505 LeaveCriticalSection( &pdh_handle_cs );
506 return PDH_NO_DATA;
508 if (query->thread)
510 HANDLE thread = query->thread;
511 SetEvent( query->stop );
512 LeaveCriticalSection( &pdh_handle_cs );
514 WaitForSingleObject( thread, INFINITE );
516 EnterCriticalSection( &pdh_handle_cs );
517 if (query->magic != PDH_MAGIC_QUERY)
519 LeaveCriticalSection( &pdh_handle_cs );
520 return PDH_INVALID_HANDLE;
522 CloseHandle( query->thread );
523 query->thread = NULL;
525 else if (!(query->stop = CreateEventW( NULL, FALSE, FALSE, NULL )))
527 ret = GetLastError();
528 LeaveCriticalSection( &pdh_handle_cs );
529 return ret;
531 query->wait = event;
532 query->interval = interval * 1000;
533 if (!(query->thread = CreateThread( NULL, 0, collect_query_thread, query, 0, NULL )))
535 ret = GetLastError();
536 CloseHandle( query->stop );
538 LeaveCriticalSection( &pdh_handle_cs );
539 return ret;
542 LeaveCriticalSection( &pdh_handle_cs );
543 return ERROR_SUCCESS;
546 /***********************************************************************
547 * PdhCollectQueryDataWithTime (PDH.@)
549 PDH_STATUS WINAPI PdhCollectQueryDataWithTime( PDH_HQUERY handle, LONGLONG *timestamp )
551 struct query *query = handle;
552 struct counter *counter;
553 struct list *item;
555 TRACE("%p %p\n", handle, timestamp);
557 if (!timestamp) return PDH_INVALID_ARGUMENT;
559 EnterCriticalSection( &pdh_handle_cs );
560 if (!query || query->magic != PDH_MAGIC_QUERY)
562 LeaveCriticalSection( &pdh_handle_cs );
563 return PDH_INVALID_HANDLE;
565 if (list_empty( &query->counters ))
567 LeaveCriticalSection( &pdh_handle_cs );
568 return PDH_NO_DATA;
571 collect_query_data( query );
573 item = list_head( &query->counters );
574 counter = LIST_ENTRY( item, struct counter, entry );
576 *timestamp = ((LONGLONG)counter->stamp.dwHighDateTime << 32) | counter->stamp.dwLowDateTime;
578 LeaveCriticalSection( &pdh_handle_cs );
579 return ERROR_SUCCESS;
582 /***********************************************************************
583 * PdhExpandWildCardPathA (PDH.@)
585 PDH_STATUS WINAPI PdhExpandWildCardPathA( LPCSTR szDataSource, LPCSTR szWildCardPath, LPSTR mszExpandedPathList, LPDWORD pcchPathListLength, DWORD dwFlags )
587 FIXME("%s, %s, %p, %p, 0x%x: stub\n", debugstr_a(szDataSource), debugstr_a(szWildCardPath), mszExpandedPathList, pcchPathListLength, dwFlags);
588 return PDH_NOT_IMPLEMENTED;
591 /***********************************************************************
592 * PdhExpandWildCardPathW (PDH.@)
594 PDH_STATUS WINAPI PdhExpandWildCardPathW( LPCWSTR szDataSource, LPCWSTR szWildCardPath, LPWSTR mszExpandedPathList, LPDWORD pcchPathListLength, DWORD dwFlags )
596 FIXME("%s, %s, %p, %p, 0x%x: stub\n", debugstr_w(szDataSource), debugstr_w(szWildCardPath), mszExpandedPathList, pcchPathListLength, dwFlags);
597 return PDH_NOT_IMPLEMENTED;
600 /***********************************************************************
601 * PdhExpandCounterPathA (PDH.@)
603 PDH_STATUS WINAPI PdhExpandCounterPathA( LPCSTR szWildCardPath, LPSTR mszExpandedPathList, LPDWORD pcchPathListLength )
605 FIXME("%s, %p, %p: stub\n", debugstr_a(szWildCardPath), mszExpandedPathList, pcchPathListLength);
606 return PdhExpandWildCardPathA(NULL, szWildCardPath, mszExpandedPathList, pcchPathListLength, 0);
609 /***********************************************************************
610 * PdhExpandCounterPathW (PDH.@)
612 PDH_STATUS WINAPI PdhExpandCounterPathW( LPCWSTR szWildCardPath, LPWSTR mszExpandedPathList, LPDWORD pcchPathListLength )
614 FIXME("%s, %p, %p: stub\n", debugstr_w(szWildCardPath), mszExpandedPathList, pcchPathListLength);
615 return PdhExpandWildCardPathW(NULL, szWildCardPath, mszExpandedPathList, pcchPathListLength, 0);
618 /***********************************************************************
619 * PdhGetCounterInfoA (PDH.@)
621 PDH_STATUS WINAPI PdhGetCounterInfoA( PDH_HCOUNTER handle, BOOLEAN text, LPDWORD size, PPDH_COUNTER_INFO_A info )
623 struct counter *counter = handle;
625 TRACE("%p %d %p %p\n", handle, text, size, info);
627 EnterCriticalSection( &pdh_handle_cs );
628 if (!counter || counter->magic != PDH_MAGIC_COUNTER)
630 LeaveCriticalSection( &pdh_handle_cs );
631 return PDH_INVALID_HANDLE;
633 if (!size)
635 LeaveCriticalSection( &pdh_handle_cs );
636 return PDH_INVALID_ARGUMENT;
638 if (*size < sizeof(PDH_COUNTER_INFO_A))
640 *size = sizeof(PDH_COUNTER_INFO_A);
641 LeaveCriticalSection( &pdh_handle_cs );
642 return PDH_MORE_DATA;
645 memset( info, 0, sizeof(PDH_COUNTER_INFO_A) );
647 info->dwType = counter->type;
648 info->CStatus = counter->status;
649 info->lScale = counter->scale;
650 info->lDefaultScale = counter->defaultscale;
651 info->dwUserData = counter->user;
652 info->dwQueryUserData = counter->queryuser;
654 *size = sizeof(PDH_COUNTER_INFO_A);
656 LeaveCriticalSection( &pdh_handle_cs );
657 return ERROR_SUCCESS;
660 /***********************************************************************
661 * PdhGetCounterInfoW (PDH.@)
663 PDH_STATUS WINAPI PdhGetCounterInfoW( PDH_HCOUNTER handle, BOOLEAN text, LPDWORD size, PPDH_COUNTER_INFO_W info )
665 struct counter *counter = handle;
667 TRACE("%p %d %p %p\n", handle, text, size, info);
669 EnterCriticalSection( &pdh_handle_cs );
670 if (!counter || counter->magic != PDH_MAGIC_COUNTER)
672 LeaveCriticalSection( &pdh_handle_cs );
673 return PDH_INVALID_HANDLE;
675 if (!size)
677 LeaveCriticalSection( &pdh_handle_cs );
678 return PDH_INVALID_ARGUMENT;
680 if (*size < sizeof(PDH_COUNTER_INFO_W))
682 *size = sizeof(PDH_COUNTER_INFO_W);
683 LeaveCriticalSection( &pdh_handle_cs );
684 return PDH_MORE_DATA;
687 memset( info, 0, sizeof(PDH_COUNTER_INFO_W) );
689 info->dwType = counter->type;
690 info->CStatus = counter->status;
691 info->lScale = counter->scale;
692 info->lDefaultScale = counter->defaultscale;
693 info->dwUserData = counter->user;
694 info->dwQueryUserData = counter->queryuser;
696 *size = sizeof(PDH_COUNTER_INFO_W);
698 LeaveCriticalSection( &pdh_handle_cs );
699 return ERROR_SUCCESS;
702 /***********************************************************************
703 * PdhGetCounterTimeBase (PDH.@)
705 PDH_STATUS WINAPI PdhGetCounterTimeBase( PDH_HCOUNTER handle, LONGLONG *base )
707 struct counter *counter = handle;
709 TRACE("%p %p\n", handle, base);
711 if (!base) return PDH_INVALID_ARGUMENT;
713 EnterCriticalSection( &pdh_handle_cs );
714 if (!counter || counter->magic != PDH_MAGIC_COUNTER)
716 LeaveCriticalSection( &pdh_handle_cs );
717 return PDH_INVALID_HANDLE;
720 *base = counter->base;
722 LeaveCriticalSection( &pdh_handle_cs );
723 return ERROR_SUCCESS;
726 /***********************************************************************
727 * PdhGetDllVersion (PDH.@)
729 PDH_STATUS WINAPI PdhGetDllVersion( LPDWORD version )
731 if (!version)
732 return PDH_INVALID_ARGUMENT;
734 *version = PDH_VERSION;
736 return ERROR_SUCCESS;
739 /***********************************************************************
740 * PdhGetFormattedCounterValue (PDH.@)
742 PDH_STATUS WINAPI PdhGetFormattedCounterValue( PDH_HCOUNTER handle, DWORD format,
743 LPDWORD type, PPDH_FMT_COUNTERVALUE value )
745 PDH_STATUS ret;
746 struct counter *counter = handle;
748 TRACE("%p %x %p %p\n", handle, format, type, value);
750 if (!value) return PDH_INVALID_ARGUMENT;
752 EnterCriticalSection( &pdh_handle_cs );
753 if (!counter || counter->magic != PDH_MAGIC_COUNTER)
755 LeaveCriticalSection( &pdh_handle_cs );
756 return PDH_INVALID_HANDLE;
758 if (counter->status)
760 LeaveCriticalSection( &pdh_handle_cs );
761 return PDH_INVALID_DATA;
763 if (!(ret = format_value( counter, format, &counter->one, &counter->two, value )))
765 value->CStatus = ERROR_SUCCESS;
766 if (type) *type = counter->type;
769 LeaveCriticalSection( &pdh_handle_cs );
770 return ret;
773 /***********************************************************************
774 * PdhGetRawCounterValue (PDH.@)
776 PDH_STATUS WINAPI PdhGetRawCounterValue( PDH_HCOUNTER handle, LPDWORD type,
777 PPDH_RAW_COUNTER value )
779 struct counter *counter = handle;
781 TRACE("%p %p %p\n", handle, type, value);
783 if (!value) return PDH_INVALID_ARGUMENT;
785 EnterCriticalSection( &pdh_handle_cs );
786 if (!counter || counter->magic != PDH_MAGIC_COUNTER)
788 LeaveCriticalSection( &pdh_handle_cs );
789 return PDH_INVALID_HANDLE;
792 value->CStatus = counter->status;
793 value->TimeStamp.dwLowDateTime = counter->stamp.dwLowDateTime;
794 value->TimeStamp.dwHighDateTime = counter->stamp.dwHighDateTime;
795 value->FirstValue = counter->one.largevalue;
796 value->SecondValue = counter->two.largevalue;
797 value->MultiCount = 1; /* FIXME */
799 if (type) *type = counter->type;
801 LeaveCriticalSection( &pdh_handle_cs );
802 return ERROR_SUCCESS;
805 /***********************************************************************
806 * PdhLookupPerfIndexByNameA (PDH.@)
808 PDH_STATUS WINAPI PdhLookupPerfIndexByNameA( LPCSTR machine, LPCSTR name, LPDWORD index )
810 PDH_STATUS ret;
811 WCHAR *machineW = NULL;
812 WCHAR *nameW;
814 TRACE("%s %s %p\n", debugstr_a(machine), debugstr_a(name), index);
816 if (!name) return PDH_INVALID_ARGUMENT;
818 if (machine && !(machineW = pdh_strdup_aw( machine ))) return PDH_MEMORY_ALLOCATION_FAILURE;
820 if (!(nameW = pdh_strdup_aw( name )))
821 return PDH_MEMORY_ALLOCATION_FAILURE;
823 ret = PdhLookupPerfIndexByNameW( machineW, nameW, index );
825 heap_free( nameW );
826 heap_free( machineW );
827 return ret;
830 /***********************************************************************
831 * PdhLookupPerfIndexByNameW (PDH.@)
833 PDH_STATUS WINAPI PdhLookupPerfIndexByNameW( LPCWSTR machine, LPCWSTR name, LPDWORD index )
835 unsigned int i;
837 TRACE("%s %s %p\n", debugstr_w(machine), debugstr_w(name), index);
839 if (!name || !index) return PDH_INVALID_ARGUMENT;
841 if (machine)
843 FIXME("remote machine not supported\n");
844 return PDH_CSTATUS_NO_MACHINE;
846 for (i = 0; i < ARRAY_SIZE(counter_sources); i++)
848 if (pdh_match_path( counter_sources[i].path, name ))
850 *index = counter_sources[i].index;
851 return ERROR_SUCCESS;
854 return PDH_STRING_NOT_FOUND;
857 /***********************************************************************
858 * PdhLookupPerfNameByIndexA (PDH.@)
860 PDH_STATUS WINAPI PdhLookupPerfNameByIndexA( LPCSTR machine, DWORD index, LPSTR buffer, LPDWORD size )
862 PDH_STATUS ret;
863 WCHAR *machineW = NULL;
864 WCHAR bufferW[PDH_MAX_COUNTER_NAME];
865 DWORD sizeW = ARRAY_SIZE(bufferW);
867 TRACE("%s %d %p %p\n", debugstr_a(machine), index, buffer, size);
869 if (!buffer || !size) return PDH_INVALID_ARGUMENT;
871 if (machine && !(machineW = pdh_strdup_aw( machine ))) return PDH_MEMORY_ALLOCATION_FAILURE;
873 if (!(ret = PdhLookupPerfNameByIndexW( machineW, index, bufferW, &sizeW )))
875 int required = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL );
877 if (*size < required) ret = PDH_MORE_DATA;
878 else WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, required, NULL, NULL );
879 *size = required;
881 heap_free( machineW );
882 return ret;
885 /***********************************************************************
886 * PdhLookupPerfNameByIndexW (PDH.@)
888 PDH_STATUS WINAPI PdhLookupPerfNameByIndexW( LPCWSTR machine, DWORD index, LPWSTR buffer, LPDWORD size )
890 PDH_STATUS ret;
891 unsigned int i;
893 TRACE("%s %d %p %p\n", debugstr_w(machine), index, buffer, size);
895 if (machine)
897 FIXME("remote machine not supported\n");
898 return PDH_CSTATUS_NO_MACHINE;
901 if (!buffer || !size) return PDH_INVALID_ARGUMENT;
902 if (!index) return ERROR_SUCCESS;
904 for (i = 0; i < ARRAY_SIZE(counter_sources); i++)
906 if (counter_sources[i].index == index)
908 WCHAR *p = wcsrchr( counter_sources[i].path, '\\' ) + 1;
909 unsigned int required = lstrlenW( p ) + 1;
911 if (*size < required) ret = PDH_MORE_DATA;
912 else
914 lstrcpyW( buffer, p );
915 ret = ERROR_SUCCESS;
917 *size = required;
918 return ret;
921 return PDH_INVALID_ARGUMENT;
924 /***********************************************************************
925 * PdhOpenQueryA (PDH.@)
927 PDH_STATUS WINAPI PdhOpenQueryA( LPCSTR source, DWORD_PTR userdata, PDH_HQUERY *query )
929 PDH_STATUS ret;
930 WCHAR *sourceW = NULL;
932 TRACE("%s %lx %p\n", debugstr_a(source), userdata, query);
934 if (source && !(sourceW = pdh_strdup_aw( source ))) return PDH_MEMORY_ALLOCATION_FAILURE;
936 ret = PdhOpenQueryW( sourceW, userdata, query );
937 heap_free( sourceW );
939 return ret;
942 /***********************************************************************
943 * PdhOpenQueryW (PDH.@)
945 PDH_STATUS WINAPI PdhOpenQueryW( LPCWSTR source, DWORD_PTR userdata, PDH_HQUERY *handle )
947 struct query *query;
949 TRACE("%s %lx %p\n", debugstr_w(source), userdata, handle);
951 if (!handle) return PDH_INVALID_ARGUMENT;
953 if (source)
955 FIXME("log file data source not supported\n");
956 return PDH_INVALID_ARGUMENT;
958 if ((query = create_query()))
960 query->user = userdata;
961 *handle = query;
963 return ERROR_SUCCESS;
965 return PDH_MEMORY_ALLOCATION_FAILURE;
968 /***********************************************************************
969 * PdhRemoveCounter (PDH.@)
971 PDH_STATUS WINAPI PdhRemoveCounter( PDH_HCOUNTER handle )
973 struct counter *counter = handle;
975 TRACE("%p\n", handle);
977 EnterCriticalSection( &pdh_handle_cs );
978 if (!counter || counter->magic != PDH_MAGIC_COUNTER)
980 LeaveCriticalSection( &pdh_handle_cs );
981 return PDH_INVALID_HANDLE;
984 list_remove( &counter->entry );
985 destroy_counter( counter );
987 LeaveCriticalSection( &pdh_handle_cs );
988 return ERROR_SUCCESS;
991 /***********************************************************************
992 * PdhSetCounterScaleFactor (PDH.@)
994 PDH_STATUS WINAPI PdhSetCounterScaleFactor( PDH_HCOUNTER handle, LONG factor )
996 struct counter *counter = handle;
998 TRACE("%p\n", handle);
1000 EnterCriticalSection( &pdh_handle_cs );
1001 if (!counter || counter->magic != PDH_MAGIC_COUNTER)
1003 LeaveCriticalSection( &pdh_handle_cs );
1004 return PDH_INVALID_HANDLE;
1006 if (factor < PDH_MIN_SCALE || factor > PDH_MAX_SCALE)
1008 LeaveCriticalSection( &pdh_handle_cs );
1009 return PDH_INVALID_ARGUMENT;
1012 counter->scale = factor;
1014 LeaveCriticalSection( &pdh_handle_cs );
1015 return ERROR_SUCCESS;
1018 /***********************************************************************
1019 * PdhValidatePathA (PDH.@)
1021 PDH_STATUS WINAPI PdhValidatePathA( LPCSTR path )
1023 PDH_STATUS ret;
1024 WCHAR *pathW;
1026 TRACE("%s\n", debugstr_a(path));
1028 if (!path) return PDH_INVALID_ARGUMENT;
1029 if (!(pathW = pdh_strdup_aw( path ))) return PDH_MEMORY_ALLOCATION_FAILURE;
1031 ret = PdhValidatePathW( pathW );
1033 heap_free( pathW );
1034 return ret;
1037 static PDH_STATUS validate_path( LPCWSTR path )
1039 if (!path || !*path) return PDH_INVALID_ARGUMENT;
1040 if (*path++ != '\\' || !wcschr( path, '\\' )) return PDH_CSTATUS_BAD_COUNTERNAME;
1041 return ERROR_SUCCESS;
1044 /***********************************************************************
1045 * PdhValidatePathW (PDH.@)
1047 PDH_STATUS WINAPI PdhValidatePathW( LPCWSTR path )
1049 PDH_STATUS ret;
1050 unsigned int i;
1052 TRACE("%s\n", debugstr_w(path));
1054 if ((ret = validate_path( path ))) return ret;
1056 for (i = 0; i < ARRAY_SIZE(counter_sources); i++)
1057 if (pdh_match_path( counter_sources[i].path, path )) return ERROR_SUCCESS;
1059 return PDH_CSTATUS_NO_COUNTER;
1062 /***********************************************************************
1063 * PdhVbAddCounter (PDH.@)
1065 PDH_STATUS WINAPI PdhVbAddCounter( PDH_HQUERY query, LPCSTR path, PDH_HCOUNTER *counter )
1067 FIXME("%p, %s, %p: stub!\n", query, debugstr_a(path), counter);
1069 if (!path) return PDH_INVALID_ARGUMENT;
1071 return PDH_NOT_IMPLEMENTED;
1074 /***********************************************************************
1075 * PdhValidatePathExA (PDH.@)
1077 PDH_STATUS WINAPI PdhValidatePathExA( PDH_HLOG source, LPCSTR path )
1079 TRACE("%p %s\n", source, debugstr_a(path));
1081 if (source)
1083 FIXME("log file data source not supported\n");
1084 return ERROR_SUCCESS;
1086 return PdhValidatePathA( path );
1089 /***********************************************************************
1090 * PdhValidatePathExW (PDH.@)
1092 PDH_STATUS WINAPI PdhValidatePathExW( PDH_HLOG source, LPCWSTR path )
1094 TRACE("%p %s\n", source, debugstr_w(path));
1096 if (source)
1098 FIXME("log file data source not supported\n");
1099 return ERROR_SUCCESS;
1101 return PdhValidatePathW( path );
1104 /***********************************************************************
1105 * PdhMakeCounterPathA (PDH.@)
1107 PDH_STATUS WINAPI PdhMakeCounterPathA( PDH_COUNTER_PATH_ELEMENTS_A *e, LPSTR buffer,
1108 LPDWORD buflen, DWORD flags )
1110 PDH_STATUS ret = PDH_MEMORY_ALLOCATION_FAILURE;
1111 PDH_COUNTER_PATH_ELEMENTS_W eW;
1112 WCHAR *bufferW;
1113 DWORD buflenW;
1115 TRACE("%p %p %p 0x%08x\n", e, buffer, buflen, flags);
1117 if (!e || !buflen) return PDH_INVALID_ARGUMENT;
1119 memset( &eW, 0, sizeof(eW) );
1120 if (e->szMachineName && !(eW.szMachineName = pdh_strdup_aw( e->szMachineName ))) goto done;
1121 if (e->szObjectName && !(eW.szObjectName = pdh_strdup_aw( e->szObjectName ))) goto done;
1122 if (e->szInstanceName && !(eW.szInstanceName = pdh_strdup_aw( e->szInstanceName ))) goto done;
1123 if (e->szParentInstance && !(eW.szParentInstance = pdh_strdup_aw( e->szParentInstance ))) goto done;
1124 if (e->szCounterName && !(eW.szCounterName = pdh_strdup_aw( e->szCounterName ))) goto done;
1125 eW.dwInstanceIndex = e->dwInstanceIndex;
1127 buflenW = 0;
1128 ret = PdhMakeCounterPathW( &eW, NULL, &buflenW, flags );
1129 if (ret == PDH_MORE_DATA)
1131 if ((bufferW = heap_alloc( buflenW * sizeof(WCHAR) )))
1133 if (!(ret = PdhMakeCounterPathW( &eW, bufferW, &buflenW, flags )))
1135 int len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
1136 if (*buflen >= len) WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, *buflen, NULL, NULL);
1137 else ret = PDH_MORE_DATA;
1138 *buflen = len;
1140 heap_free( bufferW );
1142 else
1143 ret = PDH_MEMORY_ALLOCATION_FAILURE;
1146 done:
1147 heap_free( eW.szMachineName );
1148 heap_free( eW.szObjectName );
1149 heap_free( eW.szInstanceName );
1150 heap_free( eW.szParentInstance );
1151 heap_free( eW.szCounterName );
1152 return ret;
1155 /***********************************************************************
1156 * PdhMakeCounterPathW (PDH.@)
1158 PDH_STATUS WINAPI PdhMakeCounterPathW( PDH_COUNTER_PATH_ELEMENTS_W *e, LPWSTR buffer,
1159 LPDWORD buflen, DWORD flags )
1161 WCHAR path[PDH_MAX_COUNTER_NAME], instance[12];
1162 PDH_STATUS ret = ERROR_SUCCESS;
1163 DWORD len;
1165 TRACE("%p %p %p 0x%08x\n", e, buffer, buflen, flags);
1167 if (flags) FIXME("unimplemented flags 0x%08x\n", flags);
1169 if (!e || !e->szCounterName || !e->szObjectName || !buflen)
1170 return PDH_INVALID_ARGUMENT;
1172 path[0] = 0;
1173 if (e->szMachineName)
1175 lstrcatW(path, L"\\\\");
1176 lstrcatW(path, e->szMachineName);
1178 lstrcatW(path, L"\\");
1179 lstrcatW(path, e->szObjectName);
1180 if (e->szInstanceName)
1182 lstrcatW(path, L"(");
1183 if (e->szParentInstance)
1185 lstrcatW(path, e->szParentInstance);
1186 lstrcatW(path, L"/");
1188 lstrcatW(path, e->szInstanceName);
1189 swprintf(instance, ARRAY_SIZE(instance), L"#%u", e->dwInstanceIndex);
1190 lstrcatW(path, instance);
1191 lstrcatW(path, L")");
1193 lstrcatW(path, L"\\");
1194 lstrcatW(path, e->szCounterName);
1196 len = lstrlenW(path) + 1;
1197 if (*buflen >= len) lstrcpyW(buffer, path);
1198 else ret = PDH_MORE_DATA;
1199 *buflen = len;
1200 return ret;
1203 /***********************************************************************
1204 * PdhEnumObjectItemsA (PDH.@)
1206 PDH_STATUS WINAPI PdhEnumObjectItemsA(LPCSTR szDataSource, LPCSTR szMachineName, LPCSTR szObjectName,
1207 LPSTR mszCounterList, LPDWORD pcchCounterListLength, LPSTR mszInstanceList,
1208 LPDWORD pcchInstanceListLength, DWORD dwDetailLevel, DWORD dwFlags)
1210 FIXME("%s, %s, %s, %p, %p, %p, %p, %d, 0x%x: stub\n", debugstr_a(szDataSource), debugstr_a(szMachineName),
1211 debugstr_a(szObjectName), mszCounterList, pcchCounterListLength, mszInstanceList,
1212 pcchInstanceListLength, dwDetailLevel, dwFlags);
1214 return PDH_NOT_IMPLEMENTED;
1217 /***********************************************************************
1218 * PdhEnumObjectItemsW (PDH.@)
1220 PDH_STATUS WINAPI PdhEnumObjectItemsW(LPCWSTR szDataSource, LPCWSTR szMachineName, LPCWSTR szObjectName,
1221 LPWSTR mszCounterList, LPDWORD pcchCounterListLength, LPWSTR mszInstanceList,
1222 LPDWORD pcchInstanceListLength, DWORD dwDetailLevel, DWORD dwFlags)
1224 FIXME("%s, %s, %s, %p, %p, %p, %p, %d, 0x%x: stub\n", debugstr_w(szDataSource), debugstr_w(szMachineName),
1225 debugstr_w(szObjectName), mszCounterList, pcchCounterListLength, mszInstanceList,
1226 pcchInstanceListLength, dwDetailLevel, dwFlags);
1228 return PDH_NOT_IMPLEMENTED;
1231 /***********************************************************************
1232 * PdhSetDefaultRealTimeDataSource (PDH.@)
1234 PDH_STATUS WINAPI PdhSetDefaultRealTimeDataSource( DWORD source )
1236 FIXME("%u\n", source);
1237 return ERROR_SUCCESS;
1240 /***********************************************************************
1241 * PdhGetLogFileTypeA (PDH.@)
1243 PDH_STATUS WINAPI PdhGetLogFileTypeA(const char *log, DWORD *type)
1245 FIXME("%s, %p: stub\n", debugstr_a(log), type);
1246 return PDH_NOT_IMPLEMENTED;
1249 /***********************************************************************
1250 * PdhGetLogFileTypeW (PDH.@)
1252 PDH_STATUS WINAPI PdhGetLogFileTypeW(const WCHAR *log, DWORD *type)
1254 FIXME("%s, %p: stub\n", debugstr_w(log), type);
1255 return PDH_NOT_IMPLEMENTED;
1258 /***********************************************************************
1259 * PdhBindInputDataSourceA (PDH.@)
1261 PDH_STATUS WINAPI PdhBindInputDataSourceA(PDH_HLOG *source, const char *filenamelist)
1263 FIXME("%p %s: stub\n", source, debugstr_a(filenamelist));
1264 return PDH_NOT_IMPLEMENTED;
1267 /***********************************************************************
1268 * PdhBindInputDataSourceW (PDH.@)
1270 PDH_STATUS WINAPI PdhBindInputDataSourceW(PDH_HLOG *source, const WCHAR *filenamelist)
1272 FIXME("%p %s: stub\n", source, debugstr_w(filenamelist));
1273 return PDH_NOT_IMPLEMENTED;