winegstreamer: Move the "flip" field to struct wg_parser_stream.
[wine/zf.git] / dlls / kernelbase / debug.c
blob8f8389ac372a29ea78e5e4794af66592843e2261
1 /*
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
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
25 #include "ntstatus.h"
26 #define WIN32_NO_STATUS
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winternl.h"
30 #include "winnls.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "psapi.h"
34 #include "werapi.h"
36 #include "wine/exception.h"
37 #include "wine/asm.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 )
56 DWORD_PTR port;
58 if (!process || !present)
60 SetLastError( ERROR_INVALID_PARAMETER );
61 return FALSE;
63 if (!set_ntstatus( NtQueryInformationProcess( process, ProcessDebugPort, &port, sizeof(port), NULL )))
64 return FALSE;
65 *present = !!port;
66 return TRUE;
70 /**********************************************************************
71 * ContinueDebugEvent (kernelbase.@)
73 BOOL WINAPI DECLSPEC_HOTPATCH ContinueDebugEvent( DWORD pid, DWORD tid, DWORD status )
75 CLIENT_ID id;
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 )
88 HANDLE process;
89 NTSTATUS status;
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 )))
94 return FALSE;
95 status = DbgUiDebugActiveProcess( process );
96 NtClose( process );
97 return set_ntstatus( status );
101 /**********************************************************************
102 * DebugActiveProcessStop (kernelbase.@)
104 BOOL WINAPI DECLSPEC_HOTPATCH DebugActiveProcessStop( DWORD pid )
106 HANDLE process;
107 NTSTATUS status;
109 if (!(process = OpenProcess( PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_SUSPEND_RESUME, FALSE, pid )))
110 return FALSE;
111 status = DbgUiStopDebugging( process );
112 NtClose( 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) )
122 #else
123 void WINAPI DebugBreak(void)
125 DbgBreakPoint();
127 #endif
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;
184 if (!str) str = "";
185 WARN( "%s\n", debugstr_a(str) );
187 /* raise exception, WaitForDebugEvent() will generate a corresponding debug event */
188 __TRY
190 ULONG_PTR args[2];
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;
199 __ENDTRY
200 if (caught_by_dbg) return;
202 /* send string to a system-wide monitor */
203 if (!mutex_inited)
205 /* first call to OutputDebugString, initialize mutex handle */
206 HANDLE mutex = CreateMutexExW( NULL, L"DBWinMutex", 0, SYNCHRONIZE );
207 if (mutex)
209 if (InterlockedCompareExchangePointer( &DBWinMutex, mutex, 0 ) != 0)
210 /* someone beat us here... */
211 CloseHandle( mutex );
213 mutex_inited = TRUE;
216 if (DBWinMutex)
218 HANDLE mapping;
220 mapping = OpenFileMappingW( FILE_MAP_WRITE, FALSE, L"DBWIN_BUFFER" );
221 if (mapping)
223 LPVOID 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 );
239 struct _mon_buffer_t
241 DWORD pid;
242 char buffer[1];
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 )
270 UNICODE_STRING strW;
271 STRING strA;
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;
293 if (count && args)
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;
322 int len;
324 switch(rec->ExceptionCode)
326 case EXCEPTION_INT_DIVIDE_BY_ZERO:
327 len = snprintf( buffer, size, "Unhandled division by zero" );
328 break;
329 case EXCEPTION_INT_OVERFLOW:
330 len = snprintf( buffer, size, "Unhandled overflow" );
331 break;
332 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
333 len = snprintf( buffer, size, "Unhandled array bounds" );
334 break;
335 case EXCEPTION_ILLEGAL_INSTRUCTION:
336 len = snprintf( buffer, size, "Unhandled illegal instruction" );
337 break;
338 case EXCEPTION_STACK_OVERFLOW:
339 len = snprintf( buffer, size, "Unhandled stack overflow" );
340 break;
341 case EXCEPTION_PRIV_INSTRUCTION:
342 len = snprintf( buffer, size, "Unhandled privileged instruction" );
343 break;
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]);
350 else
351 len = snprintf( buffer, size, "Unhandled page fault");
352 break;
353 case EXCEPTION_DATATYPE_MISALIGNMENT:
354 len = snprintf( buffer, size, "Unhandled alignment" );
355 break;
356 case CONTROL_C_EXIT:
357 len = snprintf( buffer, size, "Unhandled ^C");
358 break;
359 case STATUS_POSSIBLE_DEADLOCK:
360 len = snprintf( buffer, size, "Critical section %p wait failed",
361 (void *)rec->ExceptionInformation[0]);
362 break;
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] );
367 else
368 len = snprintf( buffer, size, "Unimplemented function %s.%ld called",
369 (char *)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
370 break;
371 case EXCEPTION_WINE_ASSERTION:
372 len = snprintf( buffer, size, "Assertion failed" );
373 break;
374 default:
375 len = snprintf( buffer, size, "Unhandled exception 0x%08x in thread %x",
376 rec->ExceptionCode, GetCurrentThreadId());
377 break;
379 if (len < 0 || len >= size) return;
380 snprintf( buffer + len, size - len, " at address %p", ptr->ExceptionRecord->ExceptionAddress );
384 /******************************************************************
385 * start_debugger
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;
394 HANDLE dbg_key;
395 DWORD autostart = TRUE;
396 PROCESS_INFORMATION info;
397 STARTUPINFOW startup;
398 BOOL ret = FALSE;
399 char buffer[256];
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;
407 attr.Attributes = 0;
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)
431 WCHAR *tmp;
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 );
437 format = tmp;
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 );
456 NtClose( dbg_key );
459 if (format)
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 );
466 else
468 cmdline = HeapAlloc( GetProcessHeap(), 0, 80 * sizeof(WCHAR) );
469 swprintf( cmdline, 80, L"winedbg --auto %ld %ld", (long)GetCurrentProcessId(), (long)HandleToLong(event) );
472 if (!autostart)
474 HMODULE mod = GetModuleHandleA( "user32.dll" );
475 MessageBoxA_funcptr pMessageBoxA = NULL;
477 if (mod) pMessageBoxA = (void *)GetProcAddress( mod, "MessageBoxA" );
478 if (pMessageBoxA)
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" );
487 goto exit;
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 );
504 break;
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 );
517 if (ret)
519 /* wait for debugger to come up... */
520 HANDLE handles[2];
521 CloseHandle( info.hThread );
522 handles[0] = event;
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() );
530 exit:
531 HeapFree(GetProcessHeap(), 0, cmdline);
532 return ret;
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 )
547 static HANDLE once;
549 if (once == 0)
551 OBJECT_ATTRIBUTES attr;
552 HANDLE event;
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 );
569 if (!ret)
571 /* so that the other threads won't be stuck */
572 NtSetEvent( once, NULL );
574 return ret;
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 */
586 return TRUE;
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 )
599 DWORD old_prot;
600 void *rsrc;
601 DWORD size;
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 )))
608 return FALSE;
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 );
612 return TRUE;
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;
630 break;
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 );
642 if (top_filter)
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 );
663 return E_NOTIMPL;
667 /***********************************************************************
668 * WerRegisterFile (kernelbase.@)
670 HRESULT WINAPI /* DECLSPEC_HOTPATCH */ WerRegisterFile( const WCHAR *file, WER_REGISTER_FILE_TYPE type,
671 DWORD flags )
673 FIXME( "(%s, %d, %d) stub\n", debugstr_w(file), type, flags );
674 return E_NOTIMPL;
678 /***********************************************************************
679 * WerRegisterMemoryBlock (kernelbase.@)
681 HRESULT WINAPI /* DECLSPEC_HOTPATCH */ WerRegisterMemoryBlock( void *block, DWORD size )
683 FIXME( "(%p %d) stub\n", block, size );
684 return E_NOTIMPL;
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 );
694 return S_OK;
698 /***********************************************************************
699 * WerSetFlags (kernelbase.@)
701 HRESULT WINAPI /* DECLSPEC_HOTPATCH */ WerSetFlags( DWORD flags )
703 FIXME("(%d) stub\n", flags);
704 return S_OK;
708 /***********************************************************************
709 * WerUnregisterFile (kernelbase.@)
711 HRESULT WINAPI /* DECLSPEC_HOTPATCH */ WerUnregisterFile( const WCHAR *file )
713 FIXME( "(%s) stub\n", debugstr_w(file) );
714 return E_NOTIMPL;
718 /***********************************************************************
719 * WerUnregisterMemoryBlock (kernelbase.@)
721 HRESULT WINAPI /* DECLSPEC_HOTPATCH */ WerUnregisterMemoryBlock( void *block )
723 FIXME( "(%p) stub\n", block );
724 return E_NOTIMPL;
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 );
734 return S_OK;
738 /***********************************************************************
739 * psapi functions
740 ***********************************************************************/
743 typedef struct _PEB32
745 BOOLEAN InheritedAddressSpace;
746 BOOLEAN ReadImageFileExecOptions;
747 BOOLEAN BeingDebugged;
748 BOOLEAN SpareBool;
749 DWORD Mutant;
750 DWORD ImageBaseAddress;
751 DWORD LdrData;
752 } PEB32;
754 typedef struct _LIST_ENTRY32
756 DWORD Flink;
757 DWORD Blink;
758 } LIST_ENTRY32;
760 typedef struct _PEB_LDR_DATA32
762 ULONG Length;
763 BOOLEAN Initialized;
764 DWORD SsHandle;
765 LIST_ENTRY32 InLoadOrderModuleList;
766 } PEB_LDR_DATA32;
768 typedef struct _UNICODE_STRING32
770 USHORT Length;
771 USHORT MaximumLength;
772 DWORD Buffer;
773 } UNICODE_STRING32;
775 typedef struct _LDR_DATA_TABLE_ENTRY32
777 LIST_ENTRY32 InLoadOrderModuleList;
778 LIST_ENTRY32 InMemoryOrderModuleList;
779 LIST_ENTRY32 InInitializationOrderModuleList;
780 DWORD BaseAddress;
781 DWORD EntryPoint;
782 ULONG SizeOfImage;
783 UNICODE_STRING32 FullDllName;
784 UNICODE_STRING32 BaseDllName;
785 } LDR_DATA_TABLE_ENTRY32;
787 struct module_iterator
789 HANDLE process;
790 LIST_ENTRY *head;
791 LIST_ENTRY *current;
792 BOOL wow64;
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 )))
808 return FALSE;
810 if (is_win64 && iter->wow64)
812 PEB_LDR_DATA32 *ldr_data32_ptr;
813 DWORD ldr_data32, first_module;
814 PEB32 *peb32;
816 peb32 = (PEB32 *)(DWORD_PTR)pbi.PebBaseAddress;
817 if (!ReadProcessMemory( process, &peb32->LdrData, &ldr_data32, sizeof(ldr_data32), NULL ))
818 return FALSE;
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 ))
822 return FALSE;
823 iter->head = (LIST_ENTRY *)&ldr_data32_ptr->InLoadOrderModuleList;
824 iter->current = (LIST_ENTRY *)(DWORD_PTR)first_module;
825 iter->process = process;
826 return TRUE;
829 /* read address of LdrData from PEB */
830 if (!ReadProcessMemory( process, &pbi.PebBaseAddress->LdrData, &ldr_data, sizeof(ldr_data), NULL ))
831 return FALSE;
833 /* read address of first module from LdrData */
834 if (!ReadProcessMemory( process, &ldr_data->InLoadOrderModuleList.Flink,
835 &iter->current, sizeof(iter->current), NULL ))
836 return FALSE;
838 iter->head = &ldr_data->InLoadOrderModuleList;
839 iter->process = process;
840 return TRUE;
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 ))
855 return -1;
856 iter->current = (LIST_ENTRY *)(DWORD_PTR)iter->ldr_module32.InLoadOrderModuleList.Flink;
857 return 1;
860 if (!ReadProcessMemory( iter->process,
861 CONTAINING_RECORD(iter->current, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks),
862 &iter->ldr_module, sizeof(iter->ldr_module), NULL ))
863 return -1;
865 iter->current = iter->ldr_module.InLoadOrderLinks.Flink;
866 return 1;
870 static BOOL get_ldr_module( HANDLE process, HMODULE module, LDR_DATA_TABLE_ENTRY *ldr_module )
872 struct module_iterator iter;
873 INT ret;
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;
883 return TRUE;
886 if (ret == 0) SetLastError( ERROR_INVALID_HANDLE );
887 return FALSE;
891 static BOOL get_ldr_module32( HANDLE process, HMODULE module, LDR_DATA_TABLE_ENTRY32 *ldr_module )
893 struct module_iterator iter;
894 INT ret;
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;
904 return TRUE;
907 if (ret == 0) SetLastError( ERROR_INVALID_HANDLE );
908 return FALSE;
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;
928 return TRUE;
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 );
938 return FALSE;
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 );
948 return FALSE;
952 /***********************************************************************
953 * K32EnumProcessModules (kernelbase.@)
955 BOOL WINAPI DECLSPEC_HOTPATCH K32EnumProcessModules( HANDLE process, HMODULE *module,
956 DWORD count, DWORD *needed )
958 struct module_iterator iter;
959 DWORD size = 0;
960 INT ret;
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 );
971 return FALSE;
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;
984 if (!needed)
986 SetLastError( ERROR_NOACCESS );
987 return FALSE;
989 *needed = size;
990 return TRUE;
993 if (!init_module_iterator( &iter, process )) return FALSE;
995 if (count && !module)
997 SetLastError( ERROR_NOACCESS );
998 return FALSE;
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;
1007 else
1008 *module++ = iter.ldr_module.DllBase;
1009 count -= sizeof(HMODULE);
1011 size += sizeof(HMODULE);
1014 if (!needed)
1016 SetLastError( ERROR_NOACCESS );
1017 return FALSE;
1019 *needed = size;
1020 return ret == 0;
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;
1042 void *buf = NULL;
1043 NTSTATUS status;
1047 size *= 2;
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 );
1056 return FALSE;
1058 spi = 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 );
1067 return TRUE;
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;
1078 return 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;
1089 return 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;
1100 return 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;
1111 return 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;
1122 return 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;
1133 return 0;
1137 /***********************************************************************
1138 * K32GetModuleBaseNameA (kernelbase.@)
1140 DWORD WINAPI DECLSPEC_HOTPATCH K32GetModuleBaseNameA( HANDLE process, HMODULE module,
1141 char *name, DWORD size )
1143 WCHAR *name_w;
1144 DWORD len, ret = 0;
1146 if (!name || !size)
1148 SetLastError( ERROR_INVALID_PARAMETER );
1149 return 0;
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) );
1155 if (len)
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 );
1161 return ret;
1165 /***********************************************************************
1166 * K32GetModuleBaseNameW (kernelbase.@)
1168 DWORD WINAPI DECLSPEC_HOTPATCH K32GetModuleBaseNameW( HANDLE process, HMODULE module,
1169 WCHAR *name, DWORD size )
1171 BOOL wow64;
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 ))
1183 return 0;
1185 else
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 ))
1193 return 0;
1195 name[size] = 0;
1196 return size;
1200 /***********************************************************************
1201 * K32GetModuleFileNameExA (kernelbase.@)
1203 DWORD WINAPI DECLSPEC_HOTPATCH K32GetModuleFileNameExA( HANDLE process, HMODULE module,
1204 char *name, DWORD size )
1206 WCHAR *ptr;
1207 DWORD len;
1209 TRACE( "(process=%p, module=%p, %p, %d)\n", process, module, name, size );
1211 if (!name || !size)
1213 SetLastError( ERROR_INVALID_PARAMETER );
1214 return 0;
1216 if (process == GetCurrentProcess())
1218 len = GetModuleFileNameA( module, name, size );
1219 name[size - 1] = '\0';
1220 return len;
1223 if (!(ptr = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return 0;
1224 len = K32GetModuleFileNameExW( process, module, ptr, size );
1225 if (!len)
1227 name[0] = 0;
1229 else
1231 if (!WideCharToMultiByte( CP_ACP, 0, ptr, -1, name, size, NULL, NULL ))
1233 name[size - 1] = 0;
1234 len = size;
1236 else if (len < size) len = strlen( name );
1238 HeapFree( GetProcessHeap(), 0, ptr );
1239 return len;
1243 /***********************************************************************
1244 * K32GetModuleFileNameExW (kernelbase.@)
1246 DWORD WINAPI DECLSPEC_HOTPATCH K32GetModuleFileNameExW( HANDLE process, HMODULE module,
1247 WCHAR *name, DWORD size )
1249 BOOL wow64;
1250 DWORD len;
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 ))
1264 return 0;
1266 else
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 ))
1274 return 0;
1277 if (len < size)
1279 name[len] = 0;
1280 return len;
1282 else
1284 name[size - 1] = 0;
1285 return size;
1290 /***********************************************************************
1291 * K32GetModuleInformation (kernelbase.@)
1293 BOOL WINAPI K32GetModuleInformation( HANDLE process, HMODULE module, MODULEINFO *modinfo, DWORD count )
1295 BOOL wow64;
1297 if (count < sizeof(MODULEINFO))
1299 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1300 return FALSE;
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;
1314 else
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;
1323 return TRUE;
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;
1335 DWORD info_size;
1336 NTSTATUS status;
1338 TRACE( "(%p, %d)\n", info, size );
1340 if (size < sizeof(*info))
1342 SetLastError( ERROR_BAD_LENGTH );
1343 return FALSE;
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 );
1365 for (;;)
1367 process = HeapAlloc( GetProcessHeap(), 0, info_size );
1368 if (!process)
1370 SetLastError( ERROR_OUTOFMEMORY );
1371 return FALSE;
1373 status = NtQuerySystemInformation( SystemProcessInformation, process, info_size, &info_size );
1374 if (!status) break;
1375 HeapFree( GetProcessHeap(), 0, process );
1376 if (status != STATUS_INFO_LENGTH_MISMATCH)
1378 SetLastError( RtlNtStatusToDosError( status ) );
1379 return FALSE;
1382 info->HandleCount = info->ProcessCount = info->ThreadCount = 0;
1383 spi = process;
1384 for (;;)
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 );
1393 return TRUE;
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,
1419 DWORD count )
1421 VM_COUNTERS vmc;
1423 if (count < sizeof(PROCESS_MEMORY_COUNTERS))
1425 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1426 return FALSE;
1429 if (!set_ntstatus( NtQueryInformationProcess( process, ProcessVmCounters, &vmc, sizeof(vmc), NULL )))
1430 return FALSE;
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;
1442 return TRUE;
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,
1460 DWORD *size )
1462 FIXME( "(%p, %p, %p)\n", process, info, size );
1463 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1464 return FALSE;
1468 /***********************************************************************
1469 * K32InitializeProcessForWsWatch (kernelbase.@)
1471 BOOL WINAPI /* DECLSPEC_HOTPATCH */ K32InitializeProcessForWsWatch( HANDLE process )
1473 FIXME( "(process=%p): stub\n", process );
1474 return TRUE;
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 )
1505 BOOL ret;
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 );
1513 return ret;
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;
1526 NTSTATUS status;
1527 DWORD needed;
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,
1537 needed, &needed );
1538 result = dynamic_buffer;
1540 else
1541 result = (UNICODE_STRING *)buffer;
1543 if (status) goto cleanup;
1545 if (flags & PROCESS_NAME_NATIVE)
1547 WCHAR drive[3];
1548 WCHAR device[1024];
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;
1555 goto cleanup;
1558 /* Find this drive's NT device path */
1559 drive[0] = result->Buffer[0];
1560 drive[1] = ':';
1561 drive[2] = 0;
1562 if (!QueryDosDeviceW(drive, device, ARRAY_SIZE(device)))
1564 status = STATUS_NO_SUCH_DEVICE;
1565 goto cleanup;
1568 devlen = lstrlenW(device);
1569 ntlen = devlen + (result->Length/sizeof(WCHAR) - 2);
1570 if (ntlen + 1 > *size)
1572 status = STATUS_BUFFER_TOO_SMALL;
1573 goto cleanup;
1575 *size = ntlen;
1577 memcpy( name, device, devlen * sizeof(*device) );
1578 memcpy( name + devlen, result->Buffer + 2, result->Length - 2 * sizeof(WCHAR) );
1579 name[*size] = 0;
1580 TRACE( "NT path: %s\n", debugstr_w(name) );
1582 else
1584 if (result->Length/sizeof(WCHAR) + 1 > *size)
1586 status = STATUS_BUFFER_TOO_SMALL;
1587 goto cleanup;
1590 *size = result->Length/sizeof(WCHAR);
1591 memcpy( name, result->Buffer, result->Length );
1592 name[*size] = 0;
1595 cleanup:
1596 HeapFree( GetProcessHeap(), 0, dynamic_buffer );
1597 return set_ntstatus( status );