mfmediaengine: Handle B8G8R8X8 format for d3d11 texture output.
[wine.git] / dlls / kernelbase / debug.c
blob08af7fad5ba76407dc17f035765e73a32a1b01e6
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 #define PSAPI_VERSION 1 /* avoid K32 function remapping */
34 #include "psapi.h"
35 #include "werapi.h"
37 #include "wine/exception.h"
38 #include "wine/asm.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 )
57 DWORD_PTR port;
59 if (!process || !present)
61 SetLastError( ERROR_INVALID_PARAMETER );
62 return FALSE;
64 if (!set_ntstatus( NtQueryInformationProcess( process, ProcessDebugPort, &port, sizeof(port), NULL )))
65 return FALSE;
66 *present = !!port;
67 return TRUE;
71 /**********************************************************************
72 * ContinueDebugEvent (kernelbase.@)
74 BOOL WINAPI DECLSPEC_HOTPATCH ContinueDebugEvent( DWORD pid, DWORD tid, DWORD status )
76 CLIENT_ID id;
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 )
89 HANDLE process;
90 NTSTATUS status;
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 )))
95 return FALSE;
96 status = DbgUiDebugActiveProcess( process );
97 NtClose( process );
98 return set_ntstatus( status );
102 /**********************************************************************
103 * DebugActiveProcessStop (kernelbase.@)
105 BOOL WINAPI DECLSPEC_HOTPATCH DebugActiveProcessStop( DWORD pid )
107 HANDLE process;
108 NTSTATUS status;
110 if (!(process = OpenProcess( PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_SUSPEND_RESUME, FALSE, pid )))
111 return FALSE;
112 status = DbgUiStopDebugging( process );
113 NtClose( 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) )
123 #else
124 void WINAPI DebugBreak(void)
126 DbgBreakPoint();
128 #endif
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;
185 if (!str) str = "";
186 WARN( "%s\n", debugstr_a(str) );
188 /* raise exception, WaitForDebugEvent() will generate a corresponding debug event */
189 __TRY
191 ULONG_PTR args[2];
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;
200 __ENDTRY
201 if (caught_by_dbg) return;
203 /* send string to a system-wide monitor */
204 if (!mutex_inited)
206 /* first call to OutputDebugString, initialize mutex handle */
207 HANDLE mutex = CreateMutexExW( NULL, L"DBWinMutex", 0, SYNCHRONIZE );
208 if (mutex)
210 if (InterlockedCompareExchangePointer( &DBWinMutex, mutex, 0 ) != 0)
211 /* someone beat us here... */
212 CloseHandle( mutex );
214 mutex_inited = TRUE;
217 if (DBWinMutex)
219 HANDLE mapping;
221 mapping = OpenFileMappingW( FILE_MAP_WRITE, FALSE, L"DBWIN_BUFFER" );
222 if (mapping)
224 LPVOID 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 );
240 struct _mon_buffer_t
242 DWORD pid;
243 char buffer[1];
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 )
271 UNICODE_STRING strW;
272 STRING strA;
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;
294 if (count && args)
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;
323 int len;
325 switch(rec->ExceptionCode)
327 case EXCEPTION_INT_DIVIDE_BY_ZERO:
328 len = snprintf( buffer, size, "Unhandled division by zero" );
329 break;
330 case EXCEPTION_INT_OVERFLOW:
331 len = snprintf( buffer, size, "Unhandled overflow" );
332 break;
333 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
334 len = snprintf( buffer, size, "Unhandled array bounds" );
335 break;
336 case EXCEPTION_ILLEGAL_INSTRUCTION:
337 len = snprintf( buffer, size, "Unhandled illegal instruction" );
338 break;
339 case EXCEPTION_STACK_OVERFLOW:
340 len = snprintf( buffer, size, "Unhandled stack overflow" );
341 break;
342 case EXCEPTION_PRIV_INSTRUCTION:
343 len = snprintf( buffer, size, "Unhandled privileged instruction" );
344 break;
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]);
351 else
352 len = snprintf( buffer, size, "Unhandled page fault");
353 break;
354 case EXCEPTION_DATATYPE_MISALIGNMENT:
355 len = snprintf( buffer, size, "Unhandled alignment" );
356 break;
357 case CONTROL_C_EXIT:
358 len = snprintf( buffer, size, "Unhandled ^C");
359 break;
360 case STATUS_POSSIBLE_DEADLOCK:
361 len = snprintf( buffer, size, "Critical section %p wait failed",
362 (void *)rec->ExceptionInformation[0]);
363 break;
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] );
368 else
369 len = snprintf( buffer, size, "Unimplemented function %s.%ld called",
370 (char *)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
371 break;
372 case EXCEPTION_WINE_ASSERTION:
373 len = snprintf( buffer, size, "Assertion failed" );
374 break;
375 default:
376 len = snprintf( buffer, size, "Unhandled exception 0x%08x in thread %x",
377 rec->ExceptionCode, GetCurrentThreadId());
378 break;
380 if (len < 0 || len >= size) return;
381 snprintf( buffer + len, size - len, " at address %p", ptr->ExceptionRecord->ExceptionAddress );
385 /******************************************************************
386 * start_debugger
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;
395 HANDLE dbg_key;
396 DWORD autostart = TRUE;
397 PROCESS_INFORMATION info;
398 STARTUPINFOW startup;
399 BOOL ret = FALSE;
400 char buffer[256];
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;
408 attr.Attributes = 0;
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)
432 WCHAR *tmp;
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 );
438 format = tmp;
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 );
457 NtClose( dbg_key );
460 if (format)
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 );
467 else
469 cmdline = HeapAlloc( GetProcessHeap(), 0, 80 * sizeof(WCHAR) );
470 swprintf( cmdline, 80, L"winedbg --auto %ld %ld", (long)GetCurrentProcessId(), (long)HandleToLong(event) );
473 if (!autostart)
475 HMODULE mod = GetModuleHandleA( "user32.dll" );
476 MessageBoxA_funcptr pMessageBoxA = NULL;
478 if (mod) pMessageBoxA = (void *)GetProcAddress( mod, "MessageBoxA" );
479 if (pMessageBoxA)
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" );
488 goto exit;
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 );
505 break;
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 );
518 if (ret)
520 /* wait for debugger to come up... */
521 HANDLE handles[2];
522 CloseHandle( info.hThread );
523 handles[0] = event;
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() );
531 exit:
532 HeapFree(GetProcessHeap(), 0, cmdline);
533 return ret;
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 )
548 static HANDLE once;
550 if (once == 0)
552 OBJECT_ATTRIBUTES attr;
553 HANDLE event;
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 );
570 if (!ret)
572 /* so that the other threads won't be stuck */
573 NtSetEvent( once, NULL );
575 return ret;
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 */
587 return TRUE;
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 )
600 DWORD old_prot;
601 void *rsrc;
602 DWORD size;
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 )))
609 return FALSE;
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 );
613 return TRUE;
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;
631 break;
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 );
643 if (top_filter)
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 );
664 return E_NOTIMPL;
668 /***********************************************************************
669 * WerRegisterFile (kernelbase.@)
671 HRESULT WINAPI /* DECLSPEC_HOTPATCH */ WerRegisterFile( const WCHAR *file, WER_REGISTER_FILE_TYPE type,
672 DWORD flags )
674 FIXME( "(%s, %d, %d) stub\n", debugstr_w(file), type, flags );
675 return E_NOTIMPL;
679 /***********************************************************************
680 * WerRegisterMemoryBlock (kernelbase.@)
682 HRESULT WINAPI /* DECLSPEC_HOTPATCH */ WerRegisterMemoryBlock( void *block, DWORD size )
684 FIXME( "(%p %d) stub\n", block, size );
685 return E_NOTIMPL;
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 );
695 return S_OK;
699 /***********************************************************************
700 * WerSetFlags (kernelbase.@)
702 HRESULT WINAPI /* DECLSPEC_HOTPATCH */ WerSetFlags( DWORD flags )
704 FIXME("(%d) stub\n", flags);
705 return S_OK;
709 /***********************************************************************
710 * WerUnregisterFile (kernelbase.@)
712 HRESULT WINAPI /* DECLSPEC_HOTPATCH */ WerUnregisterFile( const WCHAR *file )
714 FIXME( "(%s) stub\n", debugstr_w(file) );
715 return E_NOTIMPL;
719 /***********************************************************************
720 * WerUnregisterMemoryBlock (kernelbase.@)
722 HRESULT WINAPI /* DECLSPEC_HOTPATCH */ WerUnregisterMemoryBlock( void *block )
724 FIXME( "(%p) stub\n", block );
725 return E_NOTIMPL;
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 );
735 return S_OK;
739 /***********************************************************************
740 * psapi functions
741 ***********************************************************************/
744 typedef struct _LDR_DATA_TABLE_ENTRY32
746 LIST_ENTRY32 InLoadOrderModuleList;
747 LIST_ENTRY32 InMemoryOrderModuleList;
748 LIST_ENTRY32 InInitializationOrderModuleList;
749 DWORD BaseAddress;
750 DWORD EntryPoint;
751 ULONG SizeOfImage;
752 UNICODE_STRING32 FullDllName;
753 UNICODE_STRING32 BaseDllName;
754 } LDR_DATA_TABLE_ENTRY32;
756 struct module_iterator
758 HANDLE process;
759 LIST_ENTRY *head;
760 LIST_ENTRY *current;
761 BOOL wow64;
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 )))
777 return FALSE;
779 if (is_win64 && iter->wow64)
781 PEB_LDR_DATA32 *ldr_data32_ptr;
782 DWORD ldr_data32, first_module;
783 PEB32 *peb32;
785 peb32 = (PEB32 *)((char *)pbi.PebBaseAddress + 0x1000);
786 if (!ReadProcessMemory( process, &peb32->LdrData, &ldr_data32, sizeof(ldr_data32), NULL ))
787 return FALSE;
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 ))
791 return FALSE;
792 iter->head = (LIST_ENTRY *)&ldr_data32_ptr->InLoadOrderModuleList;
793 iter->current = (LIST_ENTRY *)(DWORD_PTR)first_module;
794 iter->process = process;
795 return TRUE;
798 /* read address of LdrData from PEB */
799 if (!ReadProcessMemory( process, &pbi.PebBaseAddress->LdrData, &ldr_data, sizeof(ldr_data), NULL ))
800 return FALSE;
802 /* read address of first module from LdrData */
803 if (!ReadProcessMemory( process, &ldr_data->InLoadOrderModuleList.Flink,
804 &iter->current, sizeof(iter->current), NULL ))
805 return FALSE;
807 iter->head = &ldr_data->InLoadOrderModuleList;
808 iter->process = process;
809 return TRUE;
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 ))
824 return -1;
825 iter->current = (LIST_ENTRY *)(DWORD_PTR)iter->ldr_module32.InLoadOrderModuleList.Flink;
826 return 1;
829 if (!ReadProcessMemory( iter->process,
830 CONTAINING_RECORD(iter->current, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks),
831 &iter->ldr_module, sizeof(iter->ldr_module), NULL ))
832 return -1;
834 iter->current = iter->ldr_module.InLoadOrderLinks.Flink;
835 return 1;
839 static BOOL get_ldr_module( HANDLE process, HMODULE module, LDR_DATA_TABLE_ENTRY *ldr_module )
841 struct module_iterator iter;
842 INT ret;
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;
852 return TRUE;
855 if (ret == 0) SetLastError( ERROR_INVALID_HANDLE );
856 return FALSE;
860 static BOOL get_ldr_module32( HANDLE process, HMODULE module, LDR_DATA_TABLE_ENTRY32 *ldr_module )
862 struct module_iterator iter;
863 INT ret;
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;
873 return TRUE;
876 if (ret == 0) SetLastError( ERROR_INVALID_HANDLE );
877 return FALSE;
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;
899 return TRUE;
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 );
910 return FALSE;
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 );
921 return FALSE;
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;
933 DWORD size = 0;
934 INT ret;
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 );
945 return FALSE;
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;
958 if (!needed)
960 SetLastError( ERROR_NOACCESS );
961 return FALSE;
963 *needed = size;
964 return TRUE;
967 if (!init_module_iterator( &iter, process )) return FALSE;
969 if (count && !module)
971 SetLastError( ERROR_NOACCESS );
972 return FALSE;
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;
981 else
982 *module++ = iter.ldr_module.DllBase;
983 count -= sizeof(HMODULE);
985 size += sizeof(HMODULE);
988 if (!needed)
990 SetLastError( ERROR_NOACCESS );
991 return FALSE;
993 *needed = size;
994 return ret == 0;
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;
1018 void *buf = NULL;
1019 NTSTATUS status;
1023 size *= 2;
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 );
1032 return FALSE;
1034 spi = 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 );
1043 return TRUE;
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;
1055 return 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;
1067 return 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;
1079 return 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;
1091 return 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];
1102 DWORD len;
1104 if (size && !name)
1106 SetLastError( ERROR_INVALID_PARAMETER );
1107 return 0;
1109 if (!GetMappedFileNameW( process, addr, nameW, MAX_PATH )) return 0;
1110 if (!size)
1112 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1113 return 0;
1115 len = file_name_WtoA( nameW, wcslen(nameW), name, size );
1116 name[min(len, size - 1)] = 0;
1117 return len;
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;
1129 DWORD len;
1131 if (size && !name)
1133 SetLastError( ERROR_INVALID_PARAMETER );
1134 return 0;
1136 if (!set_ntstatus( NtQueryVirtualMemory( process, addr, MemorySectionName, mem, sizeof(buffer), NULL )))
1137 return 0;
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;
1143 return len;
1147 /***********************************************************************
1148 * GetModuleBaseNameA (kernelbase.@)
1149 * K32GetModuleBaseNameA (kernelbase.@)
1151 DWORD WINAPI DECLSPEC_HOTPATCH GetModuleBaseNameA( HANDLE process, HMODULE module,
1152 char *name, DWORD size )
1154 WCHAR *name_w;
1155 DWORD len, ret = 0;
1157 if (!name || !size)
1159 SetLastError( ERROR_INVALID_PARAMETER );
1160 return 0;
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) );
1166 if (len)
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 );
1172 return ret;
1176 /***********************************************************************
1177 * GetModuleBaseNameW (kernelbase.@)
1178 * K32GetModuleBaseNameW (kernelbase.@)
1180 DWORD WINAPI DECLSPEC_HOTPATCH GetModuleBaseNameW( HANDLE process, HMODULE module,
1181 WCHAR *name, DWORD size )
1183 BOOL wow64;
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 ))
1195 return 0;
1197 else
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 ))
1205 return 0;
1207 name[size] = 0;
1208 return size;
1212 /***********************************************************************
1213 * GetModuleFileNameExA (kernelbase.@)
1214 * K32GetModuleFileNameExA (kernelbase.@)
1216 DWORD WINAPI DECLSPEC_HOTPATCH GetModuleFileNameExA( HANDLE process, HMODULE module,
1217 char *name, DWORD size )
1219 WCHAR *ptr;
1220 DWORD len;
1222 TRACE( "(process=%p, module=%p, %p, %d)\n", process, module, name, size );
1224 if (!name || !size)
1226 SetLastError( ERROR_INVALID_PARAMETER );
1227 return 0;
1229 if (process == GetCurrentProcess())
1231 len = GetModuleFileNameA( module, name, size );
1232 name[size - 1] = '\0';
1233 return len;
1236 if (!(ptr = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return 0;
1237 len = GetModuleFileNameExW( process, module, ptr, size );
1238 if (!len)
1240 name[0] = 0;
1242 else
1244 if (!WideCharToMultiByte( CP_ACP, 0, ptr, -1, name, size, NULL, NULL ))
1246 name[size - 1] = 0;
1247 len = size;
1249 else if (len < size) len = strlen( name );
1251 HeapFree( GetProcessHeap(), 0, ptr );
1252 return len;
1256 /***********************************************************************
1257 * GetModuleFileNameExW (kernelbase.@)
1258 * K32GetModuleFileNameExW (kernelbase.@)
1260 DWORD WINAPI DECLSPEC_HOTPATCH GetModuleFileNameExW( HANDLE process, HMODULE module,
1261 WCHAR *name, DWORD size )
1263 BOOL wow64;
1264 DWORD len;
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 ))
1278 return 0;
1280 else
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 ))
1288 return 0;
1291 if (len < size)
1293 name[len] = 0;
1294 return len;
1296 else
1298 name[size - 1] = 0;
1299 return size;
1304 /***********************************************************************
1305 * GetModuleInformation (kernelbase.@)
1306 * K32GetModuleInformation (kernelbase.@)
1308 BOOL WINAPI GetModuleInformation( HANDLE process, HMODULE module, MODULEINFO *modinfo, DWORD count )
1310 BOOL wow64;
1312 if (count < sizeof(MODULEINFO))
1314 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1315 return FALSE;
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;
1329 else
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;
1338 return TRUE;
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;
1351 DWORD info_size;
1352 NTSTATUS status;
1354 TRACE( "(%p, %d)\n", info, size );
1356 if (size < sizeof(*info))
1358 SetLastError( ERROR_BAD_LENGTH );
1359 return FALSE;
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 );
1381 for (;;)
1383 process = HeapAlloc( GetProcessHeap(), 0, info_size );
1384 if (!process)
1386 SetLastError( ERROR_OUTOFMEMORY );
1387 return FALSE;
1389 status = NtQuerySystemInformation( SystemProcessInformation, process, info_size, &info_size );
1390 if (!status) break;
1391 HeapFree( GetProcessHeap(), 0, process );
1392 if (status != STATUS_INFO_LENGTH_MISMATCH)
1394 SetLastError( RtlNtStatusToDosError( status ) );
1395 return FALSE;
1398 info->HandleCount = info->ProcessCount = info->ThreadCount = 0;
1399 spi = process;
1400 for (;;)
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 );
1409 return TRUE;
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,
1438 DWORD count )
1440 VM_COUNTERS vmc;
1442 if (count < sizeof(PROCESS_MEMORY_COUNTERS))
1444 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1445 return FALSE;
1448 if (!set_ntstatus( NtQueryInformationProcess( process, ProcessVmCounters, &vmc, sizeof(vmc), NULL )))
1449 return FALSE;
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;
1461 return TRUE;
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,
1481 DWORD *size )
1483 FIXME( "(%p, %p, %p)\n", process, info, size );
1484 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1485 return FALSE;
1489 /***********************************************************************
1490 * InitializeProcessForWsWatch (kernelbase.@)
1491 * K32InitializeProcessForWsWatch (kernelbase.@)
1493 BOOL WINAPI /* DECLSPEC_HOTPATCH */ InitializeProcessForWsWatch( HANDLE process )
1495 FIXME( "(process=%p): stub\n", process );
1496 return TRUE;
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 )
1529 BOOL ret;
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 );
1537 return ret;
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;
1550 NTSTATUS status;
1551 DWORD needed;
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,
1560 needed, &needed );
1561 result = dynamic_buffer;
1563 else
1564 result = (UNICODE_STRING *)buffer;
1566 if (status) goto cleanup;
1568 if (flags & PROCESS_NAME_NATIVE)
1570 WCHAR drive[3];
1571 WCHAR device[1024];
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;
1578 goto cleanup;
1581 /* Find this drive's NT device path */
1582 drive[0] = result->Buffer[0];
1583 drive[1] = ':';
1584 drive[2] = 0;
1585 if (!QueryDosDeviceW(drive, device, ARRAY_SIZE(device)))
1587 status = STATUS_NO_SUCH_DEVICE;
1588 goto cleanup;
1591 devlen = lstrlenW(device);
1592 ntlen = devlen + (result->Length/sizeof(WCHAR) - 2);
1593 if (ntlen + 1 > *size)
1595 status = STATUS_BUFFER_TOO_SMALL;
1596 goto cleanup;
1598 *size = ntlen;
1600 memcpy( name, device, devlen * sizeof(*device) );
1601 memcpy( name + devlen, result->Buffer + 2, result->Length - 2 * sizeof(WCHAR) );
1602 name[*size] = 0;
1603 TRACE( "NT path: %s\n", debugstr_w(name) );
1605 else
1607 if (result->Length/sizeof(WCHAR) + 1 > *size)
1609 status = STATUS_BUFFER_TOO_SMALL;
1610 goto cleanup;
1613 *size = result->Length/sizeof(WCHAR);
1614 memcpy( name, result->Buffer, result->Length );
1615 name[*size] = 0;
1618 cleanup:
1619 HeapFree( GetProcessHeap(), 0, dynamic_buffer );
1620 return set_ntstatus( status );