localspl: Add unixname port extension.
[wine.git] / dlls / pdh / pdh_main.c
blob7eae7872b4842d740a3566f0c74f6e43d3db4bc8
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 <stdlib.h>
24 #include <math.h>
26 #define NONAMELESSUNION
28 #include "windef.h"
29 #include "winbase.h"
31 #include "pdh.h"
32 #include "pdhmsg.h"
33 #include "winperf.h"
35 #include "wine/debug.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_aw( const char *src )
52 int len;
53 WCHAR *dst;
55 if (!src) return NULL;
56 len = MultiByteToWideChar( CP_ACP, 0, src, -1, NULL, 0 );
57 if ((dst = malloc( len * sizeof(WCHAR) ))) MultiByteToWideChar( CP_ACP, 0, src, -1, dst, len );
58 return dst;
61 union value
63 LONG longvalue;
64 double doublevalue;
65 LONGLONG largevalue;
68 struct counter
70 DWORD magic; /* signature */
71 struct list entry; /* list entry */
72 WCHAR *path; /* identifier */
73 DWORD type; /* counter type */
74 DWORD status; /* update status */
75 LONG scale; /* scale factor */
76 LONG defaultscale; /* default scale factor */
77 DWORD_PTR user; /* user data */
78 DWORD_PTR queryuser; /* query user data */
79 LONGLONG base; /* samples per second */
80 FILETIME stamp; /* time stamp */
81 void (CALLBACK *collect)( struct counter * ); /* collect callback */
82 union value one; /* first value */
83 union value two; /* second value */
86 #define PDH_MAGIC_COUNTER 0x50444831 /* 'PDH1' */
88 static struct counter *create_counter( void )
90 struct counter *counter;
92 if ((counter = calloc( 1, sizeof(struct counter) )))
94 counter->magic = PDH_MAGIC_COUNTER;
95 return counter;
97 return NULL;
100 static void destroy_counter( struct counter *counter )
102 counter->magic = 0;
103 free( counter->path );
104 free( counter );
107 #define PDH_MAGIC_QUERY 0x50444830 /* 'PDH0' */
109 struct query
111 DWORD magic; /* signature */
112 DWORD_PTR user; /* user data */
113 HANDLE thread; /* collect thread */
114 DWORD interval; /* collect interval */
115 HANDLE wait; /* wait event */
116 HANDLE stop; /* stop event */
117 struct list counters; /* counter list */
120 static struct query *create_query( void )
122 struct query *query;
124 if ((query = calloc( 1, sizeof(struct query) )))
126 query->magic = PDH_MAGIC_QUERY;
127 list_init( &query->counters );
128 return query;
130 return NULL;
133 static void destroy_query( struct query *query )
135 query->magic = 0;
136 free( query );
139 struct source
141 DWORD index; /* name index */
142 const WCHAR *path; /* identifier */
143 void (CALLBACK *collect)( struct counter * ); /* collect callback */
144 DWORD type; /* counter type */
145 LONG scale; /* default scale factor */
146 LONGLONG base; /* samples per second */
149 static void CALLBACK collect_processor_time( struct counter *counter )
151 counter->two.largevalue = 500000; /* FIXME */
152 counter->status = PDH_CSTATUS_VALID_DATA;
155 static void CALLBACK collect_uptime( struct counter *counter )
157 counter->two.largevalue = GetTickCount64();
158 counter->status = PDH_CSTATUS_VALID_DATA;
161 #define TYPE_PROCESSOR_TIME \
162 (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | PERF_TIMER_100NS | PERF_DELTA_COUNTER | \
163 PERF_INVERSE_COUNTER | PERF_DISPLAY_PERCENT)
165 #define TYPE_UPTIME \
166 (PERF_SIZE_LARGE | PERF_TYPE_COUNTER | PERF_COUNTER_ELAPSED | PERF_OBJECT_TIMER | PERF_DISPLAY_SECONDS)
168 /* counter source registry */
169 static const struct source counter_sources[] =
171 { 6, L"\\Processor(_Total)\\% Processor Time", collect_processor_time, TYPE_PROCESSOR_TIME, -5, 10000000 },
172 { 674, L"\\System\\System Up Time", collect_uptime, TYPE_UPTIME, -3, 1000 }
175 static BOOL is_local_machine( const WCHAR *name, DWORD len )
177 WCHAR buf[MAX_COMPUTERNAME_LENGTH + 1];
178 DWORD buflen = ARRAY_SIZE(buf);
180 if (!GetComputerNameW( buf, &buflen )) return FALSE;
181 return len == buflen && !wcsnicmp( name, buf, buflen );
184 static BOOL pdh_match_path( LPCWSTR fullpath, LPCWSTR path )
186 const WCHAR *p;
188 if (path[0] == '\\' && path[1] == '\\' && (p = wcschr( path + 2, '\\' )) &&
189 is_local_machine( path + 2, p - path - 2 ))
191 path += p - path;
193 if (wcschr( path, '\\' )) p = fullpath;
194 else p = wcsrchr( fullpath, '\\' ) + 1;
195 return !wcscmp( p, path );
198 /***********************************************************************
199 * PdhAddCounterA (PDH.@)
201 PDH_STATUS WINAPI PdhAddCounterA( PDH_HQUERY query, LPCSTR path,
202 DWORD_PTR userdata, PDH_HCOUNTER *counter )
204 PDH_STATUS ret;
205 WCHAR *pathW;
207 TRACE("%p %s %Ix %p\n", query, debugstr_a(path), userdata, counter);
209 if (!path) return PDH_INVALID_ARGUMENT;
211 if (!(pathW = pdh_strdup_aw( path )))
212 return PDH_MEMORY_ALLOCATION_FAILURE;
214 ret = PdhAddCounterW( query, pathW, userdata, counter );
216 free( pathW );
217 return ret;
220 /***********************************************************************
221 * PdhAddCounterW (PDH.@)
223 PDH_STATUS WINAPI PdhAddCounterW( PDH_HQUERY hquery, LPCWSTR path,
224 DWORD_PTR userdata, PDH_HCOUNTER *hcounter )
226 struct query *query = hquery;
227 struct counter *counter;
228 unsigned int i;
230 TRACE("%p %s %Ix %p\n", hquery, debugstr_w(path), userdata, hcounter);
232 if (!path || !hcounter) return PDH_INVALID_ARGUMENT;
234 EnterCriticalSection( &pdh_handle_cs );
235 if (!query || query->magic != PDH_MAGIC_QUERY)
237 LeaveCriticalSection( &pdh_handle_cs );
238 return PDH_INVALID_HANDLE;
241 *hcounter = NULL;
242 for (i = 0; i < ARRAY_SIZE(counter_sources); i++)
244 if (pdh_match_path( counter_sources[i].path, path ))
246 if ((counter = create_counter()))
248 counter->path = wcsdup( counter_sources[i].path );
249 counter->collect = counter_sources[i].collect;
250 counter->type = counter_sources[i].type;
251 counter->defaultscale = counter_sources[i].scale;
252 counter->base = counter_sources[i].base;
253 counter->queryuser = query->user;
254 counter->user = userdata;
256 list_add_tail( &query->counters, &counter->entry );
257 *hcounter = counter;
259 LeaveCriticalSection( &pdh_handle_cs );
260 return ERROR_SUCCESS;
262 LeaveCriticalSection( &pdh_handle_cs );
263 return PDH_MEMORY_ALLOCATION_FAILURE;
266 LeaveCriticalSection( &pdh_handle_cs );
267 return PDH_CSTATUS_NO_COUNTER;
270 /***********************************************************************
271 * PdhAddEnglishCounterA (PDH.@)
273 PDH_STATUS WINAPI PdhAddEnglishCounterA( PDH_HQUERY query, LPCSTR path,
274 DWORD_PTR userdata, PDH_HCOUNTER *counter )
276 TRACE("%p %s %Ix %p\n", query, debugstr_a(path), userdata, counter);
278 if (!counter) return PDH_INVALID_ARGUMENT;
279 if (!query) return PDH_INVALID_HANDLE;
280 return PdhAddCounterA( query, path, userdata, counter );
283 /***********************************************************************
284 * PdhAddEnglishCounterW (PDH.@)
286 PDH_STATUS WINAPI PdhAddEnglishCounterW( PDH_HQUERY query, LPCWSTR path,
287 DWORD_PTR userdata, PDH_HCOUNTER *counter )
289 TRACE("%p %s %Ix %p\n", query, debugstr_w(path), userdata, counter);
291 if (!counter) return PDH_INVALID_ARGUMENT;
292 if (!query) return PDH_INVALID_HANDLE;
293 return PdhAddCounterW( query, path, userdata, counter );
296 /* caller must hold counter lock */
297 static PDH_STATUS format_value( struct counter *counter, DWORD format, union value *raw1,
298 union value *raw2, PDH_FMT_COUNTERVALUE *value )
300 LONG factor;
302 factor = counter->scale ? counter->scale : counter->defaultscale;
303 if (format & PDH_FMT_LONG)
305 if (format & PDH_FMT_1000) value->u.longValue = raw2->longvalue * 1000;
306 else value->u.longValue = raw2->longvalue * pow( 10, factor );
308 else if (format & PDH_FMT_LARGE)
310 if (format & PDH_FMT_1000) value->u.largeValue = raw2->largevalue * 1000;
311 else value->u.largeValue = raw2->largevalue * pow( 10, factor );
313 else if (format & PDH_FMT_DOUBLE)
315 if (format & PDH_FMT_1000) value->u.doubleValue = raw2->doublevalue * 1000;
316 else value->u.doubleValue = raw2->doublevalue * pow( 10, factor );
318 else
320 WARN("unknown format %lx\n", format);
321 return PDH_INVALID_ARGUMENT;
323 return ERROR_SUCCESS;
326 /***********************************************************************
327 * PdhCalculateCounterFromRawValue (PDH.@)
329 PDH_STATUS WINAPI PdhCalculateCounterFromRawValue( PDH_HCOUNTER handle, DWORD format,
330 PPDH_RAW_COUNTER raw1, PPDH_RAW_COUNTER raw2,
331 PPDH_FMT_COUNTERVALUE value )
333 PDH_STATUS ret;
334 struct counter *counter = handle;
336 TRACE("%p 0x%08lx %p %p %p\n", handle, format, raw1, raw2, value);
338 if (!value) return PDH_INVALID_ARGUMENT;
340 EnterCriticalSection( &pdh_handle_cs );
341 if (!counter || counter->magic != PDH_MAGIC_COUNTER)
343 LeaveCriticalSection( &pdh_handle_cs );
344 return PDH_INVALID_HANDLE;
347 ret = format_value( counter, format, (union value *)&raw1->SecondValue,
348 (union value *)&raw2->SecondValue, value );
350 LeaveCriticalSection( &pdh_handle_cs );
351 return ret;
355 /***********************************************************************
356 * PdhCloseQuery (PDH.@)
358 PDH_STATUS WINAPI PdhCloseQuery( PDH_HQUERY handle )
360 struct query *query = handle;
361 struct list *item, *next;
363 TRACE("%p\n", handle);
365 EnterCriticalSection( &pdh_handle_cs );
366 if (!query || query->magic != PDH_MAGIC_QUERY)
368 LeaveCriticalSection( &pdh_handle_cs );
369 return PDH_INVALID_HANDLE;
372 if (query->thread)
374 HANDLE thread = query->thread;
375 SetEvent( query->stop );
376 LeaveCriticalSection( &pdh_handle_cs );
378 WaitForSingleObject( thread, INFINITE );
380 EnterCriticalSection( &pdh_handle_cs );
381 if (query->magic != PDH_MAGIC_QUERY)
383 LeaveCriticalSection( &pdh_handle_cs );
384 return ERROR_SUCCESS;
386 CloseHandle( query->stop );
387 CloseHandle( query->thread );
388 query->thread = NULL;
391 LIST_FOR_EACH_SAFE( item, next, &query->counters )
393 struct counter *counter = LIST_ENTRY( item, struct counter, entry );
395 list_remove( &counter->entry );
396 destroy_counter( counter );
399 destroy_query( query );
401 LeaveCriticalSection( &pdh_handle_cs );
402 return ERROR_SUCCESS;
405 /* caller must hold query lock */
406 static void collect_query_data( struct query *query )
408 struct list *item;
410 LIST_FOR_EACH( item, &query->counters )
412 SYSTEMTIME time;
413 struct counter *counter = LIST_ENTRY( item, struct counter, entry );
415 counter->collect( counter );
417 GetLocalTime( &time );
418 SystemTimeToFileTime( &time, &counter->stamp );
422 /***********************************************************************
423 * PdhCollectQueryData (PDH.@)
425 PDH_STATUS WINAPI PdhCollectQueryData( PDH_HQUERY handle )
427 struct query *query = handle;
429 TRACE("%p\n", handle);
431 EnterCriticalSection( &pdh_handle_cs );
432 if (!query || query->magic != PDH_MAGIC_QUERY)
434 LeaveCriticalSection( &pdh_handle_cs );
435 return PDH_INVALID_HANDLE;
438 if (list_empty( &query->counters ))
440 LeaveCriticalSection( &pdh_handle_cs );
441 return PDH_NO_DATA;
444 collect_query_data( query );
446 LeaveCriticalSection( &pdh_handle_cs );
447 return ERROR_SUCCESS;
450 static DWORD CALLBACK collect_query_thread( void *arg )
452 struct query *query = arg;
453 DWORD interval = query->interval;
454 HANDLE stop = query->stop;
456 for (;;)
458 if (WaitForSingleObject( stop, interval ) != WAIT_TIMEOUT) ExitThread( 0 );
460 EnterCriticalSection( &pdh_handle_cs );
461 if (query->magic != PDH_MAGIC_QUERY)
463 LeaveCriticalSection( &pdh_handle_cs );
464 ExitThread( PDH_INVALID_HANDLE );
467 collect_query_data( query );
469 if (!SetEvent( query->wait ))
471 LeaveCriticalSection( &pdh_handle_cs );
472 ExitThread( 0 );
474 LeaveCriticalSection( &pdh_handle_cs );
478 /***********************************************************************
479 * PdhCollectQueryDataEx (PDH.@)
481 PDH_STATUS WINAPI PdhCollectQueryDataEx( PDH_HQUERY handle, DWORD interval, HANDLE event )
483 PDH_STATUS ret;
484 struct query *query = handle;
486 TRACE("%p %ld %p\n", handle, interval, event);
488 EnterCriticalSection( &pdh_handle_cs );
489 if (!query || query->magic != PDH_MAGIC_QUERY)
491 LeaveCriticalSection( &pdh_handle_cs );
492 return PDH_INVALID_HANDLE;
494 if (list_empty( &query->counters ))
496 LeaveCriticalSection( &pdh_handle_cs );
497 return PDH_NO_DATA;
499 if (query->thread)
501 HANDLE thread = query->thread;
502 SetEvent( query->stop );
503 LeaveCriticalSection( &pdh_handle_cs );
505 WaitForSingleObject( thread, INFINITE );
507 EnterCriticalSection( &pdh_handle_cs );
508 if (query->magic != PDH_MAGIC_QUERY)
510 LeaveCriticalSection( &pdh_handle_cs );
511 return PDH_INVALID_HANDLE;
513 CloseHandle( query->thread );
514 query->thread = NULL;
516 else if (!(query->stop = CreateEventW( NULL, FALSE, FALSE, NULL )))
518 ret = GetLastError();
519 LeaveCriticalSection( &pdh_handle_cs );
520 return ret;
522 query->wait = event;
523 query->interval = interval * 1000;
524 if (!(query->thread = CreateThread( NULL, 0, collect_query_thread, query, 0, NULL )))
526 ret = GetLastError();
527 CloseHandle( query->stop );
529 LeaveCriticalSection( &pdh_handle_cs );
530 return ret;
533 LeaveCriticalSection( &pdh_handle_cs );
534 return ERROR_SUCCESS;
537 /***********************************************************************
538 * PdhCollectQueryDataWithTime (PDH.@)
540 PDH_STATUS WINAPI PdhCollectQueryDataWithTime( PDH_HQUERY handle, LONGLONG *timestamp )
542 struct query *query = handle;
543 struct counter *counter;
544 struct list *item;
546 TRACE("%p %p\n", handle, timestamp);
548 if (!timestamp) return PDH_INVALID_ARGUMENT;
550 EnterCriticalSection( &pdh_handle_cs );
551 if (!query || query->magic != PDH_MAGIC_QUERY)
553 LeaveCriticalSection( &pdh_handle_cs );
554 return PDH_INVALID_HANDLE;
556 if (list_empty( &query->counters ))
558 LeaveCriticalSection( &pdh_handle_cs );
559 return PDH_NO_DATA;
562 collect_query_data( query );
564 item = list_head( &query->counters );
565 counter = LIST_ENTRY( item, struct counter, entry );
567 *timestamp = ((LONGLONG)counter->stamp.dwHighDateTime << 32) | counter->stamp.dwLowDateTime;
569 LeaveCriticalSection( &pdh_handle_cs );
570 return ERROR_SUCCESS;
573 /***********************************************************************
574 * PdhExpandWildCardPathA (PDH.@)
576 PDH_STATUS WINAPI PdhExpandWildCardPathA( LPCSTR szDataSource, LPCSTR szWildCardPath, LPSTR mszExpandedPathList, LPDWORD pcchPathListLength, DWORD dwFlags )
578 FIXME("%s, %s, %p, %p, 0x%lx: stub\n", debugstr_a(szDataSource), debugstr_a(szWildCardPath), mszExpandedPathList, pcchPathListLength, dwFlags);
579 return PDH_NOT_IMPLEMENTED;
582 /***********************************************************************
583 * PdhExpandWildCardPathW (PDH.@)
585 PDH_STATUS WINAPI PdhExpandWildCardPathW( LPCWSTR szDataSource, LPCWSTR szWildCardPath, LPWSTR mszExpandedPathList, LPDWORD pcchPathListLength, DWORD dwFlags )
587 FIXME("%s, %s, %p, %p, 0x%lx: stub\n", debugstr_w(szDataSource), debugstr_w(szWildCardPath), mszExpandedPathList, pcchPathListLength, dwFlags);
588 return PDH_NOT_IMPLEMENTED;
591 /***********************************************************************
592 * PdhExpandCounterPathA (PDH.@)
594 PDH_STATUS WINAPI PdhExpandCounterPathA( LPCSTR szWildCardPath, LPSTR mszExpandedPathList, LPDWORD pcchPathListLength )
596 FIXME("%s, %p, %p: stub\n", debugstr_a(szWildCardPath), mszExpandedPathList, pcchPathListLength);
597 return PdhExpandWildCardPathA(NULL, szWildCardPath, mszExpandedPathList, pcchPathListLength, 0);
600 /***********************************************************************
601 * PdhExpandCounterPathW (PDH.@)
603 PDH_STATUS WINAPI PdhExpandCounterPathW( LPCWSTR szWildCardPath, LPWSTR mszExpandedPathList, LPDWORD pcchPathListLength )
605 FIXME("%s, %p, %p: stub\n", debugstr_w(szWildCardPath), mszExpandedPathList, pcchPathListLength);
606 return PdhExpandWildCardPathW(NULL, szWildCardPath, mszExpandedPathList, pcchPathListLength, 0);
609 /***********************************************************************
610 * PdhGetCounterInfoA (PDH.@)
612 PDH_STATUS WINAPI PdhGetCounterInfoA( PDH_HCOUNTER handle, BOOLEAN text, LPDWORD size, PPDH_COUNTER_INFO_A info )
614 struct counter *counter = handle;
616 TRACE("%p %d %p %p\n", handle, text, size, info);
618 EnterCriticalSection( &pdh_handle_cs );
619 if (!counter || counter->magic != PDH_MAGIC_COUNTER)
621 LeaveCriticalSection( &pdh_handle_cs );
622 return PDH_INVALID_HANDLE;
624 if (!size)
626 LeaveCriticalSection( &pdh_handle_cs );
627 return PDH_INVALID_ARGUMENT;
629 if (*size < sizeof(PDH_COUNTER_INFO_A))
631 *size = sizeof(PDH_COUNTER_INFO_A);
632 LeaveCriticalSection( &pdh_handle_cs );
633 return PDH_MORE_DATA;
636 memset( info, 0, sizeof(PDH_COUNTER_INFO_A) );
638 info->dwType = counter->type;
639 info->CStatus = counter->status;
640 info->lScale = counter->scale;
641 info->lDefaultScale = counter->defaultscale;
642 info->dwUserData = counter->user;
643 info->dwQueryUserData = counter->queryuser;
645 *size = sizeof(PDH_COUNTER_INFO_A);
647 LeaveCriticalSection( &pdh_handle_cs );
648 return ERROR_SUCCESS;
651 /***********************************************************************
652 * PdhGetCounterInfoW (PDH.@)
654 PDH_STATUS WINAPI PdhGetCounterInfoW( PDH_HCOUNTER handle, BOOLEAN text, LPDWORD size, PPDH_COUNTER_INFO_W info )
656 struct counter *counter = handle;
658 TRACE("%p %d %p %p\n", handle, text, size, info);
660 EnterCriticalSection( &pdh_handle_cs );
661 if (!counter || counter->magic != PDH_MAGIC_COUNTER)
663 LeaveCriticalSection( &pdh_handle_cs );
664 return PDH_INVALID_HANDLE;
666 if (!size)
668 LeaveCriticalSection( &pdh_handle_cs );
669 return PDH_INVALID_ARGUMENT;
671 if (*size < sizeof(PDH_COUNTER_INFO_W))
673 *size = sizeof(PDH_COUNTER_INFO_W);
674 LeaveCriticalSection( &pdh_handle_cs );
675 return PDH_MORE_DATA;
678 memset( info, 0, sizeof(PDH_COUNTER_INFO_W) );
680 info->dwType = counter->type;
681 info->CStatus = counter->status;
682 info->lScale = counter->scale;
683 info->lDefaultScale = counter->defaultscale;
684 info->dwUserData = counter->user;
685 info->dwQueryUserData = counter->queryuser;
687 *size = sizeof(PDH_COUNTER_INFO_W);
689 LeaveCriticalSection( &pdh_handle_cs );
690 return ERROR_SUCCESS;
693 /***********************************************************************
694 * PdhGetCounterTimeBase (PDH.@)
696 PDH_STATUS WINAPI PdhGetCounterTimeBase( PDH_HCOUNTER handle, LONGLONG *base )
698 struct counter *counter = handle;
700 TRACE("%p %p\n", handle, base);
702 if (!base) return PDH_INVALID_ARGUMENT;
704 EnterCriticalSection( &pdh_handle_cs );
705 if (!counter || counter->magic != PDH_MAGIC_COUNTER)
707 LeaveCriticalSection( &pdh_handle_cs );
708 return PDH_INVALID_HANDLE;
711 *base = counter->base;
713 LeaveCriticalSection( &pdh_handle_cs );
714 return ERROR_SUCCESS;
717 /***********************************************************************
718 * PdhGetDllVersion (PDH.@)
720 PDH_STATUS WINAPI PdhGetDllVersion( LPDWORD version )
722 if (!version)
723 return PDH_INVALID_ARGUMENT;
725 *version = PDH_VERSION;
727 return ERROR_SUCCESS;
730 /***********************************************************************
731 * PdhGetFormattedCounterValue (PDH.@)
733 PDH_STATUS WINAPI PdhGetFormattedCounterValue( PDH_HCOUNTER handle, DWORD format,
734 LPDWORD type, PPDH_FMT_COUNTERVALUE value )
736 PDH_STATUS ret;
737 struct counter *counter = handle;
739 TRACE("%p %lx %p %p\n", handle, format, type, value);
741 if (!value) 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;
749 if (counter->status)
751 LeaveCriticalSection( &pdh_handle_cs );
752 return PDH_INVALID_DATA;
754 if (!(ret = format_value( counter, format, &counter->one, &counter->two, value )))
756 value->CStatus = ERROR_SUCCESS;
757 if (type) *type = counter->type;
760 LeaveCriticalSection( &pdh_handle_cs );
761 return ret;
764 /***********************************************************************
765 * PdhGetRawCounterValue (PDH.@)
767 PDH_STATUS WINAPI PdhGetRawCounterValue( PDH_HCOUNTER handle, LPDWORD type,
768 PPDH_RAW_COUNTER value )
770 struct counter *counter = handle;
772 TRACE("%p %p %p\n", handle, type, value);
774 if (!value) return PDH_INVALID_ARGUMENT;
776 EnterCriticalSection( &pdh_handle_cs );
777 if (!counter || counter->magic != PDH_MAGIC_COUNTER)
779 LeaveCriticalSection( &pdh_handle_cs );
780 return PDH_INVALID_HANDLE;
783 value->CStatus = counter->status;
784 value->TimeStamp.dwLowDateTime = counter->stamp.dwLowDateTime;
785 value->TimeStamp.dwHighDateTime = counter->stamp.dwHighDateTime;
786 value->FirstValue = counter->one.largevalue;
787 value->SecondValue = counter->two.largevalue;
788 value->MultiCount = 1; /* FIXME */
790 if (type) *type = counter->type;
792 LeaveCriticalSection( &pdh_handle_cs );
793 return ERROR_SUCCESS;
796 /***********************************************************************
797 * PdhLookupPerfIndexByNameA (PDH.@)
799 PDH_STATUS WINAPI PdhLookupPerfIndexByNameA( LPCSTR machine, LPCSTR name, LPDWORD index )
801 PDH_STATUS ret;
802 WCHAR *machineW = NULL;
803 WCHAR *nameW;
805 TRACE("%s %s %p\n", debugstr_a(machine), debugstr_a(name), index);
807 if (!name) return PDH_INVALID_ARGUMENT;
809 if (machine && !(machineW = pdh_strdup_aw( machine ))) return PDH_MEMORY_ALLOCATION_FAILURE;
811 if (!(nameW = pdh_strdup_aw( name )))
812 return PDH_MEMORY_ALLOCATION_FAILURE;
814 ret = PdhLookupPerfIndexByNameW( machineW, nameW, index );
816 free( nameW );
817 free( machineW );
818 return ret;
821 /***********************************************************************
822 * PdhLookupPerfIndexByNameW (PDH.@)
824 PDH_STATUS WINAPI PdhLookupPerfIndexByNameW( LPCWSTR machine, LPCWSTR name, LPDWORD index )
826 unsigned int i;
828 TRACE("%s %s %p\n", debugstr_w(machine), debugstr_w(name), index);
830 if (!name || !index) return PDH_INVALID_ARGUMENT;
832 if (machine)
834 FIXME("remote machine not supported\n");
835 return PDH_CSTATUS_NO_MACHINE;
837 for (i = 0; i < ARRAY_SIZE(counter_sources); i++)
839 if (pdh_match_path( counter_sources[i].path, name ))
841 *index = counter_sources[i].index;
842 return ERROR_SUCCESS;
845 return PDH_STRING_NOT_FOUND;
848 /***********************************************************************
849 * PdhLookupPerfNameByIndexA (PDH.@)
851 PDH_STATUS WINAPI PdhLookupPerfNameByIndexA( LPCSTR machine, DWORD index, LPSTR buffer, LPDWORD size )
853 PDH_STATUS ret;
854 WCHAR *machineW = NULL;
855 WCHAR bufferW[PDH_MAX_COUNTER_NAME];
856 DWORD sizeW = ARRAY_SIZE(bufferW);
858 TRACE("%s %ld %p %p\n", debugstr_a(machine), index, buffer, size);
860 if (!buffer || !size) return PDH_INVALID_ARGUMENT;
862 if (machine && !(machineW = pdh_strdup_aw( machine ))) return PDH_MEMORY_ALLOCATION_FAILURE;
864 if (!(ret = PdhLookupPerfNameByIndexW( machineW, index, bufferW, &sizeW )))
866 int required = WideCharToMultiByte( CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL );
868 if (*size < required) ret = PDH_MORE_DATA;
869 else WideCharToMultiByte( CP_ACP, 0, bufferW, -1, buffer, required, NULL, NULL );
870 *size = required;
872 free( machineW );
873 return ret;
876 /***********************************************************************
877 * PdhLookupPerfNameByIndexW (PDH.@)
879 PDH_STATUS WINAPI PdhLookupPerfNameByIndexW( LPCWSTR machine, DWORD index, LPWSTR buffer, LPDWORD size )
881 PDH_STATUS ret;
882 unsigned int i;
884 TRACE("%s %ld %p %p\n", debugstr_w(machine), index, buffer, size);
886 if (machine)
888 FIXME("remote machine not supported\n");
889 return PDH_CSTATUS_NO_MACHINE;
892 if (!buffer || !size) return PDH_INVALID_ARGUMENT;
893 if (!index) return ERROR_SUCCESS;
895 for (i = 0; i < ARRAY_SIZE(counter_sources); i++)
897 if (counter_sources[i].index == index)
899 WCHAR *p = wcsrchr( counter_sources[i].path, '\\' ) + 1;
900 unsigned int required = lstrlenW( p ) + 1;
902 if (*size < required) ret = PDH_MORE_DATA;
903 else
905 lstrcpyW( buffer, p );
906 ret = ERROR_SUCCESS;
908 *size = required;
909 return ret;
912 return PDH_INVALID_ARGUMENT;
915 /***********************************************************************
916 * PdhOpenQueryA (PDH.@)
918 PDH_STATUS WINAPI PdhOpenQueryA( LPCSTR source, DWORD_PTR userdata, PDH_HQUERY *query )
920 PDH_STATUS ret;
921 WCHAR *sourceW = NULL;
923 TRACE("%s %Ix %p\n", debugstr_a(source), userdata, query);
925 if (source && !(sourceW = pdh_strdup_aw( source ))) return PDH_MEMORY_ALLOCATION_FAILURE;
927 ret = PdhOpenQueryW( sourceW, userdata, query );
928 free( sourceW );
930 return ret;
933 /***********************************************************************
934 * PdhOpenQueryW (PDH.@)
936 PDH_STATUS WINAPI PdhOpenQueryW( LPCWSTR source, DWORD_PTR userdata, PDH_HQUERY *handle )
938 struct query *query;
940 TRACE("%s %Ix %p\n", debugstr_w(source), userdata, handle);
942 if (!handle) return PDH_INVALID_ARGUMENT;
944 if (source)
946 FIXME("log file data source not supported\n");
947 return PDH_INVALID_ARGUMENT;
949 if ((query = create_query()))
951 query->user = userdata;
952 *handle = query;
954 return ERROR_SUCCESS;
956 return PDH_MEMORY_ALLOCATION_FAILURE;
959 /***********************************************************************
960 * PdhRemoveCounter (PDH.@)
962 PDH_STATUS WINAPI PdhRemoveCounter( PDH_HCOUNTER handle )
964 struct counter *counter = handle;
966 TRACE("%p\n", handle);
968 EnterCriticalSection( &pdh_handle_cs );
969 if (!counter || counter->magic != PDH_MAGIC_COUNTER)
971 LeaveCriticalSection( &pdh_handle_cs );
972 return PDH_INVALID_HANDLE;
975 list_remove( &counter->entry );
976 destroy_counter( counter );
978 LeaveCriticalSection( &pdh_handle_cs );
979 return ERROR_SUCCESS;
982 /***********************************************************************
983 * PdhSetCounterScaleFactor (PDH.@)
985 PDH_STATUS WINAPI PdhSetCounterScaleFactor( PDH_HCOUNTER handle, LONG factor )
987 struct counter *counter = handle;
989 TRACE("%p\n", handle);
991 EnterCriticalSection( &pdh_handle_cs );
992 if (!counter || counter->magic != PDH_MAGIC_COUNTER)
994 LeaveCriticalSection( &pdh_handle_cs );
995 return PDH_INVALID_HANDLE;
997 if (factor < PDH_MIN_SCALE || factor > PDH_MAX_SCALE)
999 LeaveCriticalSection( &pdh_handle_cs );
1000 return PDH_INVALID_ARGUMENT;
1003 counter->scale = factor;
1005 LeaveCriticalSection( &pdh_handle_cs );
1006 return ERROR_SUCCESS;
1009 /***********************************************************************
1010 * PdhValidatePathA (PDH.@)
1012 PDH_STATUS WINAPI PdhValidatePathA( LPCSTR path )
1014 PDH_STATUS ret;
1015 WCHAR *pathW;
1017 TRACE("%s\n", debugstr_a(path));
1019 if (!path) return PDH_INVALID_ARGUMENT;
1020 if (!(pathW = pdh_strdup_aw( path ))) return PDH_MEMORY_ALLOCATION_FAILURE;
1022 ret = PdhValidatePathW( pathW );
1024 free( pathW );
1025 return ret;
1028 static PDH_STATUS validate_path( LPCWSTR path )
1030 if (!path || !*path) return PDH_INVALID_ARGUMENT;
1031 if (*path++ != '\\' || !wcschr( path, '\\' )) return PDH_CSTATUS_BAD_COUNTERNAME;
1032 return ERROR_SUCCESS;
1035 /***********************************************************************
1036 * PdhValidatePathW (PDH.@)
1038 PDH_STATUS WINAPI PdhValidatePathW( LPCWSTR path )
1040 PDH_STATUS ret;
1041 unsigned int i;
1043 TRACE("%s\n", debugstr_w(path));
1045 if ((ret = validate_path( path ))) return ret;
1047 for (i = 0; i < ARRAY_SIZE(counter_sources); i++)
1048 if (pdh_match_path( counter_sources[i].path, path )) return ERROR_SUCCESS;
1050 return PDH_CSTATUS_NO_COUNTER;
1053 /***********************************************************************
1054 * PdhVbAddCounter (PDH.@)
1056 PDH_STATUS WINAPI PdhVbAddCounter( PDH_HQUERY query, LPCSTR path, PDH_HCOUNTER *counter )
1058 FIXME("%p, %s, %p: stub!\n", query, debugstr_a(path), counter);
1060 if (!path) return PDH_INVALID_ARGUMENT;
1062 return PDH_NOT_IMPLEMENTED;
1065 /***********************************************************************
1066 * PdhValidatePathExA (PDH.@)
1068 PDH_STATUS WINAPI PdhValidatePathExA( PDH_HLOG source, LPCSTR path )
1070 TRACE("%p %s\n", source, debugstr_a(path));
1072 if (source)
1074 FIXME("log file data source not supported\n");
1075 return ERROR_SUCCESS;
1077 return PdhValidatePathA( path );
1080 /***********************************************************************
1081 * PdhValidatePathExW (PDH.@)
1083 PDH_STATUS WINAPI PdhValidatePathExW( PDH_HLOG source, LPCWSTR path )
1085 TRACE("%p %s\n", source, debugstr_w(path));
1087 if (source)
1089 FIXME("log file data source not supported\n");
1090 return ERROR_SUCCESS;
1092 return PdhValidatePathW( path );
1095 /***********************************************************************
1096 * PdhMakeCounterPathA (PDH.@)
1098 PDH_STATUS WINAPI PdhMakeCounterPathA( PDH_COUNTER_PATH_ELEMENTS_A *e, LPSTR buffer,
1099 LPDWORD buflen, DWORD flags )
1101 PDH_STATUS ret = PDH_MEMORY_ALLOCATION_FAILURE;
1102 PDH_COUNTER_PATH_ELEMENTS_W eW;
1103 WCHAR *bufferW;
1104 DWORD buflenW;
1106 TRACE("%p %p %p 0x%08lx\n", e, buffer, buflen, flags);
1108 if (!e || !buflen) return PDH_INVALID_ARGUMENT;
1110 memset( &eW, 0, sizeof(eW) );
1111 if (e->szMachineName && !(eW.szMachineName = pdh_strdup_aw( e->szMachineName ))) goto done;
1112 if (e->szObjectName && !(eW.szObjectName = pdh_strdup_aw( e->szObjectName ))) goto done;
1113 if (e->szInstanceName && !(eW.szInstanceName = pdh_strdup_aw( e->szInstanceName ))) goto done;
1114 if (e->szParentInstance && !(eW.szParentInstance = pdh_strdup_aw( e->szParentInstance ))) goto done;
1115 if (e->szCounterName && !(eW.szCounterName = pdh_strdup_aw( e->szCounterName ))) goto done;
1116 eW.dwInstanceIndex = e->dwInstanceIndex;
1118 buflenW = 0;
1119 ret = PdhMakeCounterPathW( &eW, NULL, &buflenW, flags );
1120 if (ret == PDH_MORE_DATA)
1122 if ((bufferW = malloc( buflenW * sizeof(WCHAR) )))
1124 if (!(ret = PdhMakeCounterPathW( &eW, bufferW, &buflenW, flags )))
1126 int len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
1127 if (*buflen >= len) WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, *buflen, NULL, NULL);
1128 else ret = PDH_MORE_DATA;
1129 *buflen = len;
1131 free( bufferW );
1133 else
1134 ret = PDH_MEMORY_ALLOCATION_FAILURE;
1137 done:
1138 free( eW.szMachineName );
1139 free( eW.szObjectName );
1140 free( eW.szInstanceName );
1141 free( eW.szParentInstance );
1142 free( eW.szCounterName );
1143 return ret;
1146 /***********************************************************************
1147 * PdhMakeCounterPathW (PDH.@)
1149 PDH_STATUS WINAPI PdhMakeCounterPathW( PDH_COUNTER_PATH_ELEMENTS_W *e, LPWSTR buffer,
1150 LPDWORD buflen, DWORD flags )
1152 WCHAR path[PDH_MAX_COUNTER_NAME], instance[12];
1153 PDH_STATUS ret = ERROR_SUCCESS;
1154 DWORD len;
1156 TRACE("%p %p %p 0x%08lx\n", e, buffer, buflen, flags);
1158 if (flags) FIXME("unimplemented flags 0x%08lx\n", flags);
1160 if (!e || !e->szCounterName || !e->szObjectName || !buflen)
1161 return PDH_INVALID_ARGUMENT;
1163 path[0] = 0;
1164 if (e->szMachineName)
1166 lstrcatW(path, L"\\\\");
1167 lstrcatW(path, e->szMachineName);
1169 lstrcatW(path, L"\\");
1170 lstrcatW(path, e->szObjectName);
1171 if (e->szInstanceName)
1173 lstrcatW(path, L"(");
1174 if (e->szParentInstance)
1176 lstrcatW(path, e->szParentInstance);
1177 lstrcatW(path, L"/");
1179 lstrcatW(path, e->szInstanceName);
1180 swprintf(instance, ARRAY_SIZE(instance), L"#%u", e->dwInstanceIndex);
1181 lstrcatW(path, instance);
1182 lstrcatW(path, L")");
1184 lstrcatW(path, L"\\");
1185 lstrcatW(path, e->szCounterName);
1187 len = lstrlenW(path) + 1;
1188 if (*buflen >= len) lstrcpyW(buffer, path);
1189 else ret = PDH_MORE_DATA;
1190 *buflen = len;
1191 return ret;
1194 /***********************************************************************
1195 * PdhEnumObjectItemsA (PDH.@)
1197 PDH_STATUS WINAPI PdhEnumObjectItemsA(LPCSTR szDataSource, LPCSTR szMachineName, LPCSTR szObjectName,
1198 LPSTR mszCounterList, LPDWORD pcchCounterListLength, LPSTR mszInstanceList,
1199 LPDWORD pcchInstanceListLength, DWORD dwDetailLevel, DWORD dwFlags)
1201 FIXME("%s, %s, %s, %p, %p, %p, %p, %ld, 0x%lx: stub\n", debugstr_a(szDataSource), debugstr_a(szMachineName),
1202 debugstr_a(szObjectName), mszCounterList, pcchCounterListLength, mszInstanceList,
1203 pcchInstanceListLength, dwDetailLevel, dwFlags);
1205 return PDH_NOT_IMPLEMENTED;
1208 /***********************************************************************
1209 * PdhEnumObjectItemsW (PDH.@)
1211 PDH_STATUS WINAPI PdhEnumObjectItemsW(LPCWSTR szDataSource, LPCWSTR szMachineName, LPCWSTR szObjectName,
1212 LPWSTR mszCounterList, LPDWORD pcchCounterListLength, LPWSTR mszInstanceList,
1213 LPDWORD pcchInstanceListLength, DWORD dwDetailLevel, DWORD dwFlags)
1215 FIXME("%s, %s, %s, %p, %p, %p, %p, %ld, 0x%lx: stub\n", debugstr_w(szDataSource), debugstr_w(szMachineName),
1216 debugstr_w(szObjectName), mszCounterList, pcchCounterListLength, mszInstanceList,
1217 pcchInstanceListLength, dwDetailLevel, dwFlags);
1219 return PDH_NOT_IMPLEMENTED;
1222 /***********************************************************************
1223 * PdhSetDefaultRealTimeDataSource (PDH.@)
1225 PDH_STATUS WINAPI PdhSetDefaultRealTimeDataSource( DWORD source )
1227 FIXME("%lu\n", source);
1228 return ERROR_SUCCESS;
1231 /***********************************************************************
1232 * PdhGetLogFileTypeA (PDH.@)
1234 PDH_STATUS WINAPI PdhGetLogFileTypeA(const char *log, DWORD *type)
1236 FIXME("%s, %p: stub\n", debugstr_a(log), type);
1237 return PDH_NOT_IMPLEMENTED;
1240 /***********************************************************************
1241 * PdhGetLogFileTypeW (PDH.@)
1243 PDH_STATUS WINAPI PdhGetLogFileTypeW(const WCHAR *log, DWORD *type)
1245 FIXME("%s, %p: stub\n", debugstr_w(log), type);
1246 return PDH_NOT_IMPLEMENTED;
1249 /***********************************************************************
1250 * PdhBindInputDataSourceA (PDH.@)
1252 PDH_STATUS WINAPI PdhBindInputDataSourceA(PDH_HLOG *source, const char *filenamelist)
1254 FIXME("%p %s: stub\n", source, debugstr_a(filenamelist));
1255 return PDH_NOT_IMPLEMENTED;
1258 /***********************************************************************
1259 * PdhBindInputDataSourceW (PDH.@)
1261 PDH_STATUS WINAPI PdhBindInputDataSourceW(PDH_HLOG *source, const WCHAR *filenamelist)
1263 FIXME("%p %s: stub\n", source, debugstr_w(filenamelist));
1264 return PDH_NOT_IMPLEMENTED;