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
23 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
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
)
57 if (!src
) return NULL
;
58 if ((dst
= pdh_alloc( (strlenW( src
) + 1) * sizeof(WCHAR
) ))) strcpyW( dst
, src
);
62 static inline WCHAR
*pdh_strdup_aw( const char *src
)
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
);
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
);
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 */
105 } one
; /* first value */
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
;
122 #define PDH_MAGIC_QUERY 0x50444830 /* 'PDH0' */
126 DWORD magic
; /* signature */
127 DWORD_PTR user
; /* user data */
128 struct list counters
; /* counter list */
131 static struct query
*create_query( void )
135 if ((query
= pdh_alloc_zero( sizeof(struct query
) )))
137 query
->magic
= PDH_MAGIC_QUERY
;
138 list_init( &query
->counters
);
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
)
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
);
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
;
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
;
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
);
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
;
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
);
245 return ERROR_SUCCESS
;
248 /***********************************************************************
249 * PdhCollectQueryData (PDH.@)
251 PDH_STATUS WINAPI
PdhCollectQueryData( PDH_HQUERY handle
)
253 struct query
*query
= handle
;
256 TRACE("%p\n", handle
);
258 if (!query
|| (query
->magic
!= PDH_MAGIC_QUERY
)) return PDH_INVALID_HANDLE
;
260 LIST_FOR_EACH( item
, &query
->counters
)
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
)
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
);
291 /***********************************************************************
292 * PdhOpenQueryW (PDH.@)
294 PDH_STATUS WINAPI
PdhOpenQueryW( LPCWSTR source
, DWORD_PTR userdata
, PDH_HQUERY
*handle
)
298 TRACE("%s %lx %p\n", debugstr_w(source
), userdata
, handle
);
300 if (!handle
) return PDH_INVALID_ARGUMENT
;
304 FIXME("log file data source not supported\n");
305 return PDH_INVALID_ARGUMENT
;
307 if ((query
= create_query()))
309 query
->user
= userdata
;
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
);
333 return ERROR_SUCCESS
;