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)
307 /***********************************************************************
308 * SetUnhandledExceptionFilter (kernelbase.@)
310 LPTOP_LEVEL_EXCEPTION_FILTER WINAPI DECLSPEC_HOTPATCH
SetUnhandledExceptionFilter(
311 LPTOP_LEVEL_EXCEPTION_FILTER filter
)
313 return InterlockedExchangePointer( (void **)&top_filter
, filter
);
317 /*******************************************************************
318 * format_exception_msg
320 static void format_exception_msg( const EXCEPTION_POINTERS
*ptr
, char *buffer
, int size
)
322 const EXCEPTION_RECORD
*rec
= ptr
->ExceptionRecord
;
325 switch(rec
->ExceptionCode
)
327 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
328 len
= snprintf( buffer
, size
, "Unhandled division by zero" );
330 case EXCEPTION_INT_OVERFLOW
:
331 len
= snprintf( buffer
, size
, "Unhandled overflow" );
333 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
334 len
= snprintf( buffer
, size
, "Unhandled array bounds" );
336 case EXCEPTION_ILLEGAL_INSTRUCTION
:
337 len
= snprintf( buffer
, size
, "Unhandled illegal instruction" );
339 case EXCEPTION_STACK_OVERFLOW
:
340 len
= snprintf( buffer
, size
, "Unhandled stack overflow" );
342 case EXCEPTION_PRIV_INSTRUCTION
:
343 len
= snprintf( buffer
, size
, "Unhandled privileged instruction" );
345 case EXCEPTION_ACCESS_VIOLATION
:
346 if (rec
->NumberParameters
== 2)
347 len
= snprintf( buffer
, size
, "Unhandled page fault on %s access to %p",
348 rec
->ExceptionInformation
[0] == EXCEPTION_WRITE_FAULT
? "write" :
349 rec
->ExceptionInformation
[0] == EXCEPTION_EXECUTE_FAULT
? "execute" : "read",
350 (void *)rec
->ExceptionInformation
[1]);
352 len
= snprintf( buffer
, size
, "Unhandled page fault");
354 case EXCEPTION_DATATYPE_MISALIGNMENT
:
355 len
= snprintf( buffer
, size
, "Unhandled alignment" );
358 len
= snprintf( buffer
, size
, "Unhandled ^C");
360 case STATUS_POSSIBLE_DEADLOCK
:
361 len
= snprintf( buffer
, size
, "Critical section %p wait failed",
362 (void *)rec
->ExceptionInformation
[0]);
364 case EXCEPTION_WINE_STUB
:
365 if ((ULONG_PTR
)rec
->ExceptionInformation
[1] >> 16)
366 len
= snprintf( buffer
, size
, "Unimplemented function %s.%s called",
367 (char *)rec
->ExceptionInformation
[0], (char *)rec
->ExceptionInformation
[1] );
369 len
= snprintf( buffer
, size
, "Unimplemented function %s.%ld called",
370 (char *)rec
->ExceptionInformation
[0], rec
->ExceptionInformation
[1] );
372 case EXCEPTION_WINE_ASSERTION
:
373 len
= snprintf( buffer
, size
, "Assertion failed" );
376 len
= snprintf( buffer
, size
, "Unhandled exception 0x%08x in thread %x",
377 rec
->ExceptionCode
, GetCurrentThreadId());
380 if (len
< 0 || len
>= size
) return;
381 snprintf( buffer
+ len
, size
- len
, " at address %p", ptr
->ExceptionRecord
->ExceptionAddress
);
385 /******************************************************************
388 * Does the effective debugger startup according to 'format'
390 static BOOL
start_debugger( EXCEPTION_POINTERS
*epointers
, HANDLE event
)
392 OBJECT_ATTRIBUTES attr
;
393 UNICODE_STRING nameW
;
394 WCHAR
*cmdline
, *env
, *p
, *format
= NULL
;
396 DWORD autostart
= TRUE
;
397 PROCESS_INFORMATION info
;
398 STARTUPINFOW startup
;
402 format_exception_msg( epointers
, buffer
, sizeof(buffer
) );
403 MESSAGE( "wine: %s (thread %04x), starting debugger...\n", buffer
, GetCurrentThreadId() );
405 attr
.Length
= sizeof(attr
);
406 attr
.RootDirectory
= 0;
407 attr
.ObjectName
= &nameW
;
409 attr
.SecurityDescriptor
= NULL
;
410 attr
.SecurityQualityOfService
= NULL
;
411 RtlInitUnicodeString( &nameW
, L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug" );
413 if (!NtOpenKey( &dbg_key
, KEY_READ
, &attr
))
415 KEY_VALUE_PARTIAL_INFORMATION
*info
;
416 DWORD format_size
= 0;
418 RtlInitUnicodeString( &nameW
, L
"Debugger" );
419 if (NtQueryValueKey( dbg_key
, &nameW
, KeyValuePartialInformation
,
420 NULL
, 0, &format_size
) == STATUS_BUFFER_TOO_SMALL
)
422 char *data
= HeapAlloc( GetProcessHeap(), 0, format_size
);
423 NtQueryValueKey( dbg_key
, &nameW
, KeyValuePartialInformation
,
424 data
, format_size
, &format_size
);
425 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)data
;
426 format
= HeapAlloc( GetProcessHeap(), 0, info
->DataLength
+ sizeof(WCHAR
) );
427 memcpy( format
, info
->Data
, info
->DataLength
);
428 format
[info
->DataLength
/ sizeof(WCHAR
)] = 0;
430 if (info
->Type
== REG_EXPAND_SZ
)
434 format_size
= ExpandEnvironmentStringsW( format
, NULL
, 0 );
435 tmp
= HeapAlloc( GetProcessHeap(), 0, format_size
* sizeof(WCHAR
));
436 ExpandEnvironmentStringsW( format
, tmp
, format_size
);
437 HeapFree( GetProcessHeap(), 0, format
);
440 HeapFree( GetProcessHeap(), 0, data
);
443 RtlInitUnicodeString( &nameW
, L
"Auto" );
444 if (!NtQueryValueKey( dbg_key
, &nameW
, KeyValuePartialInformation
,
445 buffer
, sizeof(buffer
)-sizeof(WCHAR
), &format_size
))
447 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
448 if (info
->Type
== REG_DWORD
) memcpy( &autostart
, info
->Data
, sizeof(DWORD
) );
449 else if (info
->Type
== REG_SZ
)
451 WCHAR
*str
= (WCHAR
*)info
->Data
;
452 str
[info
->DataLength
/sizeof(WCHAR
)] = 0;
453 autostart
= wcstol( str
, NULL
, 10 );
462 size_t format_size
= lstrlenW( format
) + 2*20;
463 cmdline
= HeapAlloc( GetProcessHeap(), 0, format_size
* sizeof(WCHAR
) );
464 swprintf( cmdline
, format_size
, format
, (long)GetCurrentProcessId(), (long)HandleToLong(event
) );
465 HeapFree( GetProcessHeap(), 0, format
);
469 cmdline
= HeapAlloc( GetProcessHeap(), 0, 80 * sizeof(WCHAR
) );
470 swprintf( cmdline
, 80, L
"winedbg --auto %ld %ld", (long)GetCurrentProcessId(), (long)HandleToLong(event
) );
475 HMODULE mod
= GetModuleHandleA( "user32.dll" );
476 MessageBoxA_funcptr pMessageBoxA
= NULL
;
478 if (mod
) pMessageBoxA
= (void *)GetProcAddress( mod
, "MessageBoxA" );
481 static const char msg
[] = ".\nDo you wish to debug it?";
483 format_exception_msg( epointers
, buffer
, sizeof(buffer
) - sizeof(msg
) );
484 strcat( buffer
, msg
);
485 if (pMessageBoxA( 0, buffer
, "Exception raised", MB_YESNO
| MB_ICONHAND
) == IDNO
)
487 TRACE( "Killing process\n" );
493 /* make WINEDEBUG empty in the environment */
494 env
= GetEnvironmentStringsW();
495 if (!TRACE_ON(winedbg
))
497 for (p
= env
; *p
; p
+= lstrlenW(p
) + 1)
499 if (!wcsncmp( p
, L
"WINEDEBUG=", 10 ))
501 WCHAR
*next
= p
+ lstrlenW(p
);
502 WCHAR
*end
= next
+ 1;
503 while (*end
) end
+= lstrlenW(end
) + 1;
504 memmove( p
+ 10, next
, end
+ 1 - next
);
510 TRACE( "Starting debugger %s\n", debugstr_w(cmdline
) );
511 memset( &startup
, 0, sizeof(startup
) );
512 startup
.cb
= sizeof(startup
);
513 startup
.dwFlags
= STARTF_USESHOWWINDOW
;
514 startup
.wShowWindow
= SW_SHOWNORMAL
;
515 ret
= CreateProcessW( NULL
, cmdline
, NULL
, NULL
, TRUE
, 0, env
, NULL
, &startup
, &info
);
516 FreeEnvironmentStringsW( env
);
520 /* wait for debugger to come up... */
522 CloseHandle( info
.hThread
);
524 handles
[1] = info
.hProcess
;
525 WaitForMultipleObjects( 2, handles
, FALSE
, INFINITE
);
526 CloseHandle( info
.hProcess
);
528 else ERR( "Couldn't start debugger %s (%d)\n"
529 "Read the Wine Developers Guide on how to set up winedbg or another debugger\n",
530 debugstr_w(cmdline
), GetLastError() );
532 HeapFree(GetProcessHeap(), 0, cmdline
);
536 /******************************************************************
537 * start_debugger_atomic
539 * starts the debugger in an atomic way:
540 * - either the debugger is not started and it is started
541 * - or the debugger has already been started by another thread
542 * - or the debugger couldn't be started
544 * returns TRUE for the two first conditions, FALSE for the last
546 static BOOL
start_debugger_atomic( EXCEPTION_POINTERS
*epointers
)
552 OBJECT_ATTRIBUTES attr
;
555 attr
.Length
= sizeof(attr
);
556 attr
.RootDirectory
= 0;
557 attr
.Attributes
= OBJ_INHERIT
;
558 attr
.ObjectName
= NULL
;
559 attr
.SecurityDescriptor
= NULL
;
560 attr
.SecurityQualityOfService
= NULL
;
562 /* ask for manual reset, so that once the debugger is started,
563 * every thread will know it */
564 NtCreateEvent( &event
, EVENT_ALL_ACCESS
, &attr
, NotificationEvent
, FALSE
);
565 if (InterlockedCompareExchangePointer( &once
, event
, 0 ) == 0)
567 /* ok, our event has been set... we're the winning thread */
568 BOOL ret
= start_debugger( epointers
, once
);
572 /* so that the other threads won't be stuck */
573 NtSetEvent( once
, NULL
);
578 /* someone beat us here... */
579 CloseHandle( event
);
582 /* and wait for the winner to have actually created the debugger */
583 WaitForSingleObject( once
, INFINITE
);
584 /* in fact, here, we only know that someone has tried to start the debugger,
585 * we'll know by reposting the exception if it has actually attached
586 * to the current process */
591 /*******************************************************************
592 * check_resource_write
594 * Check if the exception is a write attempt to the resource data.
595 * If yes, we unprotect the resources to let broken apps continue
596 * (Windows does this too).
598 static BOOL
check_resource_write( void *addr
)
603 MEMORY_BASIC_INFORMATION info
;
605 if (!VirtualQuery( addr
, &info
, sizeof(info
) )) return FALSE
;
606 if (info
.State
== MEM_FREE
|| !(info
.Type
& MEM_IMAGE
)) return FALSE
;
607 if (!(rsrc
= RtlImageDirectoryEntryToData( info
.AllocationBase
, TRUE
,
608 IMAGE_DIRECTORY_ENTRY_RESOURCE
, &size
)))
610 if (addr
< rsrc
|| (char *)addr
>= (char *)rsrc
+ size
) return FALSE
;
611 TRACE( "Broken app is writing to the resource data, enabling work-around\n" );
612 VirtualProtect( rsrc
, size
, PAGE_READWRITE
, &old_prot
);
617 /*******************************************************************
618 * UnhandledExceptionFilter (kernelbase.@)
620 LONG WINAPI
UnhandledExceptionFilter( EXCEPTION_POINTERS
*epointers
)
622 const EXCEPTION_RECORD
*rec
= epointers
->ExceptionRecord
;
624 if (rec
->ExceptionCode
== EXCEPTION_ACCESS_VIOLATION
&& rec
->NumberParameters
>= 2)
626 switch (rec
->ExceptionInformation
[0])
628 case EXCEPTION_WRITE_FAULT
:
629 if (check_resource_write( (void *)rec
->ExceptionInformation
[1] ))
630 return EXCEPTION_CONTINUE_EXECUTION
;
635 if (!NtCurrentTeb()->Peb
->BeingDebugged
)
637 if (rec
->ExceptionCode
== CONTROL_C_EXIT
)
639 /* do not launch the debugger on ^C, simply terminate the process */
640 TerminateProcess( GetCurrentProcess(), 1 );
645 LONG ret
= top_filter( epointers
);
646 if (ret
!= EXCEPTION_CONTINUE_SEARCH
) return ret
;
649 /* FIXME: Should check the current error mode */
651 if (!start_debugger_atomic( epointers
) || !NtCurrentTeb()->Peb
->BeingDebugged
)
652 return EXCEPTION_EXECUTE_HANDLER
;
654 return EXCEPTION_CONTINUE_SEARCH
;
658 /***********************************************************************
659 * WerGetFlags (kernelbase.@)
661 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerGetFlags( HANDLE process
, DWORD
*flags
)
663 FIXME( "(%p, %p) stub\n", process
, flags
);
668 /***********************************************************************
669 * WerRegisterFile (kernelbase.@)
671 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerRegisterFile( const WCHAR
*file
, WER_REGISTER_FILE_TYPE type
,
674 FIXME( "(%s, %d, %d) stub\n", debugstr_w(file
), type
, flags
);
679 /***********************************************************************
680 * WerRegisterMemoryBlock (kernelbase.@)
682 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerRegisterMemoryBlock( void *block
, DWORD size
)
684 FIXME( "(%p %d) stub\n", block
, size
);
689 /***********************************************************************
690 * WerRegisterRuntimeExceptionModule (kernelbase.@)
692 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerRegisterRuntimeExceptionModule( const WCHAR
*dll
, void *context
)
694 FIXME( "(%s, %p) stub\n", debugstr_w(dll
), context
);
699 /***********************************************************************
700 * WerSetFlags (kernelbase.@)
702 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerSetFlags( DWORD flags
)
704 FIXME("(%d) stub\n", flags
);
709 /***********************************************************************
710 * WerUnregisterFile (kernelbase.@)
712 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerUnregisterFile( const WCHAR
*file
)
714 FIXME( "(%s) stub\n", debugstr_w(file
) );
719 /***********************************************************************
720 * WerUnregisterMemoryBlock (kernelbase.@)
722 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerUnregisterMemoryBlock( void *block
)
724 FIXME( "(%p) stub\n", block
);
729 /***********************************************************************
730 * WerUnregisterRuntimeExceptionModule (kernelbase.@)
732 HRESULT WINAPI
/* DECLSPEC_HOTPATCH */ WerUnregisterRuntimeExceptionModule( const WCHAR
*dll
, void *context
)
734 FIXME( "(%s, %p) stub\n", debugstr_w(dll
), context
);
739 /***********************************************************************
741 ***********************************************************************/
744 typedef struct _LDR_DATA_TABLE_ENTRY32
746 LIST_ENTRY32 InLoadOrderModuleList
;
747 LIST_ENTRY32 InMemoryOrderModuleList
;
748 LIST_ENTRY32 InInitializationOrderModuleList
;
752 UNICODE_STRING32 FullDllName
;
753 UNICODE_STRING32 BaseDllName
;
754 } LDR_DATA_TABLE_ENTRY32
;
756 struct module_iterator
762 LDR_DATA_TABLE_ENTRY ldr_module
;
763 LDR_DATA_TABLE_ENTRY32 ldr_module32
;
767 static BOOL
init_module_iterator( struct module_iterator
*iter
, HANDLE process
)
769 PROCESS_BASIC_INFORMATION pbi
;
770 PPEB_LDR_DATA ldr_data
;
772 if (!IsWow64Process( process
, &iter
->wow64
)) return FALSE
;
774 /* get address of PEB */
775 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessBasicInformation
,
776 &pbi
, sizeof(pbi
), NULL
)))
779 if (is_win64
&& iter
->wow64
)
781 PEB_LDR_DATA32
*ldr_data32_ptr
;
782 DWORD ldr_data32
, first_module
;
785 peb32
= (PEB32
*)((char *)pbi
.PebBaseAddress
+ 0x1000);
786 if (!ReadProcessMemory( process
, &peb32
->LdrData
, &ldr_data32
, sizeof(ldr_data32
), NULL
))
788 ldr_data32_ptr
= (PEB_LDR_DATA32
*)(DWORD_PTR
) ldr_data32
;
789 if (!ReadProcessMemory( process
, &ldr_data32_ptr
->InLoadOrderModuleList
.Flink
,
790 &first_module
, sizeof(first_module
), NULL
))
792 iter
->head
= (LIST_ENTRY
*)&ldr_data32_ptr
->InLoadOrderModuleList
;
793 iter
->current
= (LIST_ENTRY
*)(DWORD_PTR
)first_module
;
794 iter
->process
= process
;
798 /* read address of LdrData from PEB */
799 if (!ReadProcessMemory( process
, &pbi
.PebBaseAddress
->LdrData
, &ldr_data
, sizeof(ldr_data
), NULL
))
802 /* read address of first module from LdrData */
803 if (!ReadProcessMemory( process
, &ldr_data
->InLoadOrderModuleList
.Flink
,
804 &iter
->current
, sizeof(iter
->current
), NULL
))
807 iter
->head
= &ldr_data
->InLoadOrderModuleList
;
808 iter
->process
= process
;
813 static int module_iterator_next( struct module_iterator
*iter
)
815 if (iter
->current
== iter
->head
) return 0;
817 if (is_win64
&& iter
->wow64
)
819 LIST_ENTRY32
*entry32
= (LIST_ENTRY32
*)iter
->current
;
821 if (!ReadProcessMemory( iter
->process
,
822 CONTAINING_RECORD(entry32
, LDR_DATA_TABLE_ENTRY32
, InLoadOrderModuleList
),
823 &iter
->ldr_module32
, sizeof(iter
->ldr_module32
), NULL
))
825 iter
->current
= (LIST_ENTRY
*)(DWORD_PTR
)iter
->ldr_module32
.InLoadOrderModuleList
.Flink
;
829 if (!ReadProcessMemory( iter
->process
,
830 CONTAINING_RECORD(iter
->current
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
),
831 &iter
->ldr_module
, sizeof(iter
->ldr_module
), NULL
))
834 iter
->current
= iter
->ldr_module
.InLoadOrderLinks
.Flink
;
839 static BOOL
get_ldr_module( HANDLE process
, HMODULE module
, LDR_DATA_TABLE_ENTRY
*ldr_module
)
841 struct module_iterator iter
;
844 if (!init_module_iterator( &iter
, process
)) return FALSE
;
846 while ((ret
= module_iterator_next( &iter
)) > 0)
847 /* When hModule is NULL we return the process image - which will be
848 * the first module since our iterator uses InLoadOrderModuleList */
849 if (!module
|| module
== iter
.ldr_module
.DllBase
)
851 *ldr_module
= iter
.ldr_module
;
855 if (ret
== 0) SetLastError( ERROR_INVALID_HANDLE
);
860 static BOOL
get_ldr_module32( HANDLE process
, HMODULE module
, LDR_DATA_TABLE_ENTRY32
*ldr_module
)
862 struct module_iterator iter
;
865 if (!init_module_iterator( &iter
, process
)) return FALSE
;
867 while ((ret
= module_iterator_next( &iter
)) > 0)
868 /* When hModule is NULL we return the process image - which will be
869 * the first module since our iterator uses InLoadOrderModuleList */
870 if (!module
|| (DWORD
)(DWORD_PTR
)module
== iter
.ldr_module32
.BaseAddress
)
872 *ldr_module
= iter
.ldr_module32
;
876 if (ret
== 0) SetLastError( ERROR_INVALID_HANDLE
);
881 /***********************************************************************
882 * EmptyWorkingSet (kernelbase.@)
883 * K32EmptyWorkingSet (kernelbase.@)
885 BOOL WINAPI DECLSPEC_HOTPATCH
EmptyWorkingSet( HANDLE process
)
887 return SetProcessWorkingSetSizeEx( process
, (SIZE_T
)-1, (SIZE_T
)-1, 0 );
891 /***********************************************************************
892 * EnumDeviceDrivers (kernelbase.@)
893 * K32EnumDeviceDrivers (kernelbase.@)
895 BOOL WINAPI
EnumDeviceDrivers( void **image_base
, DWORD count
, DWORD
*needed
)
897 FIXME( "(%p, %d, %p): stub\n", image_base
, count
, needed
);
898 if (needed
) *needed
= 0;
903 /***********************************************************************
904 * EnumPageFilesA (kernelbase.@)
905 * K32EnumPageFilesA (kernelbase.@)
907 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ EnumPageFilesA( PENUM_PAGE_FILE_CALLBACKA callback
, void *context
)
909 FIXME( "(%p, %p) stub\n", callback
, context
);
914 /***********************************************************************
915 * EnumPageFilesW (kernelbase.@)
916 * K32EnumPageFilesW (kernelbase.@)
918 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ EnumPageFilesW( PENUM_PAGE_FILE_CALLBACKW callback
, void *context
)
920 FIXME( "(%p, %p) stub\n", callback
, context
);
925 /***********************************************************************
926 * EnumProcessModules (kernelbase.@)
927 * K32EnumProcessModules (kernelbase.@)
929 BOOL WINAPI DECLSPEC_HOTPATCH
EnumProcessModules( HANDLE process
, HMODULE
*module
,
930 DWORD count
, DWORD
*needed
)
932 struct module_iterator iter
;
936 if (process
== GetCurrentProcess())
938 PPEB_LDR_DATA ldr_data
= NtCurrentTeb()->Peb
->LdrData
;
939 PLIST_ENTRY head
= &ldr_data
->InLoadOrderModuleList
;
940 PLIST_ENTRY entry
= head
->Flink
;
942 if (count
&& !module
)
944 SetLastError( ERROR_NOACCESS
);
947 while (entry
!= head
)
949 LDR_DATA_TABLE_ENTRY
*ldr
= CONTAINING_RECORD( entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
950 if (count
>= sizeof(HMODULE
))
952 *module
++ = ldr
->DllBase
;
953 count
-= sizeof(HMODULE
);
955 size
+= sizeof(HMODULE
);
956 entry
= entry
->Flink
;
960 SetLastError( ERROR_NOACCESS
);
967 if (!init_module_iterator( &iter
, process
)) return FALSE
;
969 if (count
&& !module
)
971 SetLastError( ERROR_NOACCESS
);
975 while ((ret
= module_iterator_next( &iter
)) > 0)
977 if (count
>= sizeof(HMODULE
))
979 if (sizeof(void *) == 8 && iter
.wow64
)
980 *module
++ = (HMODULE
) (DWORD_PTR
)iter
.ldr_module32
.BaseAddress
;
982 *module
++ = iter
.ldr_module
.DllBase
;
983 count
-= sizeof(HMODULE
);
985 size
+= sizeof(HMODULE
);
990 SetLastError( ERROR_NOACCESS
);
998 /***********************************************************************
999 * EnumProcessModulesEx (kernelbase.@)
1000 * K32EnumProcessModulesEx (kernelbase.@)
1002 BOOL WINAPI
EnumProcessModulesEx( HANDLE process
, HMODULE
*module
, DWORD count
,
1003 DWORD
*needed
, DWORD filter
)
1005 FIXME( "(%p, %p, %d, %p, %d) semi-stub\n", process
, module
, count
, needed
, filter
);
1006 return EnumProcessModules( process
, module
, count
, needed
);
1010 /***********************************************************************
1011 * EnumProcesses (kernelbase.@)
1012 * K32EnumProcesses (kernelbase.@)
1014 BOOL WINAPI
EnumProcesses( DWORD
*ids
, DWORD count
, DWORD
*used
)
1016 SYSTEM_PROCESS_INFORMATION
*spi
;
1017 ULONG size
= 0x4000;
1024 HeapFree( GetProcessHeap(), 0, buf
);
1025 if (!(buf
= HeapAlloc( GetProcessHeap(), 0, size
))) return FALSE
;
1026 status
= NtQuerySystemInformation( SystemProcessInformation
, buf
, size
, NULL
);
1027 } while (status
== STATUS_INFO_LENGTH_MISMATCH
);
1029 if (!set_ntstatus( status
))
1031 HeapFree( GetProcessHeap(), 0, buf
);
1035 for (*used
= 0; count
>= sizeof(DWORD
); count
-= sizeof(DWORD
))
1037 *ids
++ = HandleToUlong( spi
->UniqueProcessId
);
1038 *used
+= sizeof(DWORD
);
1039 if (spi
->NextEntryOffset
== 0) break;
1040 spi
= (SYSTEM_PROCESS_INFORMATION
*)(((PCHAR
)spi
) + spi
->NextEntryOffset
);
1042 HeapFree( GetProcessHeap(), 0, buf
);
1047 /***********************************************************************
1048 * GetDeviceDriverBaseNameA (kernelbase.@)
1049 * K32GetDeviceDriverBaseNameA (kernelbase.@)
1051 DWORD WINAPI DECLSPEC_HOTPATCH
GetDeviceDriverBaseNameA( void *image_base
, char *name
, DWORD size
)
1053 FIXME( "(%p, %p, %d): stub\n", image_base
, name
, size
);
1054 if (name
&& size
) name
[0] = 0;
1059 /***********************************************************************
1060 * GetDeviceDriverBaseNameW (kernelbase.@)
1061 * K32GetDeviceDriverBaseNameW (kernelbase.@)
1063 DWORD WINAPI DECLSPEC_HOTPATCH
GetDeviceDriverBaseNameW( void *image_base
, WCHAR
*name
, DWORD size
)
1065 FIXME( "(%p, %p, %d): stub\n", image_base
, name
, size
);
1066 if (name
&& size
) name
[0] = 0;
1071 /***********************************************************************
1072 * GetDeviceDriverFileNameA (kernelbase.@)
1073 * K32GetDeviceDriverFileNameA (kernelbase.@)
1075 DWORD WINAPI DECLSPEC_HOTPATCH
GetDeviceDriverFileNameA( void *image_base
, char *name
, DWORD size
)
1077 FIXME( "(%p, %p, %d): stub\n", image_base
, name
, size
);
1078 if (name
&& size
) name
[0] = 0;
1083 /***********************************************************************
1084 * GetDeviceDriverFileNameW (kernelbase.@)
1085 * K32GetDeviceDriverFileNameW (kernelbase.@)
1087 DWORD WINAPI DECLSPEC_HOTPATCH
GetDeviceDriverFileNameW( void *image_base
, WCHAR
*name
, DWORD size
)
1089 FIXME( "(%p, %p, %d): stub\n", image_base
, name
, size
);
1090 if (name
&& size
) name
[0] = 0;
1095 /***********************************************************************
1096 * GetMappedFileNameA (kernelbase.@)
1097 * K32GetMappedFileNameA (kernelbase.@)
1099 DWORD WINAPI DECLSPEC_HOTPATCH
GetMappedFileNameA( HANDLE process
, void *addr
, char *name
, DWORD size
)
1101 WCHAR nameW
[MAX_PATH
];
1106 SetLastError( ERROR_INVALID_PARAMETER
);
1109 if (!GetMappedFileNameW( process
, addr
, nameW
, MAX_PATH
)) return 0;
1112 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1115 len
= file_name_WtoA( nameW
, wcslen(nameW
), name
, size
);
1116 name
[min(len
, size
- 1)] = 0;
1121 /***********************************************************************
1122 * GetMappedFileNameW (kernelbase.@)
1123 * K32GetMappedFileNameW (kernelbase.@)
1125 DWORD WINAPI DECLSPEC_HOTPATCH
GetMappedFileNameW( HANDLE process
, void *addr
, WCHAR
*name
, DWORD size
)
1127 ULONG_PTR buffer
[(sizeof(MEMORY_SECTION_NAME
) + MAX_PATH
* sizeof(WCHAR
)) / sizeof(ULONG_PTR
)];
1128 MEMORY_SECTION_NAME
*mem
= (MEMORY_SECTION_NAME
*)buffer
;
1133 SetLastError( ERROR_INVALID_PARAMETER
);
1136 if (!set_ntstatus( NtQueryVirtualMemory( process
, addr
, MemorySectionName
, mem
, sizeof(buffer
), NULL
)))
1139 len
= mem
->SectionFileName
.Length
/ sizeof(WCHAR
);
1140 memcpy( name
, mem
->SectionFileName
.Buffer
, min( mem
->SectionFileName
.Length
, size
* sizeof(WCHAR
) ));
1141 if (len
>= size
) SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1142 name
[min(len
, size
- 1)] = 0;
1147 /***********************************************************************
1148 * GetModuleBaseNameA (kernelbase.@)
1149 * K32GetModuleBaseNameA (kernelbase.@)
1151 DWORD WINAPI DECLSPEC_HOTPATCH
GetModuleBaseNameA( HANDLE process
, HMODULE module
,
1152 char *name
, DWORD size
)
1159 SetLastError( ERROR_INVALID_PARAMETER
);
1162 if (!(name_w
= HeapAlloc( GetProcessHeap(), 0, sizeof(WCHAR
) * size
))) return 0;
1164 len
= GetModuleBaseNameW( process
, module
, name_w
, size
);
1165 TRACE( "%d, %s\n", len
, debugstr_w(name_w
) );
1168 ret
= WideCharToMultiByte( CP_ACP
, 0, name_w
, len
, name
, size
, NULL
, NULL
);
1169 if (ret
< size
) name
[ret
] = 0;
1171 HeapFree( GetProcessHeap(), 0, name_w
);
1176 /***********************************************************************
1177 * GetModuleBaseNameW (kernelbase.@)
1178 * K32GetModuleBaseNameW (kernelbase.@)
1180 DWORD WINAPI DECLSPEC_HOTPATCH
GetModuleBaseNameW( HANDLE process
, HMODULE module
,
1181 WCHAR
*name
, DWORD size
)
1185 if (!IsWow64Process( process
, &wow64
)) return 0;
1187 if (is_win64
&& wow64
)
1189 LDR_DATA_TABLE_ENTRY32 ldr_module32
;
1191 if (!get_ldr_module32(process
, module
, &ldr_module32
)) return 0;
1192 size
= min( ldr_module32
.BaseDllName
.Length
/ sizeof(WCHAR
), size
);
1193 if (!ReadProcessMemory( process
, (void *)(DWORD_PTR
)ldr_module32
.BaseDllName
.Buffer
,
1194 name
, size
* sizeof(WCHAR
), NULL
))
1199 LDR_DATA_TABLE_ENTRY ldr_module
;
1201 if (!get_ldr_module( process
, module
, &ldr_module
)) return 0;
1202 size
= min( ldr_module
.BaseDllName
.Length
/ sizeof(WCHAR
), size
);
1203 if (!ReadProcessMemory( process
, ldr_module
.BaseDllName
.Buffer
,
1204 name
, size
* sizeof(WCHAR
), NULL
))
1212 /***********************************************************************
1213 * GetModuleFileNameExA (kernelbase.@)
1214 * K32GetModuleFileNameExA (kernelbase.@)
1216 DWORD WINAPI DECLSPEC_HOTPATCH
GetModuleFileNameExA( HANDLE process
, HMODULE module
,
1217 char *name
, DWORD size
)
1222 TRACE( "(process=%p, module=%p, %p, %d)\n", process
, module
, name
, size
);
1226 SetLastError( ERROR_INVALID_PARAMETER
);
1229 if (process
== GetCurrentProcess())
1231 len
= GetModuleFileNameA( module
, name
, size
);
1232 name
[size
- 1] = '\0';
1236 if (!(ptr
= HeapAlloc( GetProcessHeap(), 0, size
* sizeof(WCHAR
) ))) return 0;
1237 len
= GetModuleFileNameExW( process
, module
, ptr
, size
);
1244 if (!WideCharToMultiByte( CP_ACP
, 0, ptr
, -1, name
, size
, NULL
, NULL
))
1249 else if (len
< size
) len
= strlen( name
);
1251 HeapFree( GetProcessHeap(), 0, ptr
);
1256 /***********************************************************************
1257 * GetModuleFileNameExW (kernelbase.@)
1258 * K32GetModuleFileNameExW (kernelbase.@)
1260 DWORD WINAPI DECLSPEC_HOTPATCH
GetModuleFileNameExW( HANDLE process
, HMODULE module
,
1261 WCHAR
*name
, DWORD size
)
1266 if (!size
) return 0;
1268 if (!IsWow64Process( process
, &wow64
)) return 0;
1270 if (is_win64
&& wow64
)
1272 LDR_DATA_TABLE_ENTRY32 ldr_module32
;
1274 if (!get_ldr_module32( process
, module
, &ldr_module32
)) return 0;
1275 len
= ldr_module32
.FullDllName
.Length
/ sizeof(WCHAR
);
1276 if (!ReadProcessMemory( process
, (void *)(DWORD_PTR
)ldr_module32
.FullDllName
.Buffer
,
1277 name
, min( len
, size
) * sizeof(WCHAR
), NULL
))
1282 LDR_DATA_TABLE_ENTRY ldr_module
;
1284 if (!get_ldr_module(process
, module
, &ldr_module
)) return 0;
1285 len
= ldr_module
.FullDllName
.Length
/ sizeof(WCHAR
);
1286 if (!ReadProcessMemory( process
, ldr_module
.FullDllName
.Buffer
,
1287 name
, min( len
, size
) * sizeof(WCHAR
), NULL
))
1304 /***********************************************************************
1305 * GetModuleInformation (kernelbase.@)
1306 * K32GetModuleInformation (kernelbase.@)
1308 BOOL WINAPI
GetModuleInformation( HANDLE process
, HMODULE module
, MODULEINFO
*modinfo
, DWORD count
)
1312 if (count
< sizeof(MODULEINFO
))
1314 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1318 if (!IsWow64Process( process
, &wow64
)) return FALSE
;
1320 if (is_win64
&& wow64
)
1322 LDR_DATA_TABLE_ENTRY32 ldr_module32
;
1324 if (!get_ldr_module32( process
, module
, &ldr_module32
)) return FALSE
;
1325 modinfo
->lpBaseOfDll
= (void *)(DWORD_PTR
)ldr_module32
.BaseAddress
;
1326 modinfo
->SizeOfImage
= ldr_module32
.SizeOfImage
;
1327 modinfo
->EntryPoint
= (void *)(DWORD_PTR
)ldr_module32
.EntryPoint
;
1331 LDR_DATA_TABLE_ENTRY ldr_module
;
1333 if (!get_ldr_module( process
, module
, &ldr_module
)) return FALSE
;
1334 modinfo
->lpBaseOfDll
= ldr_module
.DllBase
;
1335 modinfo
->SizeOfImage
= ldr_module
.SizeOfImage
;
1336 modinfo
->EntryPoint
= ldr_module
.EntryPoint
;
1342 /***********************************************************************
1343 * GetPerformanceInfo (kernelbase.@)
1344 * K32GetPerformanceInfo (kernelbase.@)
1346 BOOL WINAPI DECLSPEC_HOTPATCH
GetPerformanceInfo( PPERFORMANCE_INFORMATION info
, DWORD size
)
1348 SYSTEM_PERFORMANCE_INFORMATION perf
;
1349 SYSTEM_BASIC_INFORMATION basic
;
1350 SYSTEM_PROCESS_INFORMATION
*process
, *spi
;
1354 TRACE( "(%p, %d)\n", info
, size
);
1356 if (size
< sizeof(*info
))
1358 SetLastError( ERROR_BAD_LENGTH
);
1362 status
= NtQuerySystemInformation( SystemPerformanceInformation
, &perf
, sizeof(perf
), NULL
);
1363 if (!set_ntstatus( status
)) return FALSE
;
1364 status
= NtQuerySystemInformation( SystemBasicInformation
, &basic
, sizeof(basic
), NULL
);
1365 if (!set_ntstatus( status
)) return FALSE
;
1367 info
->cb
= sizeof(*info
);
1368 info
->CommitTotal
= perf
.TotalCommittedPages
;
1369 info
->CommitLimit
= perf
.TotalCommitLimit
;
1370 info
->CommitPeak
= perf
.PeakCommitment
;
1371 info
->PhysicalTotal
= basic
.MmNumberOfPhysicalPages
;
1372 info
->PhysicalAvailable
= perf
.AvailablePages
;
1373 info
->SystemCache
= 0;
1374 info
->KernelTotal
= perf
.PagedPoolUsage
+ perf
.NonPagedPoolUsage
;
1375 info
->KernelPaged
= perf
.PagedPoolUsage
;
1376 info
->KernelNonpaged
= perf
.NonPagedPoolUsage
;
1377 info
->PageSize
= basic
.PageSize
;
1379 /* fields from SYSTEM_PROCESS_INFORMATION */
1380 NtQuerySystemInformation( SystemProcessInformation
, NULL
, 0, &info_size
);
1383 process
= HeapAlloc( GetProcessHeap(), 0, info_size
);
1386 SetLastError( ERROR_OUTOFMEMORY
);
1389 status
= NtQuerySystemInformation( SystemProcessInformation
, process
, info_size
, &info_size
);
1391 HeapFree( GetProcessHeap(), 0, process
);
1392 if (status
!= STATUS_INFO_LENGTH_MISMATCH
)
1394 SetLastError( RtlNtStatusToDosError( status
) );
1398 info
->HandleCount
= info
->ProcessCount
= info
->ThreadCount
= 0;
1402 info
->ProcessCount
++;
1403 info
->HandleCount
+= spi
->HandleCount
;
1404 info
->ThreadCount
+= spi
->dwThreadCount
;
1405 if (spi
->NextEntryOffset
== 0) break;
1406 spi
= (SYSTEM_PROCESS_INFORMATION
*)((char *)spi
+ spi
->NextEntryOffset
);
1408 HeapFree( GetProcessHeap(), 0, process
);
1413 /***********************************************************************
1414 * GetProcessImageFileNameA (kernelbase.@)
1415 * K32GetProcessImageFileNameA (kernelbase.@)
1417 DWORD WINAPI DECLSPEC_HOTPATCH
GetProcessImageFileNameA( HANDLE process
, char *file
, DWORD size
)
1419 return QueryFullProcessImageNameA( process
, PROCESS_NAME_NATIVE
, file
, &size
) ? size
: 0;
1423 /***********************************************************************
1424 * GetProcessImageFileNameW (kernelbase.@)
1425 * K32GetProcessImageFileNameW (kernelbase.@)
1427 DWORD WINAPI DECLSPEC_HOTPATCH
GetProcessImageFileNameW( HANDLE process
, WCHAR
*file
, DWORD size
)
1429 return QueryFullProcessImageNameW( process
, PROCESS_NAME_NATIVE
, file
, &size
) ? size
: 0;
1433 /***********************************************************************
1434 * GetProcessMemoryInfo (kernelbase.@)
1435 * K32GetProcessMemoryInfo (kernelbase.@)
1437 BOOL WINAPI DECLSPEC_HOTPATCH
GetProcessMemoryInfo( HANDLE process
, PROCESS_MEMORY_COUNTERS
*pmc
,
1442 if (count
< sizeof(PROCESS_MEMORY_COUNTERS
))
1444 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
1448 if (!set_ntstatus( NtQueryInformationProcess( process
, ProcessVmCounters
, &vmc
, sizeof(vmc
), NULL
)))
1451 pmc
->cb
= sizeof(PROCESS_MEMORY_COUNTERS
);
1452 pmc
->PageFaultCount
= vmc
.PageFaultCount
;
1453 pmc
->PeakWorkingSetSize
= vmc
.PeakWorkingSetSize
;
1454 pmc
->WorkingSetSize
= vmc
.WorkingSetSize
;
1455 pmc
->QuotaPeakPagedPoolUsage
= vmc
.QuotaPeakPagedPoolUsage
;
1456 pmc
->QuotaPagedPoolUsage
= vmc
.QuotaPagedPoolUsage
;
1457 pmc
->QuotaPeakNonPagedPoolUsage
= vmc
.QuotaPeakNonPagedPoolUsage
;
1458 pmc
->QuotaNonPagedPoolUsage
= vmc
.QuotaNonPagedPoolUsage
;
1459 pmc
->PagefileUsage
= vmc
.PagefileUsage
;
1460 pmc
->PeakPagefileUsage
= vmc
.PeakPagefileUsage
;
1465 /***********************************************************************
1466 * GetWsChanges (kernelbase.@)
1467 * K32GetWsChanges (kernelbase.@)
1469 BOOL WINAPI DECLSPEC_HOTPATCH
GetWsChanges( HANDLE process
, PSAPI_WS_WATCH_INFORMATION
*info
, DWORD size
)
1471 TRACE( "(%p, %p, %d)\n", process
, info
, size
);
1472 return set_ntstatus( NtQueryInformationProcess( process
, ProcessWorkingSetWatch
, info
, size
, NULL
));
1476 /***********************************************************************
1477 * GetWsChangesEx (kernelbase.@)
1478 * K32GetWsChangesEx (kernelbase.@)
1480 BOOL WINAPI DECLSPEC_HOTPATCH
GetWsChangesEx( HANDLE process
, PSAPI_WS_WATCH_INFORMATION_EX
*info
,
1483 FIXME( "(%p, %p, %p)\n", process
, info
, size
);
1484 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1489 /***********************************************************************
1490 * InitializeProcessForWsWatch (kernelbase.@)
1491 * K32InitializeProcessForWsWatch (kernelbase.@)
1493 BOOL WINAPI
/* DECLSPEC_HOTPATCH */ InitializeProcessForWsWatch( HANDLE process
)
1495 FIXME( "(process=%p): stub\n", process
);
1500 /***********************************************************************
1501 * QueryWorkingSet (kernelbase.@)
1502 * K32QueryWorkingSet (kernelbase.@)
1504 BOOL WINAPI DECLSPEC_HOTPATCH
QueryWorkingSet( HANDLE process
, void *buffer
, DWORD size
)
1506 TRACE( "(%p, %p, %d)\n", process
, buffer
, size
);
1507 return set_ntstatus( NtQueryVirtualMemory( process
, NULL
, MemoryWorkingSetList
, buffer
, size
, NULL
));
1511 /***********************************************************************
1512 * QueryWorkingSetEx (kernelbase.@)
1513 * K32QueryWorkingSetEx (kernelbase.@)
1515 BOOL WINAPI
QueryWorkingSetEx( HANDLE process
, void *buffer
, DWORD size
)
1517 TRACE( "(%p, %p, %d)\n", process
, buffer
, size
);
1518 return set_ntstatus( NtQueryVirtualMemory( process
, NULL
, MemoryWorkingSetExInformation
,
1519 buffer
, size
, NULL
));
1523 /******************************************************************
1524 * QueryFullProcessImageNameA (kernelbase.@)
1526 BOOL WINAPI DECLSPEC_HOTPATCH
QueryFullProcessImageNameA( HANDLE process
, DWORD flags
,
1527 char *name
, DWORD
*size
)
1530 DWORD sizeW
= *size
;
1531 WCHAR
*nameW
= HeapAlloc( GetProcessHeap(), 0, *size
* sizeof(WCHAR
) );
1533 ret
= QueryFullProcessImageNameW( process
, flags
, nameW
, &sizeW
);
1534 if (ret
) ret
= (WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, name
, *size
, NULL
, NULL
) > 0);
1535 if (ret
) *size
= strlen( name
);
1536 HeapFree( GetProcessHeap(), 0, nameW
);
1541 /******************************************************************
1542 * QueryFullProcessImageNameW (kernelbase.@)
1544 BOOL WINAPI DECLSPEC_HOTPATCH
QueryFullProcessImageNameW( HANDLE process
, DWORD flags
,
1545 WCHAR
*name
, DWORD
*size
)
1547 BYTE buffer
[sizeof(UNICODE_STRING
) + MAX_PATH
*sizeof(WCHAR
)]; /* this buffer should be enough */
1548 UNICODE_STRING
*dynamic_buffer
= NULL
;
1549 UNICODE_STRING
*result
= NULL
;
1553 /* FIXME: Use ProcessImageFileName for the PROCESS_NAME_NATIVE case */
1554 status
= NtQueryInformationProcess( process
, ProcessImageFileNameWin32
, buffer
,
1555 sizeof(buffer
) - sizeof(WCHAR
), &needed
);
1556 if (status
== STATUS_INFO_LENGTH_MISMATCH
)
1558 dynamic_buffer
= HeapAlloc( GetProcessHeap(), 0, needed
+ sizeof(WCHAR
) );
1559 status
= NtQueryInformationProcess( process
, ProcessImageFileNameWin32
, dynamic_buffer
,
1561 result
= dynamic_buffer
;
1564 result
= (UNICODE_STRING
*)buffer
;
1566 if (status
) goto cleanup
;
1568 if (flags
& PROCESS_NAME_NATIVE
)
1572 DWORD ntlen
, devlen
;
1574 if (result
->Buffer
[1] != ':' || result
->Buffer
[0] < 'A' || result
->Buffer
[0] > 'Z')
1576 /* We cannot convert it to an NT device path so fail */
1577 status
= STATUS_NO_SUCH_DEVICE
;
1581 /* Find this drive's NT device path */
1582 drive
[0] = result
->Buffer
[0];
1585 if (!QueryDosDeviceW(drive
, device
, ARRAY_SIZE(device
)))
1587 status
= STATUS_NO_SUCH_DEVICE
;
1591 devlen
= lstrlenW(device
);
1592 ntlen
= devlen
+ (result
->Length
/sizeof(WCHAR
) - 2);
1593 if (ntlen
+ 1 > *size
)
1595 status
= STATUS_BUFFER_TOO_SMALL
;
1600 memcpy( name
, device
, devlen
* sizeof(*device
) );
1601 memcpy( name
+ devlen
, result
->Buffer
+ 2, result
->Length
- 2 * sizeof(WCHAR
) );
1603 TRACE( "NT path: %s\n", debugstr_w(name
) );
1607 if (result
->Length
/sizeof(WCHAR
) + 1 > *size
)
1609 status
= STATUS_BUFFER_TOO_SMALL
;
1613 *size
= result
->Length
/sizeof(WCHAR
);
1614 memcpy( name
, result
->Buffer
, result
->Length
);
1619 HeapFree( GetProcessHeap(), 0, dynamic_buffer
);
1620 return set_ntstatus( status
);