2 * Win32 debugger functions
4 * Copyright (C) 1999 Alexandre Julliard
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
26 #define WIN32_NO_STATUS
33 #define PSAPI_VERSION 1 /* avoid K32 function remapping */
37 #include "wine/exception.h"
39 #include "kernelbase.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(seh
);
43 WINE_DECLARE_DEBUG_CHANNEL(winedbg
);
45 typedef INT (WINAPI
*MessageBoxA_funcptr
)(HWND
,LPCSTR
,LPCSTR
,UINT
);
46 typedef INT (WINAPI
*MessageBoxW_funcptr
)(HWND
,LPCWSTR
,LPCWSTR
,UINT
);
48 static PTOP_LEVEL_EXCEPTION_FILTER top_filter
;
50 void *dummy
= RtlUnwind
; /* force importing RtlUnwind from ntdll */
52 /***********************************************************************
53 * CheckRemoteDebuggerPresent (kernelbase.@)
55 BOOL WINAPI DECLSPEC_HOTPATCH
CheckRemoteDebuggerPresent( HANDLE process
, BOOL
*present
)
59 if (!process
|| !present
)
61 SetLastError( ERROR_INVALID_PARAMETER
);
64 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessDebugPort
, &port
, sizeof(port
), NULL
)))
71 /**********************************************************************
72 * ContinueDebugEvent (kernelbase.@)
74 BOOL WINAPI DECLSPEC_HOTPATCH
ContinueDebugEvent( DWORD pid
, DWORD tid
, DWORD status
)
78 id
.UniqueProcess
= ULongToHandle( pid
);
79 id
.UniqueThread
= ULongToHandle( tid
);
80 return set_ntstatus( DbgUiContinue( &id
, status
));
84 /**********************************************************************
85 * DebugActiveProcess (kernelbase.@)
87 BOOL WINAPI DECLSPEC_HOTPATCH
DebugActiveProcess( DWORD pid
)
92 if (!set_ntstatus( DbgUiConnectToDbg() )) return FALSE
;
93 if (!(process
= OpenProcess( PROCESS_VM_READ
| PROCESS_VM_WRITE
| PROCESS_SUSPEND_RESUME
|
94 PROCESS_QUERY_INFORMATION
| PROCESS_CREATE_THREAD
, FALSE
, pid
)))
96 status
= DbgUiDebugActiveProcess( process
);
98 return set_ntstatus( status
);
102 /**********************************************************************
103 * DebugActiveProcessStop (kernelbase.@)
105 BOOL WINAPI DECLSPEC_HOTPATCH
DebugActiveProcessStop( DWORD pid
)
110 if (!(process
= OpenProcess( PROCESS_VM_READ
| PROCESS_VM_WRITE
| PROCESS_SUSPEND_RESUME
, FALSE
, pid
)))
112 status
= DbgUiStopDebugging( process
);
114 return set_ntstatus( status
);
118 /***********************************************************************
119 * DebugBreak (kernelbase.@)
121 #if defined(__i386__) || defined(__x86_64__)
122 __ASM_STDCALL_FUNC( DebugBreak
, 0, "jmp " __ASM_STDCALL("DbgBreakPoint", 0) )
124 void WINAPI
DebugBreak(void)
131 /**************************************************************************
132 * FatalAppExitA (kernelbase.@)
134 void WINAPI DECLSPEC_HOTPATCH
FatalAppExitA( UINT action
, LPCSTR str
)
136 HMODULE mod
= GetModuleHandleA( "user32.dll" );
137 MessageBoxA_funcptr pMessageBoxA
= NULL
;
139 if (mod
) pMessageBoxA
= (MessageBoxA_funcptr
)GetProcAddress( mod
, "MessageBoxA" );
140 if (pMessageBoxA
) pMessageBoxA( 0, str
, NULL
, MB_SYSTEMMODAL
| MB_OK
);
141 else ERR( "%s\n", debugstr_a(str
) );
142 RtlExitUserProcess( 1 );
146 /**************************************************************************
147 * FatalAppExitW (kernelbase.@)
149 void WINAPI DECLSPEC_HOTPATCH
FatalAppExitW( UINT action
, LPCWSTR str
)
151 HMODULE mod
= GetModuleHandleW( L
"user32.dll" );
152 MessageBoxW_funcptr pMessageBoxW
= NULL
;
154 if (mod
) pMessageBoxW
= (MessageBoxW_funcptr
)GetProcAddress( mod
, "MessageBoxW" );
155 if (pMessageBoxW
) pMessageBoxW( 0, str
, NULL
, MB_SYSTEMMODAL
| MB_OK
);
156 else ERR( "%s\n", debugstr_w(str
) );
157 RtlExitUserProcess( 1 );
161 /***********************************************************************
162 * IsDebuggerPresent (kernelbase.@)
164 BOOL WINAPI
IsDebuggerPresent(void)
166 return NtCurrentTeb()->Peb
->BeingDebugged
;
170 static LONG WINAPI
debug_exception_handler( EXCEPTION_POINTERS
*eptr
)
172 EXCEPTION_RECORD
*rec
= eptr
->ExceptionRecord
;
173 return (rec
->ExceptionCode
== DBG_PRINTEXCEPTION_C
) ? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH
;
176 /***********************************************************************
177 * OutputDebugStringA (kernelbase.@)
179 void WINAPI DECLSPEC_HOTPATCH
OutputDebugStringA( LPCSTR str
)
181 static HANDLE DBWinMutex
= NULL
;
182 static BOOL mutex_inited
= FALSE
;
183 BOOL caught_by_dbg
= TRUE
;
186 WARN( "%s\n", debugstr_a(str
) );
188 /* raise exception, WaitForDebugEvent() will generate a corresponding debug event */
192 args
[0] = strlen(str
) + 1;
193 args
[1] = (ULONG_PTR
)str
;
194 RaiseException( DBG_PRINTEXCEPTION_C
, 0, 2, args
);
196 __EXCEPT(debug_exception_handler
)
198 caught_by_dbg
= FALSE
;
201 if (caught_by_dbg
) return;
203 /* send string to a system-wide monitor */
206 /* first call to OutputDebugString, initialize mutex handle */
207 HANDLE mutex
= CreateMutexExW( NULL
, L
"DBWinMutex", 0, SYNCHRONIZE
);
210 if (InterlockedCompareExchangePointer( &DBWinMutex
, mutex
, 0 ) != 0)
211 /* someone beat us here... */
212 CloseHandle( mutex
);
221 mapping
= OpenFileMappingW( FILE_MAP_WRITE
, FALSE
, L
"DBWIN_BUFFER" );
225 HANDLE eventbuffer
, eventdata
;
227 buffer
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 0 );
228 eventbuffer
= OpenEventW( SYNCHRONIZE
, FALSE
, L
"DBWIN_BUFFER_READY" );
229 eventdata
= OpenEventW( EVENT_MODIFY_STATE
, FALSE
, L
"DBWIN_DATA_READY" );
231 if (buffer
&& eventbuffer
&& eventdata
)
233 /* monitor is present, synchronize with other OutputDebugString invocations */
234 WaitForSingleObject( DBWinMutex
, INFINITE
);
236 /* acquire control over the buffer */
237 if (WaitForSingleObject( eventbuffer
, 10000 ) == WAIT_OBJECT_0
)
239 int str_len
= strlen( str
);
244 } *mon_buffer
= (struct _mon_buffer_t
*) buffer
;
246 if (str_len
> (4096 - sizeof(DWORD
) - 1)) str_len
= 4096 - sizeof(DWORD
) - 1;
247 mon_buffer
->pid
= GetCurrentProcessId();
248 memcpy( mon_buffer
->buffer
, str
, str_len
);
249 mon_buffer
->buffer
[str_len
] = 0;
251 /* signal data ready */
252 SetEvent( eventdata
);
254 ReleaseMutex( DBWinMutex
);
257 if (buffer
) UnmapViewOfFile( buffer
);
258 if (eventbuffer
) CloseHandle( eventbuffer
);
259 if (eventdata
) CloseHandle( eventdata
);
260 CloseHandle( mapping
);
266 /***********************************************************************
267 * OutputDebugStringW (kernelbase.@)
269 void WINAPI DECLSPEC_HOTPATCH
OutputDebugStringW( LPCWSTR str
)
274 RtlInitUnicodeString( &strW
, str
);
275 if (!RtlUnicodeStringToAnsiString( &strA
, &strW
, TRUE
))
277 OutputDebugStringA( strA
.Buffer
);
278 RtlFreeAnsiString( &strA
);
283 /*******************************************************************
284 * RaiseException (kernelbase.@)
286 void WINAPI DECLSPEC_HOTPATCH
RaiseException( DWORD code
, DWORD flags
, DWORD count
, const ULONG_PTR
*args
)
288 EXCEPTION_RECORD record
;
290 record
.ExceptionCode
= code
;
291 record
.ExceptionFlags
= flags
& EH_NONCONTINUABLE
;
292 record
.ExceptionRecord
= NULL
;
293 record
.ExceptionAddress
= RaiseException
;
296 if (count
> EXCEPTION_MAXIMUM_PARAMETERS
) count
= EXCEPTION_MAXIMUM_PARAMETERS
;
297 record
.NumberParameters
= count
;
298 memcpy( record
.ExceptionInformation
, args
, count
* sizeof(*args
) );
300 else record
.NumberParameters
= 0;
302 RtlRaiseException( &record
);
304 __ASM_STDCALL_IMPORT(RaiseException
,16)
306 /*******************************************************************
307 * RaiseFailFastException (kernelbase.@)
309 void WINAPI DECLSPEC_HOTPATCH
RaiseFailFastException( EXCEPTION_RECORD
*record
, CONTEXT
*context
, DWORD flags
)
311 FIXME( "(%p, %p, %ld) stub\n", record
, context
, flags
);
312 TerminateProcess( GetCurrentProcess(), STATUS_FAIL_FAST_EXCEPTION
);
315 /***********************************************************************
316 * SetUnhandledExceptionFilter (kernelbase.@)
318 LPTOP_LEVEL_EXCEPTION_FILTER WINAPI DECLSPEC_HOTPATCH
SetUnhandledExceptionFilter(
319 LPTOP_LEVEL_EXCEPTION_FILTER filter
)
321 return InterlockedExchangePointer( (void **)&top_filter
, filter
);
325 /*******************************************************************
326 * format_exception_msg
328 static void format_exception_msg( const EXCEPTION_POINTERS
*ptr
, char *buffer
, int size
)
330 const EXCEPTION_RECORD
*rec
= ptr
->ExceptionRecord
;
333 switch(rec
->ExceptionCode
)
335 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
336 len
= snprintf( buffer
, size
, "Unhandled division by zero" );
338 case EXCEPTION_INT_OVERFLOW
:
339 len
= snprintf( buffer
, size
, "Unhandled overflow" );
341 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
342 len
= snprintf( buffer
, size
, "Unhandled array bounds" );
344 case EXCEPTION_ILLEGAL_INSTRUCTION
:
345 len
= snprintf( buffer
, size
, "Unhandled illegal instruction" );
347 case EXCEPTION_STACK_OVERFLOW
:
348 len
= snprintf( buffer
, size
, "Unhandled stack overflow" );
350 case EXCEPTION_PRIV_INSTRUCTION
:
351 len
= snprintf( buffer
, size
, "Unhandled privileged instruction" );
353 case EXCEPTION_ACCESS_VIOLATION
:
354 if (rec
->NumberParameters
== 2)
355 len
= snprintf( buffer
, size
, "Unhandled page fault on %s access to %p",
356 rec
->ExceptionInformation
[0] == EXCEPTION_WRITE_FAULT
? "write" :
357 rec
->ExceptionInformation
[0] == EXCEPTION_EXECUTE_FAULT
? "execute" : "read",
358 (void *)rec
->ExceptionInformation
[1]);
360 len
= snprintf( buffer
, size
, "Unhandled page fault");
362 case EXCEPTION_DATATYPE_MISALIGNMENT
:
363 len
= snprintf( buffer
, size
, "Unhandled alignment" );
366 len
= snprintf( buffer
, size
, "Unhandled ^C");
368 case STATUS_POSSIBLE_DEADLOCK
:
369 len
= snprintf( buffer
, size
, "Critical section %p wait failed",
370 (void *)rec
->ExceptionInformation
[0]);
372 case EXCEPTION_WINE_STUB
:
373 if ((ULONG_PTR
)rec
->ExceptionInformation
[1] >> 16)
374 len
= snprintf( buffer
, size
, "Unimplemented function %s.%s called",
375 (char *)rec
->ExceptionInformation
[0], (char *)rec
->ExceptionInformation
[1] );
377 len
= snprintf( buffer
, size
, "Unimplemented function %s.%Id called",
378 (char *)rec
->ExceptionInformation
[0], rec
->ExceptionInformation
[1] );
380 case EXCEPTION_WINE_ASSERTION
:
381 len
= snprintf( buffer
, size
, "Assertion failed" );
384 len
= snprintf( buffer
, size
, "Unhandled exception 0x%08lx in thread %lx",
385 rec
->ExceptionCode
, GetCurrentThreadId());
388 if (len
< 0 || len
>= size
) return;
389 snprintf( buffer
+ len
, size
- len
, " at address %p", ptr
->ExceptionRecord
->ExceptionAddress
);
393 /******************************************************************
396 * Does the effective debugger startup according to 'format'
398 static BOOL
start_debugger( EXCEPTION_POINTERS
*epointers
, HANDLE event
)
400 OBJECT_ATTRIBUTES attr
;
401 UNICODE_STRING nameW
= RTL_CONSTANT_STRING( L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug" );
402 WCHAR
*cmdline
, *env
, *p
, *format
= NULL
;
404 DWORD autostart
= TRUE
;
405 PROCESS_INFORMATION info
;
406 STARTUPINFOW startup
;
410 format_exception_msg( epointers
, buffer
, sizeof(buffer
) );
411 MESSAGE( "wine: %s (thread %04lx), starting debugger...\n", buffer
, GetCurrentThreadId() );
413 attr
.Length
= sizeof(attr
);
414 attr
.RootDirectory
= 0;
415 attr
.ObjectName
= &nameW
;
417 attr
.SecurityDescriptor
= NULL
;
418 attr
.SecurityQualityOfService
= NULL
;
420 if (!NtOpenKey( &dbg_key
, KEY_READ
, &attr
))
422 KEY_VALUE_PARTIAL_INFORMATION
*info
;
423 DWORD format_size
= 0;
425 RtlInitUnicodeString( &nameW
, L
"Debugger" );
426 if (NtQueryValueKey( dbg_key
, &nameW
, KeyValuePartialInformation
,
427 NULL
, 0, &format_size
) == STATUS_BUFFER_TOO_SMALL
)
429 char *data
= HeapAlloc( GetProcessHeap(), 0, format_size
);
430 NtQueryValueKey( dbg_key
, &nameW
, KeyValuePartialInformation
,
431 data
, format_size
, &format_size
);
432 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)data
;
433 format
= HeapAlloc( GetProcessHeap(), 0, info
->DataLength
+ sizeof(WCHAR
) );
434 memcpy( format
, info
->Data
, info
->DataLength
);
435 format
[info
->DataLength
/ sizeof(WCHAR
)] = 0;
437 if (info
->Type
== REG_EXPAND_SZ
)
441 format_size
= ExpandEnvironmentStringsW( format
, NULL
, 0 );
442 tmp
= HeapAlloc( GetProcessHeap(), 0, format_size
* sizeof(WCHAR
));
443 ExpandEnvironmentStringsW( format
, tmp
, format_size
);
444 HeapFree( GetProcessHeap(), 0, format
);
447 HeapFree( GetProcessHeap(), 0, data
);
450 RtlInitUnicodeString( &nameW
, L
"Auto" );
451 if (!NtQueryValueKey( dbg_key
, &nameW
, KeyValuePartialInformation
,
452 buffer
, sizeof(buffer
)-sizeof(WCHAR
), &format_size
))
454 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
455 if (info
->Type
== REG_DWORD
) memcpy( &autostart
, info
->Data
, sizeof(DWORD
) );
456 else if (info
->Type
== REG_SZ
)
458 WCHAR
*str
= (WCHAR
*)info
->Data
;
459 str
[info
->DataLength
/sizeof(WCHAR
)] = 0;
460 autostart
= wcstol( str
, NULL
, 10 );
469 size_t format_size
= lstrlenW( format
) + 2*20;
470 cmdline
= HeapAlloc( GetProcessHeap(), 0, format_size
* sizeof(WCHAR
) );
471 swprintf( cmdline
, format_size
, format
, GetCurrentProcessId(), HandleToLong(event
) );
472 HeapFree( GetProcessHeap(), 0, format
);
476 cmdline
= HeapAlloc( GetProcessHeap(), 0, 80 * sizeof(WCHAR
) );
477 swprintf( cmdline
, 80, L
"winedbg --auto %ld %ld", GetCurrentProcessId(), HandleToLong(event
) );
482 HMODULE mod
= GetModuleHandleA( "user32.dll" );
483 MessageBoxA_funcptr pMessageBoxA
= NULL
;
485 if (mod
) pMessageBoxA
= (void *)GetProcAddress( mod
, "MessageBoxA" );
488 static const char msg
[] = ".\nDo you wish to debug it?";
490 format_exception_msg( epointers
, buffer
, sizeof(buffer
) - sizeof(msg
) );
491 strcat( buffer
, msg
);
492 if (pMessageBoxA( 0, buffer
, "Exception raised", MB_YESNO
| MB_ICONHAND
) == IDNO
)
494 TRACE( "Killing process\n" );
500 /* make WINEDEBUG empty in the environment */
501 env
= GetEnvironmentStringsW();
502 if (!TRACE_ON(winedbg
))
504 for (p
= env
; *p
; p
+= lstrlenW(p
) + 1)
506 if (!wcsncmp( p
, L
"WINEDEBUG=", 10 ))
508 WCHAR
*next
= p
+ lstrlenW(p
);
509 WCHAR
*end
= next
+ 1;
510 while (*end
) end
+= lstrlenW(end
) + 1;
511 memmove( p
+ 10, next
, end
+ 1 - next
);
517 TRACE( "Starting debugger %s\n", debugstr_w(cmdline
) );
518 memset( &startup
, 0, sizeof(startup
) );
519 startup
.cb
= sizeof(startup
);
520 startup
.dwFlags
= STARTF_USESHOWWINDOW
;
521 startup
.wShowWindow
= SW_SHOWNORMAL
;
522 ret
= CreateProcessW( NULL
, cmdline
, NULL
, NULL
, TRUE
, 0, env
, NULL
, &startup
, &info
);
523 FreeEnvironmentStringsW( env
);
527 /* wait for debugger to come up... */
529 CloseHandle( info
.hThread
);
531 handles
[1] = info
.hProcess
;
532 WaitForMultipleObjects( 2, handles
, FALSE
, INFINITE
);
533 CloseHandle( info
.hProcess
);
535 else ERR( "Couldn't start debugger %s (%ld)\n"
536 "Read the Wine Developers Guide on how to set up winedbg or another debugger\n",
537 debugstr_w(cmdline
), GetLastError() );
539 HeapFree(GetProcessHeap(), 0, cmdline
);
543 /******************************************************************
544 * start_debugger_atomic
546 * starts the debugger in an atomic way:
547 * - either the debugger is not started and it is started
548 * - or the debugger has already been started by another thread
549 * - or the debugger couldn't be started
551 * returns TRUE for the two first conditions, FALSE for the last
553 static BOOL
start_debugger_atomic( EXCEPTION_POINTERS
*epointers
)
559 OBJECT_ATTRIBUTES attr
;
562 attr
.Length
= sizeof(attr
);
563 attr
.RootDirectory
= 0;
564 attr
.Attributes
= OBJ_INHERIT
;
565 attr
.ObjectName
= NULL
;
566 attr
.SecurityDescriptor
= NULL
;
567 attr
.SecurityQualityOfService
= NULL
;
569 /* ask for manual reset, so that once the debugger is started,
570 * every thread will know it */
571 NtCreateEvent( &event
, EVENT_ALL_ACCESS
, &attr
, NotificationEvent
, FALSE
);
572 if (InterlockedCompareExchangePointer( &once
, event
, 0 ) == 0)
574 /* ok, our event has been set... we're the winning thread */
575 BOOL ret
= start_debugger( epointers
, once
);
579 /* so that the other threads won't be stuck */
580 NtSetEvent( once
, NULL
);
585 /* someone beat us here... */
586 CloseHandle( event
);
589 /* and wait for the winner to have actually created the debugger */
590 WaitForSingleObject( once
, INFINITE
);
591 /* in fact, here, we only know that someone has tried to start the debugger,
592 * we'll know by reposting the exception if it has actually attached
593 * to the current process */
598 /*******************************************************************
599 * check_resource_write
601 * Check if the exception is a write attempt to the resource data.
602 * If yes, we unprotect the resources to let broken apps continue
603 * (Windows does this too).
605 static BOOL
check_resource_write( void *addr
)
610 MEMORY_BASIC_INFORMATION info
;
612 if (!VirtualQuery( addr
, &info
, sizeof(info
) )) return FALSE
;
613 if (info
.State
== MEM_FREE
|| !(info
.Type
& MEM_IMAGE
)) return FALSE
;
614 if (!(rsrc
= RtlImageDirectoryEntryToData( info
.AllocationBase
, TRUE
,
615 IMAGE_DIRECTORY_ENTRY_RESOURCE
, &size
)))
617 if (addr
< rsrc
|| (char *)addr
>= (char *)rsrc
+ size
) return FALSE
;
618 TRACE( "Broken app is writing to the resource data, enabling work-around\n" );
619 VirtualProtect( rsrc
, size
, PAGE_READWRITE
, &old_prot
);
624 /*******************************************************************
625 * UnhandledExceptionFilter (kernelbase.@)
627 LONG WINAPI
UnhandledExceptionFilter( EXCEPTION_POINTERS
*epointers
)
629 const EXCEPTION_RECORD
*rec
= epointers
->ExceptionRecord
;
631 if (rec
->ExceptionCode
== EXCEPTION_ACCESS_VIOLATION
&& rec
->NumberParameters
>= 2)
633 switch (rec
->ExceptionInformation
[0])
635 case EXCEPTION_WRITE_FAULT
:
636 if (check_resource_write( (void *)rec
->ExceptionInformation
[1] ))
637 return EXCEPTION_CONTINUE_EXECUTION
;
642 if (!NtCurrentTeb()->Peb
->BeingDebugged
)
644 if (rec
->ExceptionCode
== CONTROL_C_EXIT
)
646 /* do not launch the debugger on ^C, simply terminate the process */
647 TerminateProcess( GetCurrentProcess(), 1 );
652 LONG ret
= top_filter( epointers
);
653 if (ret
!= EXCEPTION_CONTINUE_SEARCH
) return ret
;
656 /* FIXME: Should check the current error mode */
658 if (!start_debugger_atomic( epointers
) || !NtCurrentTeb()->Peb
->BeingDebugged
)
659 return EXCEPTION_EXECUTE_HANDLER
;
661 return EXCEPTION_CONTINUE_SEARCH
;
665 /***********************************************************************
666 * WerGetFlags (kernelbase.@)
668 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerGetFlags( HANDLE process
, DWORD
*flags
)
670 FIXME( "(%p, %p) stub\n", process
, flags
);
675 /***********************************************************************
676 * WerRegisterFile (kernelbase.@)
678 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerRegisterFile( const WCHAR
*file
, WER_REGISTER_FILE_TYPE type
,
681 FIXME( "(%s, %d, %ld) stub\n", debugstr_w(file
), type
, flags
);
686 /***********************************************************************
687 * WerRegisterMemoryBlock (kernelbase.@)
689 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerRegisterMemoryBlock( void *block
, DWORD size
)
691 FIXME( "(%p %ld) stub\n", block
, size
);
696 /***********************************************************************
697 * WerRegisterRuntimeExceptionModule (kernelbase.@)
699 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerRegisterRuntimeExceptionModule( const WCHAR
*dll
, void *context
)
701 FIXME( "(%s, %p) stub\n", debugstr_w(dll
), context
);
706 /***********************************************************************
707 * WerSetFlags (kernelbase.@)
709 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerSetFlags( DWORD flags
)
711 FIXME("(%ld) stub\n", flags
);
716 /***********************************************************************
717 * WerUnregisterFile (kernelbase.@)
719 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerUnregisterFile( const WCHAR
*file
)
721 FIXME( "(%s) stub\n", debugstr_w(file
) );
726 /***********************************************************************
727 * WerUnregisterMemoryBlock (kernelbase.@)
729 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerUnregisterMemoryBlock( void *block
)
731 FIXME( "(%p) stub\n", block
);
736 /***********************************************************************
737 * WerUnregisterRuntimeExceptionModule (kernelbase.@)
739 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerUnregisterRuntimeExceptionModule( const WCHAR
*dll
, void *context
)
741 FIXME( "(%s, %p) stub\n", debugstr_w(dll
), context
);
746 /***********************************************************************
748 ***********************************************************************/
751 typedef struct _LDR_DATA_TABLE_ENTRY32
753 LIST_ENTRY32 InLoadOrderModuleList
;
754 LIST_ENTRY32 InMemoryOrderModuleList
;
755 LIST_ENTRY32 InInitializationOrderModuleList
;
759 UNICODE_STRING32 FullDllName
;
760 UNICODE_STRING32 BaseDllName
;
761 } LDR_DATA_TABLE_ENTRY32
;
763 struct module_iterator
769 LDR_DATA_TABLE_ENTRY ldr_module
;
770 LDR_DATA_TABLE_ENTRY32 ldr_module32
;
774 /* Caller must ensure that wow64=TRUE is only passed from 64bit for 'process' being a wow64 process */
775 static BOOL
init_module_iterator( struct module_iterator
*iter
, HANDLE process
, BOOL wow64
)
777 PROCESS_BASIC_INFORMATION pbi
;
778 PPEB_LDR_DATA ldr_data
;
780 /* get address of PEB */
781 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessBasicInformation
,
782 &pbi
, sizeof(pbi
), NULL
)))
788 PEB_LDR_DATA32
*ldr_data32_ptr
;
789 DWORD ldr_data32
, first_module
;
792 peb32
= (PEB32
*)((char *)pbi
.PebBaseAddress
+ 0x1000);
793 if (!ReadProcessMemory( process
, &peb32
->LdrData
, &ldr_data32
, sizeof(ldr_data32
), NULL
))
795 ldr_data32_ptr
= (PEB_LDR_DATA32
*)(DWORD_PTR
) ldr_data32
;
796 if (!ReadProcessMemory( process
, &ldr_data32_ptr
->InLoadOrderModuleList
.Flink
,
797 &first_module
, sizeof(first_module
), NULL
))
799 iter
->head
= (LIST_ENTRY
*)&ldr_data32_ptr
->InLoadOrderModuleList
;
800 iter
->current
= (LIST_ENTRY
*)(DWORD_PTR
)first_module
;
801 iter
->process
= process
;
805 /* read address of LdrData from PEB */
806 if (!ReadProcessMemory( process
, &pbi
.PebBaseAddress
->LdrData
, &ldr_data
, sizeof(ldr_data
), NULL
))
809 /* This happens when running "old" wow64 configuration. Mark it as such. */
812 SetLastError( ERROR_EMPTY
);
815 /* read address of first module from LdrData */
816 if (!ReadProcessMemory( process
, &ldr_data
->InLoadOrderModuleList
.Flink
,
817 &iter
->current
, sizeof(iter
->current
), NULL
))
820 iter
->head
= &ldr_data
->InLoadOrderModuleList
;
821 iter
->process
= process
;
826 static int module_iterator_next( struct module_iterator
*iter
)
828 if (iter
->current
== iter
->head
) return 0;
830 if (is_win64
&& iter
->wow64
)
832 LIST_ENTRY32
*entry32
= (LIST_ENTRY32
*)iter
->current
;
834 if (!ReadProcessMemory( iter
->process
,
835 CONTAINING_RECORD(entry32
, LDR_DATA_TABLE_ENTRY32
, InLoadOrderModuleList
),
836 &iter
->ldr_module32
, sizeof(iter
->ldr_module32
), NULL
))
838 iter
->current
= (LIST_ENTRY
*)(DWORD_PTR
)iter
->ldr_module32
.InLoadOrderModuleList
.Flink
;
842 if (!ReadProcessMemory( iter
->process
,
843 CONTAINING_RECORD(iter
->current
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
),
844 &iter
->ldr_module
, sizeof(iter
->ldr_module
), NULL
))
847 iter
->current
= iter
->ldr_module
.InLoadOrderLinks
.Flink
;
852 static BOOL
get_ldr_module( HANDLE process
, HMODULE module
, LDR_DATA_TABLE_ENTRY
*ldr_module
)
854 struct module_iterator iter
;
857 if (!init_module_iterator( &iter
, process
, FALSE
)) return FALSE
;
859 while ((ret
= module_iterator_next( &iter
)) > 0)
860 /* When hModule is NULL we return the process image - which will be
861 * the first module since our iterator uses InLoadOrderModuleList */
862 if (!module
|| module
== iter
.ldr_module
.DllBase
)
864 *ldr_module
= iter
.ldr_module
;
868 if (ret
== 0) SetLastError( ERROR_INVALID_HANDLE
);
873 static BOOL
get_ldr_module32( HANDLE process
, HMODULE module
, LDR_DATA_TABLE_ENTRY32
*ldr_module
)
875 struct module_iterator iter
;
879 if ((ULONG_PTR
)module
>> 32)
881 SetLastError( ERROR_INVALID_HANDLE
);
885 if (!init_module_iterator( &iter
, process
, TRUE
)) return FALSE
;
887 while ((ret
= module_iterator_next( &iter
)) > 0)
888 /* When hModule is NULL we return the process image - which will be
889 * the first module since our iterator uses InLoadOrderModuleList */
890 if (!module
|| (DWORD
)(DWORD_PTR
)module
== iter
.ldr_module32
.BaseAddress
)
892 *ldr_module
= iter
.ldr_module32
;
896 if (ret
== 0) SetLastError( ERROR_INVALID_HANDLE
);
901 /***********************************************************************
902 * EmptyWorkingSet (kernelbase.@)
903 * K32EmptyWorkingSet (kernelbase.@)
905 BOOL WINAPI DECLSPEC_HOTPATCH
EmptyWorkingSet( HANDLE process
)
907 return SetProcessWorkingSetSizeEx( process
, (SIZE_T
)-1, (SIZE_T
)-1, 0 );
911 /***********************************************************************
912 * EnumDeviceDrivers (kernelbase.@)
913 * K32EnumDeviceDrivers (kernelbase.@)
915 BOOL WINAPI
EnumDeviceDrivers( void **image_base
, DWORD count
, DWORD
*needed
)
917 FIXME( "(%p, %ld, %p): stub\n", image_base
, count
, needed
);
918 if (needed
) *needed
= 0;
923 /***********************************************************************
924 * EnumPageFilesA (kernelbase.@)
925 * K32EnumPageFilesA (kernelbase.@)
927 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ EnumPageFilesA( PENUM_PAGE_FILE_CALLBACKA callback
, void *context
)
929 FIXME( "(%p, %p) stub\n", callback
, context
);
934 /***********************************************************************
935 * EnumPageFilesW (kernelbase.@)
936 * K32EnumPageFilesW (kernelbase.@)
938 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ EnumPageFilesW( PENUM_PAGE_FILE_CALLBACKW callback
, void *context
)
940 FIXME( "(%p, %p) stub\n", callback
, context
);
945 /***********************************************************************
946 * EnumProcessModules (kernelbase.@)
947 * K32EnumProcessModules (kernelbase.@)
949 BOOL WINAPI DECLSPEC_HOTPATCH
EnumProcessModules( HANDLE process
, HMODULE
*module
,
950 DWORD count
, DWORD
*needed
)
952 return EnumProcessModulesEx( process
, module
, count
, needed
, LIST_MODULES_DEFAULT
);
963 static void module_push( struct module_push
*mp
, HMODULE module
)
965 if (mp
->count
>= sizeof(HMODULE
))
967 *mp
->module
++ = module
;
968 mp
->count
-= sizeof(HMODULE
);
970 mp
->size
+= sizeof(HMODULE
);
973 static void module_push_iter( struct module_push
*mp
, struct module_iterator
*iter
)
975 if (is_win64
&& iter
->wow64
)
976 module_push( mp
, (HMODULE
) (DWORD_PTR
)iter
->ldr_module32
.BaseAddress
);
978 module_push( mp
, iter
->ldr_module
.DllBase
);
981 static int module_push_all( struct module_push
*mp
, struct module_iterator
*iter
)
985 while ((ret
= module_iterator_next( iter
)) > 0)
986 module_push_iter( mp
, iter
);
991 /***********************************************************************
992 * EnumProcessModulesEx (kernelbase.@)
993 * K32EnumProcessModulesEx (kernelbase.@)
995 BOOL WINAPI
EnumProcessModulesEx( HANDLE process
, HMODULE
*module
, DWORD count
,
996 DWORD
*needed
, DWORD filter
)
998 struct module_push mp
= {module
, count
, 0};
1003 TRACE( "(%p, %p, %ld, %p, %ld)\n", process
, module
, count
, needed
, filter
);
1005 if (process
!= GetCurrentProcess())
1007 if (!IsWow64Process( process
, &target_wow64
)) return FALSE
;
1009 else target_wow64
= is_wow64
;
1011 if (filter
& ~LIST_MODULES_ALL
)
1013 SetLastError( ERROR_INVALID_PARAMETER
);
1016 list_mode
= filter
& LIST_MODULES_ALL
;
1017 /* Can't access 64bit process from (wow64) 32bit */
1018 if (is_wow64
&& !target_wow64
)
1020 SetLastError( ERROR_PARTIAL_COPY
);
1023 if (count
&& !module
)
1025 SetLastError( ERROR_NOACCESS
);
1029 if (process
== GetCurrentProcess())
1031 if (!(is_win64
&& list_mode
== LIST_MODULES_32BIT
))
1033 PPEB_LDR_DATA ldr_data
= NtCurrentTeb()->Peb
->LdrData
;
1034 PLIST_ENTRY head
= &ldr_data
->InLoadOrderModuleList
;
1035 PLIST_ENTRY entry
= head
->Flink
;
1037 while (entry
!= head
)
1039 LDR_DATA_TABLE_ENTRY
*ldr
= CONTAINING_RECORD( entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
1040 module_push( &mp
, ldr
->DllBase
);
1041 entry
= entry
->Flink
;
1047 struct module_iterator iter
;
1049 if (is_win64
&& target_wow64
&& (list_mode
& LIST_MODULES_32BIT
))
1051 if (!init_module_iterator( &iter
, process
, TRUE
) || module_push_all( &mp
, &iter
) < 0)
1054 if (!(is_win64
&& list_mode
== LIST_MODULES_32BIT
))
1056 if (init_module_iterator( &iter
, process
, FALSE
))
1058 if (is_win64
&& target_wow64
&& (list_mode
& LIST_MODULES_64BIT
))
1059 /* Don't add main module twice in _ALL mode */
1060 ret
= module_iterator_next( &iter
);
1061 if (ret
>= 0) ret
= module_push_all( &mp
, &iter
);
1063 else if (GetLastError() == ERROR_EMPTY
)
1065 /* We're running on "old" wow configuration.
1066 * Fallback to PEB32 to get at least main module if requested.
1068 if (list_mode
== LIST_MODULES_DEFAULT
)
1070 if (init_module_iterator( &iter
, process
, TRUE
) && module_iterator_next( &iter
) > 0)
1071 module_push_iter( &mp
, &iter
);
1083 SetLastError( ERROR_NOACCESS
);
1091 /***********************************************************************
1092 * EnumProcesses (kernelbase.@)
1093 * K32EnumProcesses (kernelbase.@)
1095 BOOL WINAPI
EnumProcesses( DWORD
*ids
, DWORD count
, DWORD
*used
)
1097 SYSTEM_PROCESS_INFORMATION
*spi
;
1098 ULONG size
= 0x4000;
1105 HeapFree( GetProcessHeap(), 0, buf
);
1106 if (!(buf
= HeapAlloc( GetProcessHeap(), 0, size
))) return FALSE
;
1107 status
= NtQuerySystemInformation( SystemProcessInformation
, buf
, size
, NULL
);
1108 } while (status
== STATUS_INFO_LENGTH_MISMATCH
);
1110 if (!set_ntstatus( status
))
1112 HeapFree( GetProcessHeap(), 0, buf
);
1116 for (*used
= 0; count
>= sizeof(DWORD
); count
-= sizeof(DWORD
))
1118 *ids
++ = HandleToUlong( spi
->UniqueProcessId
);
1119 *used
+= sizeof(DWORD
);
1120 if (spi
->NextEntryOffset
== 0) break;
1121 spi
= (SYSTEM_PROCESS_INFORMATION
*)(((PCHAR
)spi
) + spi
->NextEntryOffset
);
1123 HeapFree( GetProcessHeap(), 0, buf
);
1128 /***********************************************************************
1129 * GetDeviceDriverBaseNameA (kernelbase.@)
1130 * K32GetDeviceDriverBaseNameA (kernelbase.@)
1132 DWORD WINAPI DECLSPEC_HOTPATCH
GetDeviceDriverBaseNameA( void *image_base
, char *name
, DWORD size
)
1134 FIXME( "(%p, %p, %ld): stub\n", image_base
, name
, size
);
1135 if (name
&& size
) name
[0] = 0;
1140 /***********************************************************************
1141 * GetDeviceDriverBaseNameW (kernelbase.@)
1142 * K32GetDeviceDriverBaseNameW (kernelbase.@)
1144 DWORD WINAPI DECLSPEC_HOTPATCH
GetDeviceDriverBaseNameW( void *image_base
, WCHAR
*name
, DWORD size
)
1146 FIXME( "(%p, %p, %ld): stub\n", image_base
, name
, size
);
1147 if (name
&& size
) name
[0] = 0;
1152 /***********************************************************************
1153 * GetDeviceDriverFileNameA (kernelbase.@)
1154 * K32GetDeviceDriverFileNameA (kernelbase.@)
1156 DWORD WINAPI DECLSPEC_HOTPATCH
GetDeviceDriverFileNameA( void *image_base
, char *name
, DWORD size
)
1158 FIXME( "(%p, %p, %ld): stub\n", image_base
, name
, size
);
1159 if (name
&& size
) name
[0] = 0;
1164 /***********************************************************************
1165 * GetDeviceDriverFileNameW (kernelbase.@)
1166 * K32GetDeviceDriverFileNameW (kernelbase.@)
1168 DWORD WINAPI DECLSPEC_HOTPATCH
GetDeviceDriverFileNameW( void *image_base
, WCHAR
*name
, DWORD size
)
1170 FIXME( "(%p, %p, %ld): stub\n", image_base
, name
, size
);
1171 if (name
&& size
) name
[0] = 0;
1176 /***********************************************************************
1177 * GetMappedFileNameA (kernelbase.@)
1178 * K32GetMappedFileNameA (kernelbase.@)
1180 DWORD WINAPI DECLSPEC_HOTPATCH
GetMappedFileNameA( HANDLE process
, void *addr
, char *name
, DWORD size
)
1182 WCHAR nameW
[MAX_PATH
];
1187 SetLastError( ERROR_INVALID_PARAMETER
);
1190 if (!GetMappedFileNameW( process
, addr
, nameW
, MAX_PATH
)) return 0;
1193 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1196 len
= file_name_WtoA( nameW
, wcslen(nameW
), name
, size
);
1197 name
[min(len
, size
- 1)] = 0;
1202 /***********************************************************************
1203 * GetMappedFileNameW (kernelbase.@)
1204 * K32GetMappedFileNameW (kernelbase.@)
1206 DWORD WINAPI DECLSPEC_HOTPATCH
GetMappedFileNameW( HANDLE process
, void *addr
, WCHAR
*name
, DWORD size
)
1208 ULONG_PTR buffer
[(sizeof(MEMORY_SECTION_NAME
) + MAX_PATH
* sizeof(WCHAR
)) / sizeof(ULONG_PTR
)];
1209 MEMORY_SECTION_NAME
*mem
= (MEMORY_SECTION_NAME
*)buffer
;
1214 SetLastError( ERROR_INVALID_PARAMETER
);
1217 if (!set_ntstatus( NtQueryVirtualMemory( process
, addr
, MemoryMappedFilenameInformation
,
1218 mem
, sizeof(buffer
), NULL
)))
1221 len
= mem
->SectionFileName
.Length
/ sizeof(WCHAR
);
1222 memcpy( name
, mem
->SectionFileName
.Buffer
, min( mem
->SectionFileName
.Length
, size
* sizeof(WCHAR
) ));
1223 if (len
>= size
) SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1224 name
[min(len
, size
- 1)] = 0;
1229 /***********************************************************************
1230 * GetModuleBaseNameA (kernelbase.@)
1231 * K32GetModuleBaseNameA (kernelbase.@)
1233 DWORD WINAPI DECLSPEC_HOTPATCH
GetModuleBaseNameA( HANDLE process
, HMODULE module
,
1234 char *name
, DWORD size
)
1241 SetLastError( ERROR_INVALID_PARAMETER
);
1244 if (!(name_w
= HeapAlloc( GetProcessHeap(), 0, sizeof(WCHAR
) * size
))) return 0;
1246 len
= GetModuleBaseNameW( process
, module
, name_w
, size
);
1247 TRACE( "%ld, %s\n", len
, debugstr_w(name_w
) );
1250 ret
= WideCharToMultiByte( CP_ACP
, 0, name_w
, len
, name
, size
, NULL
, NULL
);
1251 if (ret
< size
) name
[ret
] = 0;
1253 HeapFree( GetProcessHeap(), 0, name_w
);
1258 /***********************************************************************
1259 * GetModuleBaseNameW (kernelbase.@)
1260 * K32GetModuleBaseNameW (kernelbase.@)
1262 DWORD WINAPI DECLSPEC_HOTPATCH
GetModuleBaseNameW( HANDLE process
, HMODULE module
,
1263 WCHAR
*name
, DWORD size
)
1265 BOOL wow64
, found
= FALSE
;
1267 if (!IsWow64Process( process
, &wow64
)) return 0;
1269 if (is_win64
&& wow64
)
1271 LDR_DATA_TABLE_ENTRY32 ldr_module32
;
1273 if (get_ldr_module32(process
, module
, &ldr_module32
))
1275 size
= min( ldr_module32
.BaseDllName
.Length
/ sizeof(WCHAR
), size
);
1276 if (ReadProcessMemory( process
, (void *)(DWORD_PTR
)ldr_module32
.BaseDllName
.Buffer
,
1277 name
, size
* sizeof(WCHAR
), NULL
))
1283 LDR_DATA_TABLE_ENTRY ldr_module
;
1285 if (!get_ldr_module( process
, module
, &ldr_module
)) return 0;
1286 size
= min( ldr_module
.BaseDllName
.Length
/ sizeof(WCHAR
), size
);
1287 if (!ReadProcessMemory( process
, ldr_module
.BaseDllName
.Buffer
,
1288 name
, size
* sizeof(WCHAR
), NULL
))
1296 /***********************************************************************
1297 * GetModuleFileNameExA (kernelbase.@)
1298 * K32GetModuleFileNameExA (kernelbase.@)
1300 DWORD WINAPI DECLSPEC_HOTPATCH
GetModuleFileNameExA( HANDLE process
, HMODULE module
,
1301 char *name
, DWORD size
)
1306 TRACE( "(process=%p, module=%p, %p, %ld)\n", process
, module
, name
, size
);
1310 SetLastError( ERROR_INVALID_PARAMETER
);
1313 if (process
== GetCurrentProcess())
1315 len
= GetModuleFileNameA( module
, name
, size
);
1316 name
[size
- 1] = '\0';
1320 if (!(ptr
= HeapAlloc( GetProcessHeap(), 0, size
* sizeof(WCHAR
) ))) return 0;
1321 len
= GetModuleFileNameExW( process
, module
, ptr
, size
);
1328 if (!WideCharToMultiByte( CP_ACP
, 0, ptr
, -1, name
, size
, NULL
, NULL
))
1333 else if (len
< size
) len
= strlen( name
);
1335 HeapFree( GetProcessHeap(), 0, ptr
);
1340 /***********************************************************************
1341 * GetModuleFileNameExW (kernelbase.@)
1342 * K32GetModuleFileNameExW (kernelbase.@)
1344 DWORD WINAPI DECLSPEC_HOTPATCH
GetModuleFileNameExW( HANDLE process
, HMODULE module
,
1345 WCHAR
*name
, DWORD size
)
1347 BOOL wow64
, found
= FALSE
;
1350 if (!size
) return 0;
1352 if (!IsWow64Process( process
, &wow64
)) return 0;
1354 if (is_win64
&& wow64
)
1356 LDR_DATA_TABLE_ENTRY32 ldr_module32
;
1358 if (get_ldr_module32( process
, module
, &ldr_module32
))
1360 len
= ldr_module32
.FullDllName
.Length
/ sizeof(WCHAR
);
1361 if (ReadProcessMemory( process
, (void *)(DWORD_PTR
)ldr_module32
.FullDllName
.Buffer
,
1362 name
, min( len
, size
) * sizeof(WCHAR
), NULL
))
1368 LDR_DATA_TABLE_ENTRY ldr_module
;
1370 if (!get_ldr_module(process
, module
, &ldr_module
)) return 0;
1371 len
= ldr_module
.FullDllName
.Length
/ sizeof(WCHAR
);
1372 if (!ReadProcessMemory( process
, ldr_module
.FullDllName
.Buffer
,
1373 name
, min( len
, size
) * sizeof(WCHAR
), NULL
))
1390 /***********************************************************************
1391 * GetModuleInformation (kernelbase.@)
1392 * K32GetModuleInformation (kernelbase.@)
1394 BOOL WINAPI
GetModuleInformation( HANDLE process
, HMODULE module
, MODULEINFO
*modinfo
, DWORD count
)
1396 BOOL wow64
, found
= FALSE
;
1398 if (count
< sizeof(MODULEINFO
))
1400 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1404 if (!IsWow64Process( process
, &wow64
)) return FALSE
;
1406 if (is_win64
&& wow64
)
1408 LDR_DATA_TABLE_ENTRY32 ldr_module32
;
1410 if (get_ldr_module32( process
, module
, &ldr_module32
))
1412 modinfo
->lpBaseOfDll
= (void *)(DWORD_PTR
)ldr_module32
.BaseAddress
;
1413 modinfo
->SizeOfImage
= ldr_module32
.SizeOfImage
;
1414 modinfo
->EntryPoint
= (void *)(DWORD_PTR
)ldr_module32
.EntryPoint
;
1420 LDR_DATA_TABLE_ENTRY ldr_module
;
1422 if (!get_ldr_module( process
, module
, &ldr_module
)) return FALSE
;
1423 modinfo
->lpBaseOfDll
= ldr_module
.DllBase
;
1424 modinfo
->SizeOfImage
= ldr_module
.SizeOfImage
;
1425 modinfo
->EntryPoint
= ldr_module
.EntryPoint
;
1431 /***********************************************************************
1432 * GetPerformanceInfo (kernelbase.@)
1433 * K32GetPerformanceInfo (kernelbase.@)
1435 BOOL WINAPI DECLSPEC_HOTPATCH
GetPerformanceInfo( PPERFORMANCE_INFORMATION info
, DWORD size
)
1437 SYSTEM_PERFORMANCE_INFORMATION perf
;
1438 SYSTEM_BASIC_INFORMATION basic
;
1439 SYSTEM_PROCESS_INFORMATION
*process
, *spi
;
1443 TRACE( "(%p, %ld)\n", info
, size
);
1445 if (size
< sizeof(*info
))
1447 SetLastError( ERROR_BAD_LENGTH
);
1451 status
= NtQuerySystemInformation( SystemPerformanceInformation
, &perf
, sizeof(perf
), NULL
);
1452 if (!set_ntstatus( status
)) return FALSE
;
1453 status
= NtQuerySystemInformation( SystemBasicInformation
, &basic
, sizeof(basic
), NULL
);
1454 if (!set_ntstatus( status
)) return FALSE
;
1456 info
->cb
= sizeof(*info
);
1457 info
->CommitTotal
= perf
.TotalCommittedPages
;
1458 info
->CommitLimit
= perf
.TotalCommitLimit
;
1459 info
->CommitPeak
= perf
.PeakCommitment
;
1460 info
->PhysicalTotal
= basic
.MmNumberOfPhysicalPages
;
1461 info
->PhysicalAvailable
= perf
.AvailablePages
;
1462 info
->SystemCache
= 0;
1463 info
->KernelTotal
= perf
.PagedPoolUsage
+ perf
.NonPagedPoolUsage
;
1464 info
->KernelPaged
= perf
.PagedPoolUsage
;
1465 info
->KernelNonpaged
= perf
.NonPagedPoolUsage
;
1466 info
->PageSize
= basic
.PageSize
;
1468 /* fields from SYSTEM_PROCESS_INFORMATION */
1469 NtQuerySystemInformation( SystemProcessInformation
, NULL
, 0, &info_size
);
1472 process
= HeapAlloc( GetProcessHeap(), 0, info_size
);
1475 SetLastError( ERROR_OUTOFMEMORY
);
1478 status
= NtQuerySystemInformation( SystemProcessInformation
, process
, info_size
, &info_size
);
1480 HeapFree( GetProcessHeap(), 0, process
);
1481 if (status
!= STATUS_INFO_LENGTH_MISMATCH
)
1483 SetLastError( RtlNtStatusToDosError( status
) );
1487 info
->HandleCount
= info
->ProcessCount
= info
->ThreadCount
= 0;
1491 info
->ProcessCount
++;
1492 info
->HandleCount
+= spi
->HandleCount
;
1493 info
->ThreadCount
+= spi
->dwThreadCount
;
1494 if (spi
->NextEntryOffset
== 0) break;
1495 spi
= (SYSTEM_PROCESS_INFORMATION
*)((char *)spi
+ spi
->NextEntryOffset
);
1497 HeapFree( GetProcessHeap(), 0, process
);
1502 /***********************************************************************
1503 * GetProcessImageFileNameA (kernelbase.@)
1504 * K32GetProcessImageFileNameA (kernelbase.@)
1506 DWORD WINAPI DECLSPEC_HOTPATCH
GetProcessImageFileNameA( HANDLE process
, char *file
, DWORD size
)
1508 return QueryFullProcessImageNameA( process
, PROCESS_NAME_NATIVE
, file
, &size
) ? size
: 0;
1512 /***********************************************************************
1513 * GetProcessImageFileNameW (kernelbase.@)
1514 * K32GetProcessImageFileNameW (kernelbase.@)
1516 DWORD WINAPI DECLSPEC_HOTPATCH
GetProcessImageFileNameW( HANDLE process
, WCHAR
*file
, DWORD size
)
1518 return QueryFullProcessImageNameW( process
, PROCESS_NAME_NATIVE
, file
, &size
) ? size
: 0;
1522 /***********************************************************************
1523 * GetProcessMemoryInfo (kernelbase.@)
1524 * K32GetProcessMemoryInfo (kernelbase.@)
1526 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessMemoryInfo( HANDLE process
, PROCESS_MEMORY_COUNTERS
*pmc
,
1531 if (count
< sizeof(PROCESS_MEMORY_COUNTERS
))
1533 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1537 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessVmCounters
, &vmc
, sizeof(vmc
), NULL
)))
1540 pmc
->cb
= sizeof(PROCESS_MEMORY_COUNTERS
);
1541 pmc
->PageFaultCount
= vmc
.PageFaultCount
;
1542 pmc
->PeakWorkingSetSize
= vmc
.PeakWorkingSetSize
;
1543 pmc
->WorkingSetSize
= vmc
.WorkingSetSize
;
1544 pmc
->QuotaPeakPagedPoolUsage
= vmc
.QuotaPeakPagedPoolUsage
;
1545 pmc
->QuotaPagedPoolUsage
= vmc
.QuotaPagedPoolUsage
;
1546 pmc
->QuotaPeakNonPagedPoolUsage
= vmc
.QuotaPeakNonPagedPoolUsage
;
1547 pmc
->QuotaNonPagedPoolUsage
= vmc
.QuotaNonPagedPoolUsage
;
1548 pmc
->PagefileUsage
= vmc
.PagefileUsage
;
1549 pmc
->PeakPagefileUsage
= vmc
.PeakPagefileUsage
;
1554 /***********************************************************************
1555 * GetWsChanges (kernelbase.@)
1556 * K32GetWsChanges (kernelbase.@)
1558 BOOL WINAPI DECLSPEC_HOTPATCH
GetWsChanges( HANDLE process
, PSAPI_WS_WATCH_INFORMATION
*info
, DWORD size
)
1560 TRACE( "(%p, %p, %ld)\n", process
, info
, size
);
1561 return set_ntstatus( NtQueryInformationProcess( process
, ProcessWorkingSetWatch
, info
, size
, NULL
));
1565 /***********************************************************************
1566 * GetWsChangesEx (kernelbase.@)
1567 * K32GetWsChangesEx (kernelbase.@)
1569 BOOL WINAPI DECLSPEC_HOTPATCH
GetWsChangesEx( HANDLE process
, PSAPI_WS_WATCH_INFORMATION_EX
*info
,
1572 FIXME( "(%p, %p, %p)\n", process
, info
, size
);
1573 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1578 /***********************************************************************
1579 * InitializeProcessForWsWatch (kernelbase.@)
1580 * K32InitializeProcessForWsWatch (kernelbase.@)
1582 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ InitializeProcessForWsWatch( HANDLE process
)
1584 FIXME( "(process=%p): stub\n", process
);
1589 /***********************************************************************
1590 * QueryWorkingSet (kernelbase.@)
1591 * K32QueryWorkingSet (kernelbase.@)
1593 BOOL WINAPI DECLSPEC_HOTPATCH
QueryWorkingSet( HANDLE process
, void *buffer
, DWORD size
)
1595 TRACE( "(%p, %p, %ld)\n", process
, buffer
, size
);
1596 return set_ntstatus( NtQueryVirtualMemory( process
, NULL
, MemoryWorkingSetInformation
,
1597 buffer
, size
, NULL
));
1601 /***********************************************************************
1602 * QueryWorkingSetEx (kernelbase.@)
1603 * K32QueryWorkingSetEx (kernelbase.@)
1605 BOOL WINAPI
QueryWorkingSetEx( HANDLE process
, void *buffer
, DWORD size
)
1607 TRACE( "(%p, %p, %ld)\n", process
, buffer
, size
);
1608 return set_ntstatus( NtQueryVirtualMemory( process
, NULL
, MemoryWorkingSetExInformation
,
1609 buffer
, size
, NULL
));
1613 /******************************************************************
1614 * QueryFullProcessImageNameA (kernelbase.@)
1616 BOOL WINAPI DECLSPEC_HOTPATCH
QueryFullProcessImageNameA( HANDLE process
, DWORD flags
,
1617 char *name
, DWORD
*size
)
1620 DWORD sizeW
= *size
;
1621 WCHAR
*nameW
= HeapAlloc( GetProcessHeap(), 0, *size
* sizeof(WCHAR
) );
1623 ret
= QueryFullProcessImageNameW( process
, flags
, nameW
, &sizeW
);
1624 if (ret
) ret
= (WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, name
, *size
, NULL
, NULL
) > 0);
1625 if (ret
) *size
= strlen( name
);
1626 HeapFree( GetProcessHeap(), 0, nameW
);
1631 /******************************************************************
1632 * QueryFullProcessImageNameW (kernelbase.@)
1634 BOOL WINAPI DECLSPEC_HOTPATCH
QueryFullProcessImageNameW( HANDLE process
, DWORD flags
,
1635 WCHAR
*name
, DWORD
*size
)
1637 BYTE buffer
[sizeof(UNICODE_STRING
) + MAX_PATH
*sizeof(WCHAR
)]; /* this buffer should be enough */
1638 UNICODE_STRING
*dynamic_buffer
= NULL
;
1639 UNICODE_STRING
*result
= NULL
;
1643 /* FIXME: Use ProcessImageFileName for the PROCESS_NAME_NATIVE case */
1644 status
= NtQueryInformationProcess( process
, ProcessImageFileNameWin32
, buffer
,
1645 sizeof(buffer
) - sizeof(WCHAR
), &needed
);
1646 if (status
== STATUS_INFO_LENGTH_MISMATCH
)
1648 dynamic_buffer
= HeapAlloc( GetProcessHeap(), 0, needed
+ sizeof(WCHAR
) );
1649 status
= NtQueryInformationProcess( process
, ProcessImageFileNameWin32
, dynamic_buffer
,
1651 result
= dynamic_buffer
;
1654 result
= (UNICODE_STRING
*)buffer
;
1656 if (status
) goto cleanup
;
1658 if (flags
& PROCESS_NAME_NATIVE
&& result
->Length
> 2 * sizeof(WCHAR
))
1662 DWORD ntlen
, devlen
;
1664 if (result
->Buffer
[1] != ':' || result
->Buffer
[0] < 'A' || result
->Buffer
[0] > 'Z')
1666 /* We cannot convert it to an NT device path so fail */
1667 status
= STATUS_NO_SUCH_DEVICE
;
1671 /* Find this drive's NT device path */
1672 drive
[0] = result
->Buffer
[0];
1675 if (!QueryDosDeviceW(drive
, device
, ARRAY_SIZE(device
)))
1677 status
= STATUS_NO_SUCH_DEVICE
;
1681 devlen
= lstrlenW(device
);
1682 ntlen
= devlen
+ (result
->Length
/sizeof(WCHAR
) - 2);
1683 if (ntlen
+ 1 > *size
)
1685 status
= STATUS_BUFFER_TOO_SMALL
;
1690 memcpy( name
, device
, devlen
* sizeof(*device
) );
1691 memcpy( name
+ devlen
, result
->Buffer
+ 2, result
->Length
- 2 * sizeof(WCHAR
) );
1693 TRACE( "NT path: %s\n", debugstr_w(name
) );
1697 if (result
->Length
/sizeof(WCHAR
) + 1 > *size
)
1699 status
= STATUS_BUFFER_TOO_SMALL
;
1703 *size
= result
->Length
/sizeof(WCHAR
);
1704 memcpy( name
, result
->Buffer
, result
->Length
);
1709 HeapFree( GetProcessHeap(), 0, dynamic_buffer
);
1710 return set_ntstatus( status
);