push aea352fc3df615e3f4b48daf6f897ea93ad1fffd
[wine/hacks.git] / dlls / pdh / pdh_main.c
blobb21391a807f79ac434bbbb0b7302a7f5b9cffe41
1 /*
2 * Performance Data Helper (pdh.dll)
4 * Copyright 2007 Andrey Turkin
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
25 #include "windef.h"
26 #include "winbase.h"
28 #include "pdh.h"
29 #include "pdhmsg.h"
30 #include "winperf.h"
32 #include "wine/debug.h"
33 #include "wine/list.h"
34 #include "wine/unicode.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(pdh);
38 static inline void *pdh_alloc( SIZE_T size )
40 return HeapAlloc( GetProcessHeap(), 0, size );
43 static inline void *pdh_alloc_zero( SIZE_T size )
45 return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
48 static inline void pdh_free( LPVOID mem )
50 HeapFree( GetProcessHeap(), 0, mem );
53 static inline WCHAR *pdh_strdup( const WCHAR *src )
55 WCHAR *dst;
57 if (!src) return NULL;
58 if ((dst = pdh_alloc( (strlenW( src ) + 1) * sizeof(WCHAR) ))) strcpyW( dst, src );
59 return dst;
62 static inline WCHAR *pdh_strdup_aw( const char *src )
64 int len;
65 WCHAR *dst;
67 if (!src) return NULL;
68 len = MultiByteToWideChar( CP_ACP, 0, src, -1, NULL, 0 );
69 if ((dst = pdh_alloc( len * sizeof(WCHAR) ))) MultiByteToWideChar( CP_ACP, 0, src, -1, dst, len );
70 return dst;
73 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
75 TRACE("(0x%p, %d, %p)\n",hinstDLL,fdwReason,lpvReserved);
77 if (fdwReason == DLL_WINE_PREATTACH) return FALSE; /* prefer native version */
79 if (fdwReason == DLL_PROCESS_ATTACH)
81 DisableThreadLibraryCalls( hinstDLL );
84 return TRUE;
87 struct counter
89 struct list entry;
90 WCHAR *path; /* identifier */
91 DWORD type; /* counter type */
92 DWORD status; /* update status */
93 LONG scale; /* scale factor */
94 LONG defaultscale; /* default scale factor */
95 DWORD_PTR user; /* user data */
96 DWORD_PTR queryuser; /* query user data */
97 LONGLONG base; /* samples per second */
98 FILETIME stamp; /* time stamp */
99 void (CALLBACK *collect)( struct counter * ); /* collect callback */
100 union
102 LONG longvalue;
103 double doublevalue;
104 LONGLONG largevalue;
105 } one; /* first value */
106 union
108 LONG longvalue;
109 double doublevalue;
110 LONGLONG largevalue;
111 } two; /* second value */
114 static struct counter *create_counter( void )
116 struct counter *counter;
118 if ((counter = pdh_alloc_zero( sizeof(struct counter) ))) return counter;
119 return NULL;
122 #define PDH_MAGIC_QUERY 0x50444830 /* 'PDH0' */
124 struct query
126 DWORD magic; /* signature */
127 DWORD_PTR user; /* user data */
128 struct list counters; /* counter list */
131 static struct query *create_query( void )
133 struct query *query;
135 if ((query = pdh_alloc_zero( sizeof(struct query) )))
137 query->magic = PDH_MAGIC_QUERY;
138 list_init( &query->counters );
139 return query;
141 return NULL;
144 struct source
146 const WCHAR *path; /* identifier */
147 void (CALLBACK *collect)( struct counter * ); /* collect callback */
148 DWORD type; /* counter type */
149 LONG scale; /* default scale factor */
150 LONGLONG base; /* samples per second */
153 /* counter source registry */
154 static const struct source counter_sources[] =
156 { NULL, NULL, 0, 0, 0 }
159 /***********************************************************************
160 * PdhAddCounterA (PDH.@)
162 PDH_STATUS WINAPI PdhAddCounterA( PDH_HQUERY query, LPCSTR path,
163 DWORD_PTR userdata, PDH_HCOUNTER *counter )
165 PDH_STATUS ret;
166 WCHAR *pathW;
168 TRACE("%p %s %lx %p\n", query, debugstr_a(path), userdata, counter);
170 if (!path) return PDH_INVALID_ARGUMENT;
172 if (!(pathW = pdh_strdup_aw( path )))
173 return PDH_MEMORY_ALLOCATION_FAILURE;
175 ret = PdhAddCounterW( query, pathW, userdata, counter );
177 pdh_free( pathW );
178 return ret;
181 /***********************************************************************
182 * PdhAddCounterW (PDH.@)
184 PDH_STATUS WINAPI PdhAddCounterW( PDH_HQUERY hquery, LPCWSTR path,
185 DWORD_PTR userdata, PDH_HCOUNTER *hcounter )
187 struct query *query = hquery;
188 struct counter *counter;
189 unsigned int i;
191 TRACE("%p %s %lx %p\n", hquery, debugstr_w(path), userdata, hcounter);
193 if (!path || !hcounter) return PDH_INVALID_ARGUMENT;
194 if (!query || (query->magic != PDH_MAGIC_QUERY)) return PDH_INVALID_HANDLE;
196 *hcounter = NULL;
197 for (i = 0; i < sizeof(counter_sources) / sizeof(counter_sources[0]); i++)
199 if (strstrW( path, counter_sources[i].path ))
201 if ((counter = create_counter()))
203 counter->path = pdh_strdup( counter_sources[i].path );
204 counter->collect = counter_sources[i].collect;
205 counter->type = counter_sources[i].type;
206 counter->defaultscale = counter_sources[i].scale;
207 counter->base = counter_sources[i].base;
208 counter->queryuser = query->user;
209 counter->user = userdata;
211 list_add_tail( &query->counters, &counter->entry );
213 *hcounter = counter;
214 return ERROR_SUCCESS;
216 return PDH_MEMORY_ALLOCATION_FAILURE;
219 return PDH_CSTATUS_NO_COUNTER;
222 /***********************************************************************
223 * PdhCloseQuery (PDH.@)
225 PDH_STATUS WINAPI PdhCloseQuery( PDH_HQUERY handle )
227 struct query *query = handle;
228 struct list *item;
230 TRACE("%p\n", handle);
232 if (!query || (query->magic != PDH_MAGIC_QUERY)) return PDH_INVALID_HANDLE;
234 LIST_FOR_EACH( item, &query->counters )
236 struct counter *counter = LIST_ENTRY( item, struct counter, entry );
238 list_remove( &counter->entry );
240 pdh_free( counter->path );
241 pdh_free( counter );
244 pdh_free( query );
245 return ERROR_SUCCESS;
248 /***********************************************************************
249 * PdhCollectQueryData (PDH.@)
251 PDH_STATUS WINAPI PdhCollectQueryData( PDH_HQUERY handle )
253 struct query *query = handle;
254 struct list *item;
256 TRACE("%p\n", handle);
258 if (!query || (query->magic != PDH_MAGIC_QUERY)) return PDH_INVALID_HANDLE;
260 LIST_FOR_EACH( item, &query->counters )
262 SYSTEMTIME time;
263 struct counter *counter = LIST_ENTRY( item, struct counter, entry );
265 counter->collect( counter );
267 GetLocalTime( &time );
268 SystemTimeToFileTime( &time, &counter->stamp );
270 return ERROR_SUCCESS;
273 /***********************************************************************
274 * PdhOpenQueryA (PDH.@)
276 PDH_STATUS WINAPI PdhOpenQueryA( LPCSTR source, DWORD_PTR userdata, PDH_HQUERY *query )
278 PDH_STATUS ret;
279 WCHAR *sourceW = NULL;
281 TRACE("%s %lx %p\n", debugstr_a(source), userdata, query);
283 if (source && !(sourceW = pdh_strdup_aw( source ))) return PDH_MEMORY_ALLOCATION_FAILURE;
285 ret = PdhOpenQueryW( sourceW, userdata, query );
286 pdh_free( sourceW );
288 return ret;
291 /***********************************************************************
292 * PdhOpenQueryW (PDH.@)
294 PDH_STATUS WINAPI PdhOpenQueryW( LPCWSTR source, DWORD_PTR userdata, PDH_HQUERY *handle )
296 struct query *query;
298 TRACE("%s %lx %p\n", debugstr_w(source), userdata, handle);
300 if (!handle) return PDH_INVALID_ARGUMENT;
302 if (source)
304 FIXME("log file data source not supported\n");
305 return PDH_INVALID_ARGUMENT;
307 if ((query = create_query()))
309 query->user = userdata;
310 *handle = query;
312 return ERROR_SUCCESS;
314 return PDH_MEMORY_ALLOCATION_FAILURE;
317 /***********************************************************************
318 * PdhRemoveCounter (PDH.@)
320 PDH_STATUS WINAPI PdhRemoveCounter( PDH_HCOUNTER handle )
322 struct counter *counter = handle;
324 TRACE("%p\n", handle);
326 if (!counter) return PDH_INVALID_HANDLE;
328 list_remove( &counter->entry );
330 pdh_free( counter->path );
331 pdh_free( counter );
333 return ERROR_SUCCESS;