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
36 #include "wine/exception.h"
38 #include "kernelbase.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(seh
);
42 WINE_DECLARE_DEBUG_CHANNEL(winedbg
);
44 typedef INT (WINAPI
*MessageBoxA_funcptr
)(HWND
,LPCSTR
,LPCSTR
,UINT
);
45 typedef INT (WINAPI
*MessageBoxW_funcptr
)(HWND
,LPCWSTR
,LPCWSTR
,UINT
);
47 static PTOP_LEVEL_EXCEPTION_FILTER top_filter
;
49 void *dummy
= RtlUnwind
; /* force importing RtlUnwind from ntdll */
51 /***********************************************************************
52 * CheckRemoteDebuggerPresent (kernelbase.@)
54 BOOL WINAPI DECLSPEC_HOTPATCH
CheckRemoteDebuggerPresent( HANDLE process
, BOOL
*present
)
58 if (!process
|| !present
)
60 SetLastError( ERROR_INVALID_PARAMETER
);
63 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessDebugPort
, &port
, sizeof(port
), NULL
)))
70 /**********************************************************************
71 * ContinueDebugEvent (kernelbase.@)
73 BOOL WINAPI DECLSPEC_HOTPATCH
ContinueDebugEvent( DWORD pid
, DWORD tid
, DWORD status
)
77 id
.UniqueProcess
= ULongToHandle( pid
);
78 id
.UniqueThread
= ULongToHandle( tid
);
79 return set_ntstatus( DbgUiContinue( &id
, status
));
83 /**********************************************************************
84 * DebugActiveProcess (kernelbase.@)
86 BOOL WINAPI DECLSPEC_HOTPATCH
DebugActiveProcess( DWORD pid
)
91 if (!set_ntstatus( DbgUiConnectToDbg() )) return FALSE
;
92 if (!(process
= OpenProcess( PROCESS_VM_READ
| PROCESS_VM_WRITE
| PROCESS_SUSPEND_RESUME
|
93 PROCESS_CREATE_THREAD
, FALSE
, pid
)))
95 status
= DbgUiDebugActiveProcess( process
);
97 return set_ntstatus( status
);
101 /**********************************************************************
102 * DebugActiveProcessStop (kernelbase.@)
104 BOOL WINAPI DECLSPEC_HOTPATCH
DebugActiveProcessStop( DWORD pid
)
109 if (!(process
= OpenProcess( PROCESS_VM_READ
| PROCESS_VM_WRITE
| PROCESS_SUSPEND_RESUME
, FALSE
, pid
)))
111 status
= DbgUiStopDebugging( process
);
113 return set_ntstatus( status
);
117 /***********************************************************************
118 * DebugBreak (kernelbase.@)
120 #if defined(__i386__) || defined(__x86_64__)
121 __ASM_STDCALL_FUNC( DebugBreak
, 0, "jmp " __ASM_STDCALL("DbgBreakPoint", 0) )
123 void WINAPI
DebugBreak(void)
130 /**************************************************************************
131 * FatalAppExitA (kernelbase.@)
133 void WINAPI DECLSPEC_HOTPATCH
FatalAppExitA( UINT action
, LPCSTR str
)
135 HMODULE mod
= GetModuleHandleA( "user32.dll" );
136 MessageBoxA_funcptr pMessageBoxA
= NULL
;
138 if (mod
) pMessageBoxA
= (MessageBoxA_funcptr
)GetProcAddress( mod
, "MessageBoxA" );
139 if (pMessageBoxA
) pMessageBoxA( 0, str
, NULL
, MB_SYSTEMMODAL
| MB_OK
);
140 else ERR( "%s\n", debugstr_a(str
) );
141 RtlExitUserProcess( 1 );
145 /**************************************************************************
146 * FatalAppExitW (kernelbase.@)
148 void WINAPI DECLSPEC_HOTPATCH
FatalAppExitW( UINT action
, LPCWSTR str
)
150 HMODULE mod
= GetModuleHandleW( L
"user32.dll" );
151 MessageBoxW_funcptr pMessageBoxW
= NULL
;
153 if (mod
) pMessageBoxW
= (MessageBoxW_funcptr
)GetProcAddress( mod
, "MessageBoxW" );
154 if (pMessageBoxW
) pMessageBoxW( 0, str
, NULL
, MB_SYSTEMMODAL
| MB_OK
);
155 else ERR( "%s\n", debugstr_w(str
) );
156 RtlExitUserProcess( 1 );
160 /***********************************************************************
161 * IsDebuggerPresent (kernelbase.@)
163 BOOL WINAPI
IsDebuggerPresent(void)
165 return NtCurrentTeb()->Peb
->BeingDebugged
;
169 static LONG WINAPI
debug_exception_handler( EXCEPTION_POINTERS
*eptr
)
171 EXCEPTION_RECORD
*rec
= eptr
->ExceptionRecord
;
172 return (rec
->ExceptionCode
== DBG_PRINTEXCEPTION_C
) ? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH
;
175 /***********************************************************************
176 * OutputDebugStringA (kernelbase.@)
178 void WINAPI DECLSPEC_HOTPATCH
OutputDebugStringA( LPCSTR str
)
180 static HANDLE DBWinMutex
= NULL
;
181 static BOOL mutex_inited
= FALSE
;
182 BOOL caught_by_dbg
= TRUE
;
185 WARN( "%s\n", debugstr_a(str
) );
187 /* raise exception, WaitForDebugEvent() will generate a corresponding debug event */
191 args
[0] = strlen(str
) + 1;
192 args
[1] = (ULONG_PTR
)str
;
193 RaiseException( DBG_PRINTEXCEPTION_C
, 0, 2, args
);
195 __EXCEPT(debug_exception_handler
)
197 caught_by_dbg
= FALSE
;
200 if (caught_by_dbg
) return;
202 /* send string to a system-wide monitor */
205 /* first call to OutputDebugString, initialize mutex handle */
206 HANDLE mutex
= CreateMutexExW( NULL
, L
"DBWinMutex", 0, SYNCHRONIZE
);
209 if (InterlockedCompareExchangePointer( &DBWinMutex
, mutex
, 0 ) != 0)
210 /* someone beat us here... */
211 CloseHandle( mutex
);
220 mapping
= OpenFileMappingW( FILE_MAP_WRITE
, FALSE
, L
"DBWIN_BUFFER" );
224 HANDLE eventbuffer
, eventdata
;
226 buffer
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 0 );
227 eventbuffer
= OpenEventW( SYNCHRONIZE
, FALSE
, L
"DBWIN_BUFFER_READY" );
228 eventdata
= OpenEventW( EVENT_MODIFY_STATE
, FALSE
, L
"DBWIN_DATA_READY" );
230 if (buffer
&& eventbuffer
&& eventdata
)
232 /* monitor is present, synchronize with other OutputDebugString invocations */
233 WaitForSingleObject( DBWinMutex
, INFINITE
);
235 /* acquire control over the buffer */
236 if (WaitForSingleObject( eventbuffer
, 10000 ) == WAIT_OBJECT_0
)
238 int str_len
= strlen( str
);
243 } *mon_buffer
= (struct _mon_buffer_t
*) buffer
;
245 if (str_len
> (4096 - sizeof(DWORD
) - 1)) str_len
= 4096 - sizeof(DWORD
) - 1;
246 mon_buffer
->pid
= GetCurrentProcessId();
247 memcpy( mon_buffer
->buffer
, str
, str_len
);
248 mon_buffer
->buffer
[str_len
] = 0;
250 /* signal data ready */
251 SetEvent( eventdata
);
253 ReleaseMutex( DBWinMutex
);
256 if (buffer
) UnmapViewOfFile( buffer
);
257 if (eventbuffer
) CloseHandle( eventbuffer
);
258 if (eventdata
) CloseHandle( eventdata
);
259 CloseHandle( mapping
);
265 /***********************************************************************
266 * OutputDebugStringW (kernelbase.@)
268 void WINAPI DECLSPEC_HOTPATCH
OutputDebugStringW( LPCWSTR str
)
273 RtlInitUnicodeString( &strW
, str
);
274 if (!RtlUnicodeStringToAnsiString( &strA
, &strW
, TRUE
))
276 OutputDebugStringA( strA
.Buffer
);
277 RtlFreeAnsiString( &strA
);
282 /*******************************************************************
283 * RaiseException (kernelbase.@)
285 void WINAPI DECLSPEC_HOTPATCH
RaiseException( DWORD code
, DWORD flags
, DWORD count
, const ULONG_PTR
*args
)
287 EXCEPTION_RECORD record
;
289 record
.ExceptionCode
= code
;
290 record
.ExceptionFlags
= flags
& EH_NONCONTINUABLE
;
291 record
.ExceptionRecord
= NULL
;
292 record
.ExceptionAddress
= RaiseException
;
295 if (count
> EXCEPTION_MAXIMUM_PARAMETERS
) count
= EXCEPTION_MAXIMUM_PARAMETERS
;
296 record
.NumberParameters
= count
;
297 memcpy( record
.ExceptionInformation
, args
, count
* sizeof(*args
) );
299 else record
.NumberParameters
= 0;
301 RtlRaiseException( &record
);
303 __ASM_STDCALL_IMPORT(RaiseException
,16)
306 /***********************************************************************
307 * SetUnhandledExceptionFilter (kernelbase.@)
309 LPTOP_LEVEL_EXCEPTION_FILTER WINAPI DECLSPEC_HOTPATCH
SetUnhandledExceptionFilter(
310 LPTOP_LEVEL_EXCEPTION_FILTER filter
)
312 return InterlockedExchangePointer( (void **)&top_filter
, filter
);
316 /*******************************************************************
317 * format_exception_msg
319 static void format_exception_msg( const EXCEPTION_POINTERS
*ptr
, char *buffer
, int size
)
321 const EXCEPTION_RECORD
*rec
= ptr
->ExceptionRecord
;
324 switch(rec
->ExceptionCode
)
326 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
327 len
= snprintf( buffer
, size
, "Unhandled division by zero" );
329 case EXCEPTION_INT_OVERFLOW
:
330 len
= snprintf( buffer
, size
, "Unhandled overflow" );
332 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
333 len
= snprintf( buffer
, size
, "Unhandled array bounds" );
335 case EXCEPTION_ILLEGAL_INSTRUCTION
:
336 len
= snprintf( buffer
, size
, "Unhandled illegal instruction" );
338 case EXCEPTION_STACK_OVERFLOW
:
339 len
= snprintf( buffer
, size
, "Unhandled stack overflow" );
341 case EXCEPTION_PRIV_INSTRUCTION
:
342 len
= snprintf( buffer
, size
, "Unhandled privileged instruction" );
344 case EXCEPTION_ACCESS_VIOLATION
:
345 if (rec
->NumberParameters
== 2)
346 len
= snprintf( buffer
, size
, "Unhandled page fault on %s access to %p",
347 rec
->ExceptionInformation
[0] == EXCEPTION_WRITE_FAULT
? "write" :
348 rec
->ExceptionInformation
[0] == EXCEPTION_EXECUTE_FAULT
? "execute" : "read",
349 (void *)rec
->ExceptionInformation
[1]);
351 len
= snprintf( buffer
, size
, "Unhandled page fault");
353 case EXCEPTION_DATATYPE_MISALIGNMENT
:
354 len
= snprintf( buffer
, size
, "Unhandled alignment" );
357 len
= snprintf( buffer
, size
, "Unhandled ^C");
359 case STATUS_POSSIBLE_DEADLOCK
:
360 len
= snprintf( buffer
, size
, "Critical section %p wait failed",
361 (void *)rec
->ExceptionInformation
[0]);
363 case EXCEPTION_WINE_STUB
:
364 if ((ULONG_PTR
)rec
->ExceptionInformation
[1] >> 16)
365 len
= snprintf( buffer
, size
, "Unimplemented function %s.%s called",
366 (char *)rec
->ExceptionInformation
[0], (char *)rec
->ExceptionInformation
[1] );
368 len
= snprintf( buffer
, size
, "Unimplemented function %s.%ld called",
369 (char *)rec
->ExceptionInformation
[0], rec
->ExceptionInformation
[1] );
371 case EXCEPTION_WINE_ASSERTION
:
372 len
= snprintf( buffer
, size
, "Assertion failed" );
375 len
= snprintf( buffer
, size
, "Unhandled exception 0x%08x in thread %x",
376 rec
->ExceptionCode
, GetCurrentThreadId());
379 if (len
< 0 || len
>= size
) return;
380 snprintf( buffer
+ len
, size
- len
, " at address %p", ptr
->ExceptionRecord
->ExceptionAddress
);
384 /******************************************************************
387 * Does the effective debugger startup according to 'format'
389 static BOOL
start_debugger( EXCEPTION_POINTERS
*epointers
, HANDLE event
)
391 OBJECT_ATTRIBUTES attr
;
392 UNICODE_STRING nameW
;
393 WCHAR
*cmdline
, *env
, *p
, *format
= NULL
;
395 DWORD autostart
= TRUE
;
396 PROCESS_INFORMATION info
;
397 STARTUPINFOW startup
;
401 format_exception_msg( epointers
, buffer
, sizeof(buffer
) );
402 MESSAGE( "wine: %s (thread %04x), starting debugger...\n", buffer
, GetCurrentThreadId() );
404 attr
.Length
= sizeof(attr
);
405 attr
.RootDirectory
= 0;
406 attr
.ObjectName
= &nameW
;
408 attr
.SecurityDescriptor
= NULL
;
409 attr
.SecurityQualityOfService
= NULL
;
410 RtlInitUnicodeString( &nameW
, L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug" );
412 if (!NtOpenKey( &dbg_key
, KEY_READ
, &attr
))
414 KEY_VALUE_PARTIAL_INFORMATION
*info
;
415 DWORD format_size
= 0;
417 RtlInitUnicodeString( &nameW
, L
"Debugger" );
418 if (NtQueryValueKey( dbg_key
, &nameW
, KeyValuePartialInformation
,
419 NULL
, 0, &format_size
) == STATUS_BUFFER_TOO_SMALL
)
421 char *data
= HeapAlloc( GetProcessHeap(), 0, format_size
);
422 NtQueryValueKey( dbg_key
, &nameW
, KeyValuePartialInformation
,
423 data
, format_size
, &format_size
);
424 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)data
;
425 format
= HeapAlloc( GetProcessHeap(), 0, info
->DataLength
+ sizeof(WCHAR
) );
426 memcpy( format
, info
->Data
, info
->DataLength
);
427 format
[info
->DataLength
/ sizeof(WCHAR
)] = 0;
429 if (info
->Type
== REG_EXPAND_SZ
)
433 format_size
= ExpandEnvironmentStringsW( format
, NULL
, 0 );
434 tmp
= HeapAlloc( GetProcessHeap(), 0, format_size
* sizeof(WCHAR
));
435 ExpandEnvironmentStringsW( format
, tmp
, format_size
);
436 HeapFree( GetProcessHeap(), 0, format
);
439 HeapFree( GetProcessHeap(), 0, data
);
442 RtlInitUnicodeString( &nameW
, L
"Auto" );
443 if (!NtQueryValueKey( dbg_key
, &nameW
, KeyValuePartialInformation
,
444 buffer
, sizeof(buffer
)-sizeof(WCHAR
), &format_size
))
446 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
447 if (info
->Type
== REG_DWORD
) memcpy( &autostart
, info
->Data
, sizeof(DWORD
) );
448 else if (info
->Type
== REG_SZ
)
450 WCHAR
*str
= (WCHAR
*)info
->Data
;
451 str
[info
->DataLength
/sizeof(WCHAR
)] = 0;
452 autostart
= wcstol( str
, NULL
, 10 );
461 size_t format_size
= lstrlenW( format
) + 2*20;
462 cmdline
= HeapAlloc( GetProcessHeap(), 0, format_size
* sizeof(WCHAR
) );
463 swprintf( cmdline
, format_size
, format
, (long)GetCurrentProcessId(), (long)HandleToLong(event
) );
464 HeapFree( GetProcessHeap(), 0, format
);
468 cmdline
= HeapAlloc( GetProcessHeap(), 0, 80 * sizeof(WCHAR
) );
469 swprintf( cmdline
, 80, L
"winedbg --auto %ld %ld", (long)GetCurrentProcessId(), (long)HandleToLong(event
) );
474 HMODULE mod
= GetModuleHandleA( "user32.dll" );
475 MessageBoxA_funcptr pMessageBoxA
= NULL
;
477 if (mod
) pMessageBoxA
= (void *)GetProcAddress( mod
, "MessageBoxA" );
480 static const char msg
[] = ".\nDo you wish to debug it?";
482 format_exception_msg( epointers
, buffer
, sizeof(buffer
) - sizeof(msg
) );
483 strcat( buffer
, msg
);
484 if (pMessageBoxA( 0, buffer
, "Exception raised", MB_YESNO
| MB_ICONHAND
) == IDNO
)
486 TRACE( "Killing process\n" );
492 /* make WINEDEBUG empty in the environment */
493 env
= GetEnvironmentStringsW();
494 if (!TRACE_ON(winedbg
))
496 for (p
= env
; *p
; p
+= lstrlenW(p
) + 1)
498 if (!wcsncmp( p
, L
"WINEDEBUG=", 10 ))
500 WCHAR
*next
= p
+ lstrlenW(p
);
501 WCHAR
*end
= next
+ 1;
502 while (*end
) end
+= lstrlenW(end
) + 1;
503 memmove( p
+ 10, next
, end
+ 1 - next
);
509 TRACE( "Starting debugger %s\n", debugstr_w(cmdline
) );
510 memset( &startup
, 0, sizeof(startup
) );
511 startup
.cb
= sizeof(startup
);
512 startup
.dwFlags
= STARTF_USESHOWWINDOW
;
513 startup
.wShowWindow
= SW_SHOWNORMAL
;
514 ret
= CreateProcessW( NULL
, cmdline
, NULL
, NULL
, TRUE
, 0, env
, NULL
, &startup
, &info
);
515 FreeEnvironmentStringsW( env
);
519 /* wait for debugger to come up... */
521 CloseHandle( info
.hThread
);
523 handles
[1] = info
.hProcess
;
524 WaitForMultipleObjects( 2, handles
, FALSE
, INFINITE
);
525 CloseHandle( info
.hProcess
);
527 else ERR( "Couldn't start debugger %s (%d)\n"
528 "Read the Wine Developers Guide on how to set up winedbg or another debugger\n",
529 debugstr_w(cmdline
), GetLastError() );
531 HeapFree(GetProcessHeap(), 0, cmdline
);
535 /******************************************************************
536 * start_debugger_atomic
538 * starts the debugger in an atomic way:
539 * - either the debugger is not started and it is started
540 * - or the debugger has already been started by another thread
541 * - or the debugger couldn't be started
543 * returns TRUE for the two first conditions, FALSE for the last
545 static BOOL
start_debugger_atomic( EXCEPTION_POINTERS
*epointers
)
551 OBJECT_ATTRIBUTES attr
;
554 attr
.Length
= sizeof(attr
);
555 attr
.RootDirectory
= 0;
556 attr
.Attributes
= OBJ_INHERIT
;
557 attr
.ObjectName
= NULL
;
558 attr
.SecurityDescriptor
= NULL
;
559 attr
.SecurityQualityOfService
= NULL
;
561 /* ask for manual reset, so that once the debugger is started,
562 * every thread will know it */
563 NtCreateEvent( &event
, EVENT_ALL_ACCESS
, &attr
, NotificationEvent
, FALSE
);
564 if (InterlockedCompareExchangePointer( &once
, event
, 0 ) == 0)
566 /* ok, our event has been set... we're the winning thread */
567 BOOL ret
= start_debugger( epointers
, once
);
571 /* so that the other threads won't be stuck */
572 NtSetEvent( once
, NULL
);
577 /* someone beat us here... */
578 CloseHandle( event
);
581 /* and wait for the winner to have actually created the debugger */
582 WaitForSingleObject( once
, INFINITE
);
583 /* in fact, here, we only know that someone has tried to start the debugger,
584 * we'll know by reposting the exception if it has actually attached
585 * to the current process */
590 /*******************************************************************
591 * check_resource_write
593 * Check if the exception is a write attempt to the resource data.
594 * If yes, we unprotect the resources to let broken apps continue
595 * (Windows does this too).
597 static BOOL
check_resource_write( void *addr
)
602 MEMORY_BASIC_INFORMATION info
;
604 if (!VirtualQuery( addr
, &info
, sizeof(info
) )) return FALSE
;
605 if (info
.State
== MEM_FREE
|| !(info
.Type
& MEM_IMAGE
)) return FALSE
;
606 if (!(rsrc
= RtlImageDirectoryEntryToData( info
.AllocationBase
, TRUE
,
607 IMAGE_DIRECTORY_ENTRY_RESOURCE
, &size
)))
609 if (addr
< rsrc
|| (char *)addr
>= (char *)rsrc
+ size
) return FALSE
;
610 TRACE( "Broken app is writing to the resource data, enabling work-around\n" );
611 VirtualProtect( rsrc
, size
, PAGE_READWRITE
, &old_prot
);
616 /*******************************************************************
617 * UnhandledExceptionFilter (kernelbase.@)
619 LONG WINAPI
UnhandledExceptionFilter( EXCEPTION_POINTERS
*epointers
)
621 const EXCEPTION_RECORD
*rec
= epointers
->ExceptionRecord
;
623 if (rec
->ExceptionCode
== EXCEPTION_ACCESS_VIOLATION
&& rec
->NumberParameters
>= 2)
625 switch (rec
->ExceptionInformation
[0])
627 case EXCEPTION_WRITE_FAULT
:
628 if (check_resource_write( (void *)rec
->ExceptionInformation
[1] ))
629 return EXCEPTION_CONTINUE_EXECUTION
;
634 if (!NtCurrentTeb()->Peb
->BeingDebugged
)
636 if (rec
->ExceptionCode
== CONTROL_C_EXIT
)
638 /* do not launch the debugger on ^C, simply terminate the process */
639 TerminateProcess( GetCurrentProcess(), 1 );
644 LONG ret
= top_filter( epointers
);
645 if (ret
!= EXCEPTION_CONTINUE_SEARCH
) return ret
;
648 /* FIXME: Should check the current error mode */
650 if (!start_debugger_atomic( epointers
) || !NtCurrentTeb()->Peb
->BeingDebugged
)
651 return EXCEPTION_EXECUTE_HANDLER
;
653 return EXCEPTION_CONTINUE_SEARCH
;
657 /***********************************************************************
658 * WerGetFlags (kernelbase.@)
660 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerGetFlags( HANDLE process
, DWORD
*flags
)
662 FIXME( "(%p, %p) stub\n", process
, flags
);
667 /***********************************************************************
668 * WerRegisterFile (kernelbase.@)
670 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerRegisterFile( const WCHAR
*file
, WER_REGISTER_FILE_TYPE type
,
673 FIXME( "(%s, %d, %d) stub\n", debugstr_w(file
), type
, flags
);
678 /***********************************************************************
679 * WerRegisterMemoryBlock (kernelbase.@)
681 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerRegisterMemoryBlock( void *block
, DWORD size
)
683 FIXME( "(%p %d) stub\n", block
, size
);
688 /***********************************************************************
689 * WerRegisterRuntimeExceptionModule (kernelbase.@)
691 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerRegisterRuntimeExceptionModule( const WCHAR
*dll
, void *context
)
693 FIXME( "(%s, %p) stub\n", debugstr_w(dll
), context
);
698 /***********************************************************************
699 * WerSetFlags (kernelbase.@)
701 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerSetFlags( DWORD flags
)
703 FIXME("(%d) stub\n", flags
);
708 /***********************************************************************
709 * WerUnregisterFile (kernelbase.@)
711 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerUnregisterFile( const WCHAR
*file
)
713 FIXME( "(%s) stub\n", debugstr_w(file
) );
718 /***********************************************************************
719 * WerUnregisterMemoryBlock (kernelbase.@)
721 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerUnregisterMemoryBlock( void *block
)
723 FIXME( "(%p) stub\n", block
);
728 /***********************************************************************
729 * WerUnregisterRuntimeExceptionModule (kernelbase.@)
731 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerUnregisterRuntimeExceptionModule( const WCHAR
*dll
, void *context
)
733 FIXME( "(%s, %p) stub\n", debugstr_w(dll
), context
);
738 /***********************************************************************
740 ***********************************************************************/
743 typedef struct _PEB32
745 BOOLEAN InheritedAddressSpace
;
746 BOOLEAN ReadImageFileExecOptions
;
747 BOOLEAN BeingDebugged
;
750 DWORD ImageBaseAddress
;
754 typedef struct _LIST_ENTRY32
760 typedef struct _PEB_LDR_DATA32
765 LIST_ENTRY32 InLoadOrderModuleList
;
768 typedef struct _UNICODE_STRING32
771 USHORT MaximumLength
;
775 typedef struct _LDR_DATA_TABLE_ENTRY32
777 LIST_ENTRY32 InLoadOrderModuleList
;
778 LIST_ENTRY32 InMemoryOrderModuleList
;
779 LIST_ENTRY32 InInitializationOrderModuleList
;
783 UNICODE_STRING32 FullDllName
;
784 UNICODE_STRING32 BaseDllName
;
785 } LDR_DATA_TABLE_ENTRY32
;
787 struct module_iterator
793 LDR_DATA_TABLE_ENTRY ldr_module
;
794 LDR_DATA_TABLE_ENTRY32 ldr_module32
;
798 static BOOL
init_module_iterator( struct module_iterator
*iter
, HANDLE process
)
800 PROCESS_BASIC_INFORMATION pbi
;
801 PPEB_LDR_DATA ldr_data
;
803 if (!IsWow64Process( process
, &iter
->wow64
)) return FALSE
;
805 /* get address of PEB */
806 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessBasicInformation
,
807 &pbi
, sizeof(pbi
), NULL
)))
810 if (is_win64
&& iter
->wow64
)
812 PEB_LDR_DATA32
*ldr_data32_ptr
;
813 DWORD ldr_data32
, first_module
;
816 peb32
= (PEB32
*)(DWORD_PTR
)pbi
.PebBaseAddress
;
817 if (!ReadProcessMemory( process
, &peb32
->LdrData
, &ldr_data32
, sizeof(ldr_data32
), NULL
))
819 ldr_data32_ptr
= (PEB_LDR_DATA32
*)(DWORD_PTR
) ldr_data32
;
820 if (!ReadProcessMemory( process
, &ldr_data32_ptr
->InLoadOrderModuleList
.Flink
,
821 &first_module
, sizeof(first_module
), NULL
))
823 iter
->head
= (LIST_ENTRY
*)&ldr_data32_ptr
->InLoadOrderModuleList
;
824 iter
->current
= (LIST_ENTRY
*)(DWORD_PTR
)first_module
;
825 iter
->process
= process
;
829 /* read address of LdrData from PEB */
830 if (!ReadProcessMemory( process
, &pbi
.PebBaseAddress
->LdrData
, &ldr_data
, sizeof(ldr_data
), NULL
))
833 /* read address of first module from LdrData */
834 if (!ReadProcessMemory( process
, &ldr_data
->InLoadOrderModuleList
.Flink
,
835 &iter
->current
, sizeof(iter
->current
), NULL
))
838 iter
->head
= &ldr_data
->InLoadOrderModuleList
;
839 iter
->process
= process
;
844 static int module_iterator_next( struct module_iterator
*iter
)
846 if (iter
->current
== iter
->head
) return 0;
848 if (is_win64
&& iter
->wow64
)
850 LIST_ENTRY32
*entry32
= (LIST_ENTRY32
*)iter
->current
;
852 if (!ReadProcessMemory( iter
->process
,
853 CONTAINING_RECORD(entry32
, LDR_DATA_TABLE_ENTRY32
, InLoadOrderModuleList
),
854 &iter
->ldr_module32
, sizeof(iter
->ldr_module32
), NULL
))
856 iter
->current
= (LIST_ENTRY
*)(DWORD_PTR
)iter
->ldr_module32
.InLoadOrderModuleList
.Flink
;
860 if (!ReadProcessMemory( iter
->process
,
861 CONTAINING_RECORD(iter
->current
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
),
862 &iter
->ldr_module
, sizeof(iter
->ldr_module
), NULL
))
865 iter
->current
= iter
->ldr_module
.InLoadOrderLinks
.Flink
;
870 static BOOL
get_ldr_module( HANDLE process
, HMODULE module
, LDR_DATA_TABLE_ENTRY
*ldr_module
)
872 struct module_iterator iter
;
875 if (!init_module_iterator( &iter
, process
)) return FALSE
;
877 while ((ret
= module_iterator_next( &iter
)) > 0)
878 /* When hModule is NULL we return the process image - which will be
879 * the first module since our iterator uses InLoadOrderModuleList */
880 if (!module
|| module
== iter
.ldr_module
.DllBase
)
882 *ldr_module
= iter
.ldr_module
;
886 if (ret
== 0) SetLastError( ERROR_INVALID_HANDLE
);
891 static BOOL
get_ldr_module32( HANDLE process
, HMODULE module
, LDR_DATA_TABLE_ENTRY32
*ldr_module
)
893 struct module_iterator iter
;
896 if (!init_module_iterator( &iter
, process
)) return FALSE
;
898 while ((ret
= module_iterator_next( &iter
)) > 0)
899 /* When hModule is NULL we return the process image - which will be
900 * the first module since our iterator uses InLoadOrderModuleList */
901 if (!module
|| (DWORD
)(DWORD_PTR
)module
== iter
.ldr_module32
.BaseAddress
)
903 *ldr_module
= iter
.ldr_module32
;
907 if (ret
== 0) SetLastError( ERROR_INVALID_HANDLE
);
912 /***********************************************************************
913 * K32EmptyWorkingSet (kernelbase.@)
915 BOOL WINAPI DECLSPEC_HOTPATCH
K32EmptyWorkingSet( HANDLE process
)
917 return SetProcessWorkingSetSizeEx( process
, (SIZE_T
)-1, (SIZE_T
)-1, 0 );
921 /***********************************************************************
922 * K32EnumDeviceDrivers (kernelbase.@)
924 BOOL WINAPI
K32EnumDeviceDrivers( void **image_base
, DWORD count
, DWORD
*needed
)
926 FIXME( "(%p, %d, %p): stub\n", image_base
, count
, needed
);
927 if (needed
) *needed
= 0;
932 /***********************************************************************
933 * K32EnumPageFilesA (kernelbase.@)
935 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ K32EnumPageFilesA( PENUM_PAGE_FILE_CALLBACKA callback
, void *context
)
937 FIXME( "(%p, %p) stub\n", callback
, context
);
942 /***********************************************************************
943 * K32EnumPageFilesW (kernelbase.@)
945 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ K32EnumPageFilesW( PENUM_PAGE_FILE_CALLBACKW callback
, void *context
)
947 FIXME( "(%p, %p) stub\n", callback
, context
);
952 /***********************************************************************
953 * K32EnumProcessModules (kernelbase.@)
955 BOOL WINAPI DECLSPEC_HOTPATCH
K32EnumProcessModules( HANDLE process
, HMODULE
*module
,
956 DWORD count
, DWORD
*needed
)
958 struct module_iterator iter
;
962 if (process
== GetCurrentProcess())
964 PPEB_LDR_DATA ldr_data
= NtCurrentTeb()->Peb
->LdrData
;
965 PLIST_ENTRY head
= &ldr_data
->InLoadOrderModuleList
;
966 PLIST_ENTRY entry
= head
->Flink
;
968 if (count
&& !module
)
970 SetLastError( ERROR_NOACCESS
);
973 while (entry
!= head
)
975 LDR_DATA_TABLE_ENTRY
*ldr
= CONTAINING_RECORD( entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
976 if (count
>= sizeof(HMODULE
))
978 *module
++ = ldr
->DllBase
;
979 count
-= sizeof(HMODULE
);
981 size
+= sizeof(HMODULE
);
982 entry
= entry
->Flink
;
986 SetLastError( ERROR_NOACCESS
);
993 if (!init_module_iterator( &iter
, process
)) return FALSE
;
995 if (count
&& !module
)
997 SetLastError( ERROR_NOACCESS
);
1001 while ((ret
= module_iterator_next( &iter
)) > 0)
1003 if (count
>= sizeof(HMODULE
))
1005 if (sizeof(void *) == 8 && iter
.wow64
)
1006 *module
++ = (HMODULE
) (DWORD_PTR
)iter
.ldr_module32
.BaseAddress
;
1008 *module
++ = iter
.ldr_module
.DllBase
;
1009 count
-= sizeof(HMODULE
);
1011 size
+= sizeof(HMODULE
);
1016 SetLastError( ERROR_NOACCESS
);
1024 /***********************************************************************
1025 * K32EnumProcessModulesEx (kernelbase.@)
1027 BOOL WINAPI
K32EnumProcessModulesEx( HANDLE process
, HMODULE
*module
, DWORD count
,
1028 DWORD
*needed
, DWORD filter
)
1030 FIXME( "(%p, %p, %d, %p, %d) semi-stub\n", process
, module
, count
, needed
, filter
);
1031 return K32EnumProcessModules( process
, module
, count
, needed
);
1035 /***********************************************************************
1036 * K32EnumProcesses (kernelbase.@)
1038 BOOL WINAPI
K32EnumProcesses( DWORD
*ids
, DWORD count
, DWORD
*used
)
1040 SYSTEM_PROCESS_INFORMATION
*spi
;
1041 ULONG size
= 0x4000;
1048 HeapFree( GetProcessHeap(), 0, buf
);
1049 if (!(buf
= HeapAlloc( GetProcessHeap(), 0, size
))) return FALSE
;
1050 status
= NtQuerySystemInformation( SystemProcessInformation
, buf
, size
, NULL
);
1051 } while (status
== STATUS_INFO_LENGTH_MISMATCH
);
1053 if (!set_ntstatus( status
))
1055 HeapFree( GetProcessHeap(), 0, buf
);
1059 for (*used
= 0; count
>= sizeof(DWORD
); count
-= sizeof(DWORD
))
1061 *ids
++ = HandleToUlong( spi
->UniqueProcessId
);
1062 *used
+= sizeof(DWORD
);
1063 if (spi
->NextEntryOffset
== 0) break;
1064 spi
= (SYSTEM_PROCESS_INFORMATION
*)(((PCHAR
)spi
) + spi
->NextEntryOffset
);
1066 HeapFree( GetProcessHeap(), 0, buf
);
1071 /***********************************************************************
1072 * K32GetDeviceDriverBaseNameA (kernelbase.@)
1074 DWORD WINAPI DECLSPEC_HOTPATCH
K32GetDeviceDriverBaseNameA( void *image_base
, char *name
, DWORD size
)
1076 FIXME( "(%p, %p, %d): stub\n", image_base
, name
, size
);
1077 if (name
&& size
) name
[0] = 0;
1082 /***********************************************************************
1083 * K32GetDeviceDriverBaseNameW (kernelbase.@)
1085 DWORD WINAPI DECLSPEC_HOTPATCH
K32GetDeviceDriverBaseNameW( void *image_base
, WCHAR
*name
, DWORD size
)
1087 FIXME( "(%p, %p, %d): stub\n", image_base
, name
, size
);
1088 if (name
&& size
) name
[0] = 0;
1093 /***********************************************************************
1094 * K32GetDeviceDriverFileNameA (kernelbase.@)
1096 DWORD WINAPI DECLSPEC_HOTPATCH
K32GetDeviceDriverFileNameA( void *image_base
, char *name
, DWORD size
)
1098 FIXME( "(%p, %p, %d): stub\n", image_base
, name
, size
);
1099 if (name
&& size
) name
[0] = 0;
1104 /***********************************************************************
1105 * K32GetDeviceDriverFileNameW (kernelbase.@)
1107 DWORD WINAPI DECLSPEC_HOTPATCH
K32GetDeviceDriverFileNameW( void *image_base
, WCHAR
*name
, DWORD size
)
1109 FIXME( "(%p, %p, %d): stub\n", image_base
, name
, size
);
1110 if (name
&& size
) name
[0] = 0;
1115 /***********************************************************************
1116 * K32GetMappedFileNameA (kernelbase.@)
1118 DWORD WINAPI DECLSPEC_HOTPATCH
K32GetMappedFileNameA( HANDLE process
, void *addr
, char *name
, DWORD size
)
1120 FIXME( "(%p, %p, %p, %d): stub\n", process
, addr
, name
, size
);
1121 if (name
&& size
) name
[0] = 0;
1126 /***********************************************************************
1127 * K32GetMappedFileNameW (kernelbase.@)
1129 DWORD WINAPI DECLSPEC_HOTPATCH
K32GetMappedFileNameW( HANDLE process
, void *addr
, WCHAR
*name
, DWORD size
)
1131 FIXME( "(%p, %p, %p, %d): stub\n", process
, addr
, name
, size
);
1132 if (name
&& size
) name
[0] = 0;
1137 /***********************************************************************
1138 * K32GetModuleBaseNameA (kernelbase.@)
1140 DWORD WINAPI DECLSPEC_HOTPATCH
K32GetModuleBaseNameA( HANDLE process
, HMODULE module
,
1141 char *name
, DWORD size
)
1148 SetLastError( ERROR_INVALID_PARAMETER
);
1151 if (!(name_w
= HeapAlloc( GetProcessHeap(), 0, sizeof(WCHAR
) * size
))) return 0;
1153 len
= K32GetModuleBaseNameW( process
, module
, name_w
, size
);
1154 TRACE( "%d, %s\n", len
, debugstr_w(name_w
) );
1157 ret
= WideCharToMultiByte( CP_ACP
, 0, name_w
, len
, name
, size
, NULL
, NULL
);
1158 if (ret
< size
) name
[ret
] = 0;
1160 HeapFree( GetProcessHeap(), 0, name_w
);
1165 /***********************************************************************
1166 * K32GetModuleBaseNameW (kernelbase.@)
1168 DWORD WINAPI DECLSPEC_HOTPATCH
K32GetModuleBaseNameW( HANDLE process
, HMODULE module
,
1169 WCHAR
*name
, DWORD size
)
1173 if (!IsWow64Process( process
, &wow64
)) return 0;
1175 if (is_win64
&& wow64
)
1177 LDR_DATA_TABLE_ENTRY32 ldr_module32
;
1179 if (!get_ldr_module32(process
, module
, &ldr_module32
)) return 0;
1180 size
= min( ldr_module32
.BaseDllName
.Length
/ sizeof(WCHAR
), size
);
1181 if (!ReadProcessMemory( process
, (void *)(DWORD_PTR
)ldr_module32
.BaseDllName
.Buffer
,
1182 name
, size
* sizeof(WCHAR
), NULL
))
1187 LDR_DATA_TABLE_ENTRY ldr_module
;
1189 if (!get_ldr_module( process
, module
, &ldr_module
)) return 0;
1190 size
= min( ldr_module
.BaseDllName
.Length
/ sizeof(WCHAR
), size
);
1191 if (!ReadProcessMemory( process
, ldr_module
.BaseDllName
.Buffer
,
1192 name
, size
* sizeof(WCHAR
), NULL
))
1200 /***********************************************************************
1201 * K32GetModuleFileNameExA (kernelbase.@)
1203 DWORD WINAPI DECLSPEC_HOTPATCH
K32GetModuleFileNameExA( HANDLE process
, HMODULE module
,
1204 char *name
, DWORD size
)
1209 TRACE( "(process=%p, module=%p, %p, %d)\n", process
, module
, name
, size
);
1213 SetLastError( ERROR_INVALID_PARAMETER
);
1216 if (process
== GetCurrentProcess())
1218 len
= GetModuleFileNameA( module
, name
, size
);
1219 name
[size
- 1] = '\0';
1223 if (!(ptr
= HeapAlloc( GetProcessHeap(), 0, size
* sizeof(WCHAR
) ))) return 0;
1224 len
= K32GetModuleFileNameExW( process
, module
, ptr
, size
);
1231 if (!WideCharToMultiByte( CP_ACP
, 0, ptr
, -1, name
, size
, NULL
, NULL
))
1236 else if (len
< size
) len
= strlen( name
);
1238 HeapFree( GetProcessHeap(), 0, ptr
);
1243 /***********************************************************************
1244 * K32GetModuleFileNameExW (kernelbase.@)
1246 DWORD WINAPI DECLSPEC_HOTPATCH
K32GetModuleFileNameExW( HANDLE process
, HMODULE module
,
1247 WCHAR
*name
, DWORD size
)
1252 if (!size
) return 0;
1254 if (!IsWow64Process( process
, &wow64
)) return 0;
1256 if (is_win64
&& wow64
)
1258 LDR_DATA_TABLE_ENTRY32 ldr_module32
;
1260 if (!get_ldr_module32( process
, module
, &ldr_module32
)) return 0;
1261 len
= ldr_module32
.FullDllName
.Length
/ sizeof(WCHAR
);
1262 if (!ReadProcessMemory( process
, (void *)(DWORD_PTR
)ldr_module32
.FullDllName
.Buffer
,
1263 name
, min( len
, size
) * sizeof(WCHAR
), NULL
))
1268 LDR_DATA_TABLE_ENTRY ldr_module
;
1270 if (!get_ldr_module(process
, module
, &ldr_module
)) return 0;
1271 len
= ldr_module
.FullDllName
.Length
/ sizeof(WCHAR
);
1272 if (!ReadProcessMemory( process
, ldr_module
.FullDllName
.Buffer
,
1273 name
, min( len
, size
) * sizeof(WCHAR
), NULL
))
1290 /***********************************************************************
1291 * K32GetModuleInformation (kernelbase.@)
1293 BOOL WINAPI
K32GetModuleInformation( HANDLE process
, HMODULE module
, MODULEINFO
*modinfo
, DWORD count
)
1297 if (count
< sizeof(MODULEINFO
))
1299 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1303 if (!IsWow64Process( process
, &wow64
)) return FALSE
;
1305 if (is_win64
&& wow64
)
1307 LDR_DATA_TABLE_ENTRY32 ldr_module32
;
1309 if (!get_ldr_module32( process
, module
, &ldr_module32
)) return FALSE
;
1310 modinfo
->lpBaseOfDll
= (void *)(DWORD_PTR
)ldr_module32
.BaseAddress
;
1311 modinfo
->SizeOfImage
= ldr_module32
.SizeOfImage
;
1312 modinfo
->EntryPoint
= (void *)(DWORD_PTR
)ldr_module32
.EntryPoint
;
1316 LDR_DATA_TABLE_ENTRY ldr_module
;
1318 if (!get_ldr_module( process
, module
, &ldr_module
)) return FALSE
;
1319 modinfo
->lpBaseOfDll
= ldr_module
.DllBase
;
1320 modinfo
->SizeOfImage
= ldr_module
.SizeOfImage
;
1321 modinfo
->EntryPoint
= ldr_module
.EntryPoint
;
1327 /***********************************************************************
1328 * K32GetPerformanceInfo (kernelbase.@)
1330 BOOL WINAPI DECLSPEC_HOTPATCH
K32GetPerformanceInfo( PPERFORMANCE_INFORMATION info
, DWORD size
)
1332 SYSTEM_PERFORMANCE_INFORMATION perf
;
1333 SYSTEM_BASIC_INFORMATION basic
;
1334 SYSTEM_PROCESS_INFORMATION
*process
, *spi
;
1338 TRACE( "(%p, %d)\n", info
, size
);
1340 if (size
< sizeof(*info
))
1342 SetLastError( ERROR_BAD_LENGTH
);
1346 status
= NtQuerySystemInformation( SystemPerformanceInformation
, &perf
, sizeof(perf
), NULL
);
1347 if (!set_ntstatus( status
)) return FALSE
;
1348 status
= NtQuerySystemInformation( SystemBasicInformation
, &basic
, sizeof(basic
), NULL
);
1349 if (!set_ntstatus( status
)) return FALSE
;
1351 info
->cb
= sizeof(*info
);
1352 info
->CommitTotal
= perf
.TotalCommittedPages
;
1353 info
->CommitLimit
= perf
.TotalCommitLimit
;
1354 info
->CommitPeak
= perf
.PeakCommitment
;
1355 info
->PhysicalTotal
= basic
.MmNumberOfPhysicalPages
;
1356 info
->PhysicalAvailable
= perf
.AvailablePages
;
1357 info
->SystemCache
= 0;
1358 info
->KernelTotal
= perf
.PagedPoolUsage
+ perf
.NonPagedPoolUsage
;
1359 info
->KernelPaged
= perf
.PagedPoolUsage
;
1360 info
->KernelNonpaged
= perf
.NonPagedPoolUsage
;
1361 info
->PageSize
= basic
.PageSize
;
1363 /* fields from SYSTEM_PROCESS_INFORMATION */
1364 NtQuerySystemInformation( SystemProcessInformation
, NULL
, 0, &info_size
);
1367 process
= HeapAlloc( GetProcessHeap(), 0, info_size
);
1370 SetLastError( ERROR_OUTOFMEMORY
);
1373 status
= NtQuerySystemInformation( SystemProcessInformation
, process
, info_size
, &info_size
);
1375 HeapFree( GetProcessHeap(), 0, process
);
1376 if (status
!= STATUS_INFO_LENGTH_MISMATCH
)
1378 SetLastError( RtlNtStatusToDosError( status
) );
1382 info
->HandleCount
= info
->ProcessCount
= info
->ThreadCount
= 0;
1386 info
->ProcessCount
++;
1387 info
->HandleCount
+= spi
->HandleCount
;
1388 info
->ThreadCount
+= spi
->dwThreadCount
;
1389 if (spi
->NextEntryOffset
== 0) break;
1390 spi
= (SYSTEM_PROCESS_INFORMATION
*)((char *)spi
+ spi
->NextEntryOffset
);
1392 HeapFree( GetProcessHeap(), 0, process
);
1397 /***********************************************************************
1398 * K32GetProcessImageFileNameA (kernelbase.@)
1400 DWORD WINAPI DECLSPEC_HOTPATCH
K32GetProcessImageFileNameA( HANDLE process
, char *file
, DWORD size
)
1402 return QueryFullProcessImageNameA( process
, PROCESS_NAME_NATIVE
, file
, &size
) ? size
: 0;
1406 /***********************************************************************
1407 * K32GetProcessImageFileNameW (kernelbase.@)
1409 DWORD WINAPI DECLSPEC_HOTPATCH
K32GetProcessImageFileNameW( HANDLE process
, WCHAR
*file
, DWORD size
)
1411 return QueryFullProcessImageNameW( process
, PROCESS_NAME_NATIVE
, file
, &size
) ? size
: 0;
1415 /***********************************************************************
1416 * K32GetProcessMemoryInfo (kernelbase.@)
1418 BOOL WINAPI DECLSPEC_HOTPATCH
K32GetProcessMemoryInfo( HANDLE process
, PROCESS_MEMORY_COUNTERS
*pmc
,
1423 if (count
< sizeof(PROCESS_MEMORY_COUNTERS
))
1425 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1429 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessVmCounters
, &vmc
, sizeof(vmc
), NULL
)))
1432 pmc
->cb
= sizeof(PROCESS_MEMORY_COUNTERS
);
1433 pmc
->PageFaultCount
= vmc
.PageFaultCount
;
1434 pmc
->PeakWorkingSetSize
= vmc
.PeakWorkingSetSize
;
1435 pmc
->WorkingSetSize
= vmc
.WorkingSetSize
;
1436 pmc
->QuotaPeakPagedPoolUsage
= vmc
.QuotaPeakPagedPoolUsage
;
1437 pmc
->QuotaPagedPoolUsage
= vmc
.QuotaPagedPoolUsage
;
1438 pmc
->QuotaPeakNonPagedPoolUsage
= vmc
.QuotaPeakNonPagedPoolUsage
;
1439 pmc
->QuotaNonPagedPoolUsage
= vmc
.QuotaNonPagedPoolUsage
;
1440 pmc
->PagefileUsage
= vmc
.PagefileUsage
;
1441 pmc
->PeakPagefileUsage
= vmc
.PeakPagefileUsage
;
1446 /***********************************************************************
1447 * K32GetWsChanges (kernelbase.@)
1449 BOOL WINAPI DECLSPEC_HOTPATCH
K32GetWsChanges( HANDLE process
, PSAPI_WS_WATCH_INFORMATION
*info
, DWORD size
)
1451 TRACE( "(%p, %p, %d)\n", process
, info
, size
);
1452 return set_ntstatus( NtQueryInformationProcess( process
, ProcessWorkingSetWatch
, info
, size
, NULL
));
1456 /***********************************************************************
1457 * K32GetWsChangesEx (kernelbase.@)
1459 BOOL WINAPI DECLSPEC_HOTPATCH
K32GetWsChangesEx( HANDLE process
, PSAPI_WS_WATCH_INFORMATION_EX
*info
,
1462 FIXME( "(%p, %p, %p)\n", process
, info
, size
);
1463 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1468 /***********************************************************************
1469 * K32InitializeProcessForWsWatch (kernelbase.@)
1471 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ K32InitializeProcessForWsWatch( HANDLE process
)
1473 FIXME( "(process=%p): stub\n", process
);
1478 /***********************************************************************
1479 * K32QueryWorkingSet (kernelbase.@)
1481 BOOL WINAPI DECLSPEC_HOTPATCH
K32QueryWorkingSet( HANDLE process
, void *buffer
, DWORD size
)
1483 TRACE( "(%p, %p, %d)\n", process
, buffer
, size
);
1484 return set_ntstatus( NtQueryVirtualMemory( process
, NULL
, MemoryWorkingSetList
, buffer
, size
, NULL
));
1488 /***********************************************************************
1489 * K32QueryWorkingSetEx (kernelbase.@)
1491 BOOL WINAPI
K32QueryWorkingSetEx( HANDLE process
, void *buffer
, DWORD size
)
1493 TRACE( "(%p, %p, %d)\n", process
, buffer
, size
);
1494 return set_ntstatus( NtQueryVirtualMemory( process
, NULL
, MemoryWorkingSetExInformation
,
1495 buffer
, size
, NULL
));
1499 /******************************************************************
1500 * QueryFullProcessImageNameA (kernelbase.@)
1502 BOOL WINAPI DECLSPEC_HOTPATCH
QueryFullProcessImageNameA( HANDLE process
, DWORD flags
,
1503 char *name
, DWORD
*size
)
1506 DWORD sizeW
= *size
;
1507 WCHAR
*nameW
= HeapAlloc( GetProcessHeap(), 0, *size
* sizeof(WCHAR
) );
1509 ret
= QueryFullProcessImageNameW( process
, flags
, nameW
, &sizeW
);
1510 if (ret
) ret
= (WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, name
, *size
, NULL
, NULL
) > 0);
1511 if (ret
) *size
= strlen( name
);
1512 HeapFree( GetProcessHeap(), 0, nameW
);
1517 /******************************************************************
1518 * QueryFullProcessImageNameW (kernelbase.@)
1520 BOOL WINAPI DECLSPEC_HOTPATCH
QueryFullProcessImageNameW( HANDLE process
, DWORD flags
,
1521 WCHAR
*name
, DWORD
*size
)
1523 BYTE buffer
[sizeof(UNICODE_STRING
) + MAX_PATH
*sizeof(WCHAR
)]; /* this buffer should be enough */
1524 UNICODE_STRING
*dynamic_buffer
= NULL
;
1525 UNICODE_STRING
*result
= NULL
;
1529 /* FIXME: On Windows, ProcessImageFileName return an NT path. In Wine it
1530 * is a DOS path and we depend on this. */
1531 status
= NtQueryInformationProcess( process
, ProcessImageFileName
, buffer
,
1532 sizeof(buffer
) - sizeof(WCHAR
), &needed
);
1533 if (status
== STATUS_INFO_LENGTH_MISMATCH
)
1535 dynamic_buffer
= HeapAlloc( GetProcessHeap(), 0, needed
+ sizeof(WCHAR
) );
1536 status
= NtQueryInformationProcess( process
, ProcessImageFileName
, dynamic_buffer
,
1538 result
= dynamic_buffer
;
1541 result
= (UNICODE_STRING
*)buffer
;
1543 if (status
) goto cleanup
;
1545 if (flags
& PROCESS_NAME_NATIVE
)
1549 DWORD ntlen
, devlen
;
1551 if (result
->Buffer
[1] != ':' || result
->Buffer
[0] < 'A' || result
->Buffer
[0] > 'Z')
1553 /* We cannot convert it to an NT device path so fail */
1554 status
= STATUS_NO_SUCH_DEVICE
;
1558 /* Find this drive's NT device path */
1559 drive
[0] = result
->Buffer
[0];
1562 if (!QueryDosDeviceW(drive
, device
, ARRAY_SIZE(device
)))
1564 status
= STATUS_NO_SUCH_DEVICE
;
1568 devlen
= lstrlenW(device
);
1569 ntlen
= devlen
+ (result
->Length
/sizeof(WCHAR
) - 2);
1570 if (ntlen
+ 1 > *size
)
1572 status
= STATUS_BUFFER_TOO_SMALL
;
1577 memcpy( name
, device
, devlen
* sizeof(*device
) );
1578 memcpy( name
+ devlen
, result
->Buffer
+ 2, result
->Length
- 2 * sizeof(WCHAR
) );
1580 TRACE( "NT path: %s\n", debugstr_w(name
) );
1584 if (result
->Length
/sizeof(WCHAR
) + 1 > *size
)
1586 status
= STATUS_BUFFER_TOO_SMALL
;
1590 *size
= result
->Length
/sizeof(WCHAR
);
1591 memcpy( name
, result
->Buffer
, result
->Length
);
1596 HeapFree( GetProcessHeap(), 0, dynamic_buffer
);
1597 return set_ntstatus( status
);