kernelbase: Implement GetMappedFileNameA/W.
[wine.git] / dlls / kernelbase / debug.c
blobcbc53e22ac1397aa38fe63aaba43b3ec0d98ea44
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_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 _PEB32
746 BOOLEAN InheritedAddressSpace;
747 BOOLEAN ReadImageFileExecOptions;
748 BOOLEAN BeingDebugged;
749 BOOLEAN SpareBool;
750 DWORD Mutant;
751 DWORD ImageBaseAddress;
752 DWORD LdrData;
753 } PEB32;
755 typedef struct _LIST_ENTRY32
757 DWORD Flink;
758 DWORD Blink;
759 } LIST_ENTRY32;
761 typedef struct _PEB_LDR_DATA32
763 ULONG Length;
764 BOOLEAN Initialized;
765 DWORD SsHandle;
766 LIST_ENTRY32 InLoadOrderModuleList;
767 } PEB_LDR_DATA32;
769 typedef struct _UNICODE_STRING32
771 USHORT Length;
772 USHORT MaximumLength;
773 DWORD Buffer;
774 } UNICODE_STRING32;
776 typedef struct _LDR_DATA_TABLE_ENTRY32
778 LIST_ENTRY32 InLoadOrderModuleList;
779 LIST_ENTRY32 InMemoryOrderModuleList;
780 LIST_ENTRY32 InInitializationOrderModuleList;
781 DWORD BaseAddress;
782 DWORD EntryPoint;
783 ULONG SizeOfImage;
784 UNICODE_STRING32 FullDllName;
785 UNICODE_STRING32 BaseDllName;
786 } LDR_DATA_TABLE_ENTRY32;
788 struct module_iterator
790 HANDLE process;
791 LIST_ENTRY *head;
792 LIST_ENTRY *current;
793 BOOL wow64;
794 LDR_DATA_TABLE_ENTRY ldr_module;
795 LDR_DATA_TABLE_ENTRY32 ldr_module32;
799 static BOOL init_module_iterator( struct module_iterator *iter, HANDLE process )
801 PROCESS_BASIC_INFORMATION pbi;
802 PPEB_LDR_DATA ldr_data;
804 if (!IsWow64Process( process, &iter->wow64 )) return FALSE;
806 /* get address of PEB */
807 if (!set_ntstatus( NtQueryInformationProcess( process, ProcessBasicInformation,
808 &pbi, sizeof(pbi), NULL )))
809 return FALSE;
811 if (is_win64 && iter->wow64)
813 PEB_LDR_DATA32 *ldr_data32_ptr;
814 DWORD ldr_data32, first_module;
815 PEB32 *peb32;
817 peb32 = (PEB32 *)(DWORD_PTR)pbi.PebBaseAddress;
818 if (!ReadProcessMemory( process, &peb32->LdrData, &ldr_data32, sizeof(ldr_data32), NULL ))
819 return FALSE;
820 ldr_data32_ptr = (PEB_LDR_DATA32 *)(DWORD_PTR) ldr_data32;
821 if (!ReadProcessMemory( process, &ldr_data32_ptr->InLoadOrderModuleList.Flink,
822 &first_module, sizeof(first_module), NULL ))
823 return FALSE;
824 iter->head = (LIST_ENTRY *)&ldr_data32_ptr->InLoadOrderModuleList;
825 iter->current = (LIST_ENTRY *)(DWORD_PTR)first_module;
826 iter->process = process;
827 return TRUE;
830 /* read address of LdrData from PEB */
831 if (!ReadProcessMemory( process, &pbi.PebBaseAddress->LdrData, &ldr_data, sizeof(ldr_data), NULL ))
832 return FALSE;
834 /* read address of first module from LdrData */
835 if (!ReadProcessMemory( process, &ldr_data->InLoadOrderModuleList.Flink,
836 &iter->current, sizeof(iter->current), NULL ))
837 return FALSE;
839 iter->head = &ldr_data->InLoadOrderModuleList;
840 iter->process = process;
841 return TRUE;
845 static int module_iterator_next( struct module_iterator *iter )
847 if (iter->current == iter->head) return 0;
849 if (is_win64 && iter->wow64)
851 LIST_ENTRY32 *entry32 = (LIST_ENTRY32 *)iter->current;
853 if (!ReadProcessMemory( iter->process,
854 CONTAINING_RECORD(entry32, LDR_DATA_TABLE_ENTRY32, InLoadOrderModuleList),
855 &iter->ldr_module32, sizeof(iter->ldr_module32), NULL ))
856 return -1;
857 iter->current = (LIST_ENTRY *)(DWORD_PTR)iter->ldr_module32.InLoadOrderModuleList.Flink;
858 return 1;
861 if (!ReadProcessMemory( iter->process,
862 CONTAINING_RECORD(iter->current, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks),
863 &iter->ldr_module, sizeof(iter->ldr_module), NULL ))
864 return -1;
866 iter->current = iter->ldr_module.InLoadOrderLinks.Flink;
867 return 1;
871 static BOOL get_ldr_module( HANDLE process, HMODULE module, LDR_DATA_TABLE_ENTRY *ldr_module )
873 struct module_iterator iter;
874 INT ret;
876 if (!init_module_iterator( &iter, process )) return FALSE;
878 while ((ret = module_iterator_next( &iter )) > 0)
879 /* When hModule is NULL we return the process image - which will be
880 * the first module since our iterator uses InLoadOrderModuleList */
881 if (!module || module == iter.ldr_module.DllBase)
883 *ldr_module = iter.ldr_module;
884 return TRUE;
887 if (ret == 0) SetLastError( ERROR_INVALID_HANDLE );
888 return FALSE;
892 static BOOL get_ldr_module32( HANDLE process, HMODULE module, LDR_DATA_TABLE_ENTRY32 *ldr_module )
894 struct module_iterator iter;
895 INT ret;
897 if (!init_module_iterator( &iter, process )) return FALSE;
899 while ((ret = module_iterator_next( &iter )) > 0)
900 /* When hModule is NULL we return the process image - which will be
901 * the first module since our iterator uses InLoadOrderModuleList */
902 if (!module || (DWORD)(DWORD_PTR)module == iter.ldr_module32.BaseAddress)
904 *ldr_module = iter.ldr_module32;
905 return TRUE;
908 if (ret == 0) SetLastError( ERROR_INVALID_HANDLE );
909 return FALSE;
913 /***********************************************************************
914 * EmptyWorkingSet (kernelbase.@)
915 * K32EmptyWorkingSet (kernelbase.@)
917 BOOL WINAPI DECLSPEC_HOTPATCH EmptyWorkingSet( HANDLE process )
919 return SetProcessWorkingSetSizeEx( process, (SIZE_T)-1, (SIZE_T)-1, 0 );
923 /***********************************************************************
924 * EnumDeviceDrivers (kernelbase.@)
925 * K32EnumDeviceDrivers (kernelbase.@)
927 BOOL WINAPI EnumDeviceDrivers( void **image_base, DWORD count, DWORD *needed )
929 FIXME( "(%p, %d, %p): stub\n", image_base, count, needed );
930 if (needed) *needed = 0;
931 return TRUE;
935 /***********************************************************************
936 * EnumPageFilesA (kernelbase.@)
937 * K32EnumPageFilesA (kernelbase.@)
939 BOOL WINAPI /* DECLSPEC_HOTPATCH */ EnumPageFilesA( PENUM_PAGE_FILE_CALLBACKA callback, void *context )
941 FIXME( "(%p, %p) stub\n", callback, context );
942 return FALSE;
946 /***********************************************************************
947 * EnumPageFilesW (kernelbase.@)
948 * K32EnumPageFilesW (kernelbase.@)
950 BOOL WINAPI /* DECLSPEC_HOTPATCH */ EnumPageFilesW( PENUM_PAGE_FILE_CALLBACKW callback, void *context )
952 FIXME( "(%p, %p) stub\n", callback, context );
953 return FALSE;
957 /***********************************************************************
958 * EnumProcessModules (kernelbase.@)
959 * K32EnumProcessModules (kernelbase.@)
961 BOOL WINAPI DECLSPEC_HOTPATCH EnumProcessModules( HANDLE process, HMODULE *module,
962 DWORD count, DWORD *needed )
964 struct module_iterator iter;
965 DWORD size = 0;
966 INT ret;
968 if (process == GetCurrentProcess())
970 PPEB_LDR_DATA ldr_data = NtCurrentTeb()->Peb->LdrData;
971 PLIST_ENTRY head = &ldr_data->InLoadOrderModuleList;
972 PLIST_ENTRY entry = head->Flink;
974 if (count && !module)
976 SetLastError( ERROR_NOACCESS );
977 return FALSE;
979 while (entry != head)
981 LDR_DATA_TABLE_ENTRY *ldr = CONTAINING_RECORD( entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks );
982 if (count >= sizeof(HMODULE))
984 *module++ = ldr->DllBase;
985 count -= sizeof(HMODULE);
987 size += sizeof(HMODULE);
988 entry = entry->Flink;
990 if (!needed)
992 SetLastError( ERROR_NOACCESS );
993 return FALSE;
995 *needed = size;
996 return TRUE;
999 if (!init_module_iterator( &iter, process )) return FALSE;
1001 if (count && !module)
1003 SetLastError( ERROR_NOACCESS );
1004 return FALSE;
1007 while ((ret = module_iterator_next( &iter )) > 0)
1009 if (count >= sizeof(HMODULE))
1011 if (sizeof(void *) == 8 && iter.wow64)
1012 *module++ = (HMODULE) (DWORD_PTR)iter.ldr_module32.BaseAddress;
1013 else
1014 *module++ = iter.ldr_module.DllBase;
1015 count -= sizeof(HMODULE);
1017 size += sizeof(HMODULE);
1020 if (!needed)
1022 SetLastError( ERROR_NOACCESS );
1023 return FALSE;
1025 *needed = size;
1026 return ret == 0;
1030 /***********************************************************************
1031 * EnumProcessModulesEx (kernelbase.@)
1032 * K32EnumProcessModulesEx (kernelbase.@)
1034 BOOL WINAPI EnumProcessModulesEx( HANDLE process, HMODULE *module, DWORD count,
1035 DWORD *needed, DWORD filter )
1037 FIXME( "(%p, %p, %d, %p, %d) semi-stub\n", process, module, count, needed, filter );
1038 return EnumProcessModules( process, module, count, needed );
1042 /***********************************************************************
1043 * EnumProcesses (kernelbase.@)
1044 * K32EnumProcesses (kernelbase.@)
1046 BOOL WINAPI EnumProcesses( DWORD *ids, DWORD count, DWORD *used )
1048 SYSTEM_PROCESS_INFORMATION *spi;
1049 ULONG size = 0x4000;
1050 void *buf = NULL;
1051 NTSTATUS status;
1055 size *= 2;
1056 HeapFree( GetProcessHeap(), 0, buf );
1057 if (!(buf = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE;
1058 status = NtQuerySystemInformation( SystemProcessInformation, buf, size, NULL );
1059 } while (status == STATUS_INFO_LENGTH_MISMATCH);
1061 if (!set_ntstatus( status ))
1063 HeapFree( GetProcessHeap(), 0, buf );
1064 return FALSE;
1066 spi = buf;
1067 for (*used = 0; count >= sizeof(DWORD); count -= sizeof(DWORD))
1069 *ids++ = HandleToUlong( spi->UniqueProcessId );
1070 *used += sizeof(DWORD);
1071 if (spi->NextEntryOffset == 0) break;
1072 spi = (SYSTEM_PROCESS_INFORMATION *)(((PCHAR)spi) + spi->NextEntryOffset);
1074 HeapFree( GetProcessHeap(), 0, buf );
1075 return TRUE;
1079 /***********************************************************************
1080 * GetDeviceDriverBaseNameA (kernelbase.@)
1081 * K32GetDeviceDriverBaseNameA (kernelbase.@)
1083 DWORD WINAPI DECLSPEC_HOTPATCH GetDeviceDriverBaseNameA( void *image_base, char *name, DWORD size )
1085 FIXME( "(%p, %p, %d): stub\n", image_base, name, size );
1086 if (name && size) name[0] = 0;
1087 return 0;
1091 /***********************************************************************
1092 * GetDeviceDriverBaseNameW (kernelbase.@)
1093 * K32GetDeviceDriverBaseNameW (kernelbase.@)
1095 DWORD WINAPI DECLSPEC_HOTPATCH GetDeviceDriverBaseNameW( void *image_base, WCHAR *name, DWORD size )
1097 FIXME( "(%p, %p, %d): stub\n", image_base, name, size );
1098 if (name && size) name[0] = 0;
1099 return 0;
1103 /***********************************************************************
1104 * GetDeviceDriverFileNameA (kernelbase.@)
1105 * K32GetDeviceDriverFileNameA (kernelbase.@)
1107 DWORD WINAPI DECLSPEC_HOTPATCH GetDeviceDriverFileNameA( void *image_base, char *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 * GetDeviceDriverFileNameW (kernelbase.@)
1117 * K32GetDeviceDriverFileNameW (kernelbase.@)
1119 DWORD WINAPI DECLSPEC_HOTPATCH GetDeviceDriverFileNameW( void *image_base, WCHAR *name, DWORD size )
1121 FIXME( "(%p, %p, %d): stub\n", image_base, name, size );
1122 if (name && size) name[0] = 0;
1123 return 0;
1127 /***********************************************************************
1128 * GetMappedFileNameA (kernelbase.@)
1129 * K32GetMappedFileNameA (kernelbase.@)
1131 DWORD WINAPI DECLSPEC_HOTPATCH GetMappedFileNameA( HANDLE process, void *addr, char *name, DWORD size )
1133 WCHAR nameW[MAX_PATH];
1134 DWORD len;
1136 if (size && !name)
1138 SetLastError( ERROR_INVALID_PARAMETER );
1139 return 0;
1141 if (!GetMappedFileNameW( process, addr, nameW, MAX_PATH )) return 0;
1142 if (!size)
1144 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1145 return 0;
1147 len = file_name_WtoA( nameW, wcslen(nameW), name, size );
1148 name[min(len, size - 1)] = 0;
1149 return len;
1153 /***********************************************************************
1154 * GetMappedFileNameW (kernelbase.@)
1155 * K32GetMappedFileNameW (kernelbase.@)
1157 DWORD WINAPI DECLSPEC_HOTPATCH GetMappedFileNameW( HANDLE process, void *addr, WCHAR *name, DWORD size )
1159 ULONG_PTR buffer[(sizeof(MEMORY_SECTION_NAME) + MAX_PATH * sizeof(WCHAR)) / sizeof(ULONG_PTR)];
1160 MEMORY_SECTION_NAME *mem = (MEMORY_SECTION_NAME *)buffer;
1161 DWORD len;
1163 if (size && !name)
1165 SetLastError( ERROR_INVALID_PARAMETER );
1166 return 0;
1168 if (!set_ntstatus( NtQueryVirtualMemory( process, addr, MemorySectionName, mem, sizeof(buffer), NULL )))
1169 return 0;
1171 len = mem->SectionFileName.Length / sizeof(WCHAR);
1172 memcpy( name, mem->SectionFileName.Buffer, min( mem->SectionFileName.Length, size * sizeof(WCHAR) ));
1173 if (len >= size) SetLastError( ERROR_INSUFFICIENT_BUFFER );
1174 name[min(len, size - 1)] = 0;
1175 return len;
1179 /***********************************************************************
1180 * GetModuleBaseNameA (kernelbase.@)
1181 * K32GetModuleBaseNameA (kernelbase.@)
1183 DWORD WINAPI DECLSPEC_HOTPATCH GetModuleBaseNameA( HANDLE process, HMODULE module,
1184 char *name, DWORD size )
1186 WCHAR *name_w;
1187 DWORD len, ret = 0;
1189 if (!name || !size)
1191 SetLastError( ERROR_INVALID_PARAMETER );
1192 return 0;
1194 if (!(name_w = HeapAlloc( GetProcessHeap(), 0, sizeof(WCHAR) * size ))) return 0;
1196 len = GetModuleBaseNameW( process, module, name_w, size );
1197 TRACE( "%d, %s\n", len, debugstr_w(name_w) );
1198 if (len)
1200 ret = WideCharToMultiByte( CP_ACP, 0, name_w, len, name, size, NULL, NULL );
1201 if (ret < size) name[ret] = 0;
1203 HeapFree( GetProcessHeap(), 0, name_w );
1204 return ret;
1208 /***********************************************************************
1209 * GetModuleBaseNameW (kernelbase.@)
1210 * K32GetModuleBaseNameW (kernelbase.@)
1212 DWORD WINAPI DECLSPEC_HOTPATCH GetModuleBaseNameW( HANDLE process, HMODULE module,
1213 WCHAR *name, DWORD size )
1215 BOOL wow64;
1217 if (!IsWow64Process( process, &wow64 )) return 0;
1219 if (is_win64 && wow64)
1221 LDR_DATA_TABLE_ENTRY32 ldr_module32;
1223 if (!get_ldr_module32(process, module, &ldr_module32)) return 0;
1224 size = min( ldr_module32.BaseDllName.Length / sizeof(WCHAR), size );
1225 if (!ReadProcessMemory( process, (void *)(DWORD_PTR)ldr_module32.BaseDllName.Buffer,
1226 name, size * sizeof(WCHAR), NULL ))
1227 return 0;
1229 else
1231 LDR_DATA_TABLE_ENTRY ldr_module;
1233 if (!get_ldr_module( process, module, &ldr_module )) return 0;
1234 size = min( ldr_module.BaseDllName.Length / sizeof(WCHAR), size );
1235 if (!ReadProcessMemory( process, ldr_module.BaseDllName.Buffer,
1236 name, size * sizeof(WCHAR), NULL ))
1237 return 0;
1239 name[size] = 0;
1240 return size;
1244 /***********************************************************************
1245 * GetModuleFileNameExA (kernelbase.@)
1246 * K32GetModuleFileNameExA (kernelbase.@)
1248 DWORD WINAPI DECLSPEC_HOTPATCH GetModuleFileNameExA( HANDLE process, HMODULE module,
1249 char *name, DWORD size )
1251 WCHAR *ptr;
1252 DWORD len;
1254 TRACE( "(process=%p, module=%p, %p, %d)\n", process, module, name, size );
1256 if (!name || !size)
1258 SetLastError( ERROR_INVALID_PARAMETER );
1259 return 0;
1261 if (process == GetCurrentProcess())
1263 len = GetModuleFileNameA( module, name, size );
1264 name[size - 1] = '\0';
1265 return len;
1268 if (!(ptr = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return 0;
1269 len = GetModuleFileNameExW( process, module, ptr, size );
1270 if (!len)
1272 name[0] = 0;
1274 else
1276 if (!WideCharToMultiByte( CP_ACP, 0, ptr, -1, name, size, NULL, NULL ))
1278 name[size - 1] = 0;
1279 len = size;
1281 else if (len < size) len = strlen( name );
1283 HeapFree( GetProcessHeap(), 0, ptr );
1284 return len;
1288 /***********************************************************************
1289 * GetModuleFileNameExW (kernelbase.@)
1290 * K32GetModuleFileNameExW (kernelbase.@)
1292 DWORD WINAPI DECLSPEC_HOTPATCH GetModuleFileNameExW( HANDLE process, HMODULE module,
1293 WCHAR *name, DWORD size )
1295 BOOL wow64;
1296 DWORD len;
1298 if (!size) return 0;
1300 if (!IsWow64Process( process, &wow64 )) return 0;
1302 if (is_win64 && wow64)
1304 LDR_DATA_TABLE_ENTRY32 ldr_module32;
1306 if (!get_ldr_module32( process, module, &ldr_module32 )) return 0;
1307 len = ldr_module32.FullDllName.Length / sizeof(WCHAR);
1308 if (!ReadProcessMemory( process, (void *)(DWORD_PTR)ldr_module32.FullDllName.Buffer,
1309 name, min( len, size ) * sizeof(WCHAR), NULL ))
1310 return 0;
1312 else
1314 LDR_DATA_TABLE_ENTRY ldr_module;
1316 if (!get_ldr_module(process, module, &ldr_module)) return 0;
1317 len = ldr_module.FullDllName.Length / sizeof(WCHAR);
1318 if (!ReadProcessMemory( process, ldr_module.FullDllName.Buffer,
1319 name, min( len, size ) * sizeof(WCHAR), NULL ))
1320 return 0;
1323 if (len < size)
1325 name[len] = 0;
1326 return len;
1328 else
1330 name[size - 1] = 0;
1331 return size;
1336 /***********************************************************************
1337 * GetModuleInformation (kernelbase.@)
1338 * K32GetModuleInformation (kernelbase.@)
1340 BOOL WINAPI GetModuleInformation( HANDLE process, HMODULE module, MODULEINFO *modinfo, DWORD count )
1342 BOOL wow64;
1344 if (count < sizeof(MODULEINFO))
1346 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1347 return FALSE;
1350 if (!IsWow64Process( process, &wow64 )) return FALSE;
1352 if (is_win64 && wow64)
1354 LDR_DATA_TABLE_ENTRY32 ldr_module32;
1356 if (!get_ldr_module32( process, module, &ldr_module32 )) return FALSE;
1357 modinfo->lpBaseOfDll = (void *)(DWORD_PTR)ldr_module32.BaseAddress;
1358 modinfo->SizeOfImage = ldr_module32.SizeOfImage;
1359 modinfo->EntryPoint = (void *)(DWORD_PTR)ldr_module32.EntryPoint;
1361 else
1363 LDR_DATA_TABLE_ENTRY ldr_module;
1365 if (!get_ldr_module( process, module, &ldr_module )) return FALSE;
1366 modinfo->lpBaseOfDll = ldr_module.DllBase;
1367 modinfo->SizeOfImage = ldr_module.SizeOfImage;
1368 modinfo->EntryPoint = ldr_module.EntryPoint;
1370 return TRUE;
1374 /***********************************************************************
1375 * GetPerformanceInfo (kernelbase.@)
1376 * K32GetPerformanceInfo (kernelbase.@)
1378 BOOL WINAPI DECLSPEC_HOTPATCH GetPerformanceInfo( PPERFORMANCE_INFORMATION info, DWORD size )
1380 SYSTEM_PERFORMANCE_INFORMATION perf;
1381 SYSTEM_BASIC_INFORMATION basic;
1382 SYSTEM_PROCESS_INFORMATION *process, *spi;
1383 DWORD info_size;
1384 NTSTATUS status;
1386 TRACE( "(%p, %d)\n", info, size );
1388 if (size < sizeof(*info))
1390 SetLastError( ERROR_BAD_LENGTH );
1391 return FALSE;
1394 status = NtQuerySystemInformation( SystemPerformanceInformation, &perf, sizeof(perf), NULL );
1395 if (!set_ntstatus( status )) return FALSE;
1396 status = NtQuerySystemInformation( SystemBasicInformation, &basic, sizeof(basic), NULL );
1397 if (!set_ntstatus( status )) return FALSE;
1399 info->cb = sizeof(*info);
1400 info->CommitTotal = perf.TotalCommittedPages;
1401 info->CommitLimit = perf.TotalCommitLimit;
1402 info->CommitPeak = perf.PeakCommitment;
1403 info->PhysicalTotal = basic.MmNumberOfPhysicalPages;
1404 info->PhysicalAvailable = perf.AvailablePages;
1405 info->SystemCache = 0;
1406 info->KernelTotal = perf.PagedPoolUsage + perf.NonPagedPoolUsage;
1407 info->KernelPaged = perf.PagedPoolUsage;
1408 info->KernelNonpaged = perf.NonPagedPoolUsage;
1409 info->PageSize = basic.PageSize;
1411 /* fields from SYSTEM_PROCESS_INFORMATION */
1412 NtQuerySystemInformation( SystemProcessInformation, NULL, 0, &info_size );
1413 for (;;)
1415 process = HeapAlloc( GetProcessHeap(), 0, info_size );
1416 if (!process)
1418 SetLastError( ERROR_OUTOFMEMORY );
1419 return FALSE;
1421 status = NtQuerySystemInformation( SystemProcessInformation, process, info_size, &info_size );
1422 if (!status) break;
1423 HeapFree( GetProcessHeap(), 0, process );
1424 if (status != STATUS_INFO_LENGTH_MISMATCH)
1426 SetLastError( RtlNtStatusToDosError( status ) );
1427 return FALSE;
1430 info->HandleCount = info->ProcessCount = info->ThreadCount = 0;
1431 spi = process;
1432 for (;;)
1434 info->ProcessCount++;
1435 info->HandleCount += spi->HandleCount;
1436 info->ThreadCount += spi->dwThreadCount;
1437 if (spi->NextEntryOffset == 0) break;
1438 spi = (SYSTEM_PROCESS_INFORMATION *)((char *)spi + spi->NextEntryOffset);
1440 HeapFree( GetProcessHeap(), 0, process );
1441 return TRUE;
1445 /***********************************************************************
1446 * GetProcessImageFileNameA (kernelbase.@)
1447 * K32GetProcessImageFileNameA (kernelbase.@)
1449 DWORD WINAPI DECLSPEC_HOTPATCH GetProcessImageFileNameA( HANDLE process, char *file, DWORD size )
1451 return QueryFullProcessImageNameA( process, PROCESS_NAME_NATIVE, file, &size ) ? size : 0;
1455 /***********************************************************************
1456 * GetProcessImageFileNameW (kernelbase.@)
1457 * K32GetProcessImageFileNameW (kernelbase.@)
1459 DWORD WINAPI DECLSPEC_HOTPATCH GetProcessImageFileNameW( HANDLE process, WCHAR *file, DWORD size )
1461 return QueryFullProcessImageNameW( process, PROCESS_NAME_NATIVE, file, &size ) ? size : 0;
1465 /***********************************************************************
1466 * GetProcessMemoryInfo (kernelbase.@)
1467 * K32GetProcessMemoryInfo (kernelbase.@)
1469 BOOL WINAPI DECLSPEC_HOTPATCH GetProcessMemoryInfo( HANDLE process, PROCESS_MEMORY_COUNTERS *pmc,
1470 DWORD count )
1472 VM_COUNTERS vmc;
1474 if (count < sizeof(PROCESS_MEMORY_COUNTERS))
1476 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1477 return FALSE;
1480 if (!set_ntstatus( NtQueryInformationProcess( process, ProcessVmCounters, &vmc, sizeof(vmc), NULL )))
1481 return FALSE;
1483 pmc->cb = sizeof(PROCESS_MEMORY_COUNTERS);
1484 pmc->PageFaultCount = vmc.PageFaultCount;
1485 pmc->PeakWorkingSetSize = vmc.PeakWorkingSetSize;
1486 pmc->WorkingSetSize = vmc.WorkingSetSize;
1487 pmc->QuotaPeakPagedPoolUsage = vmc.QuotaPeakPagedPoolUsage;
1488 pmc->QuotaPagedPoolUsage = vmc.QuotaPagedPoolUsage;
1489 pmc->QuotaPeakNonPagedPoolUsage = vmc.QuotaPeakNonPagedPoolUsage;
1490 pmc->QuotaNonPagedPoolUsage = vmc.QuotaNonPagedPoolUsage;
1491 pmc->PagefileUsage = vmc.PagefileUsage;
1492 pmc->PeakPagefileUsage = vmc.PeakPagefileUsage;
1493 return TRUE;
1497 /***********************************************************************
1498 * GetWsChanges (kernelbase.@)
1499 * K32GetWsChanges (kernelbase.@)
1501 BOOL WINAPI DECLSPEC_HOTPATCH GetWsChanges( HANDLE process, PSAPI_WS_WATCH_INFORMATION *info, DWORD size )
1503 TRACE( "(%p, %p, %d)\n", process, info, size );
1504 return set_ntstatus( NtQueryInformationProcess( process, ProcessWorkingSetWatch, info, size, NULL ));
1508 /***********************************************************************
1509 * GetWsChangesEx (kernelbase.@)
1510 * K32GetWsChangesEx (kernelbase.@)
1512 BOOL WINAPI DECLSPEC_HOTPATCH GetWsChangesEx( HANDLE process, PSAPI_WS_WATCH_INFORMATION_EX *info,
1513 DWORD *size )
1515 FIXME( "(%p, %p, %p)\n", process, info, size );
1516 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
1517 return FALSE;
1521 /***********************************************************************
1522 * InitializeProcessForWsWatch (kernelbase.@)
1523 * K32InitializeProcessForWsWatch (kernelbase.@)
1525 BOOL WINAPI /* DECLSPEC_HOTPATCH */ InitializeProcessForWsWatch( HANDLE process )
1527 FIXME( "(process=%p): stub\n", process );
1528 return TRUE;
1532 /***********************************************************************
1533 * QueryWorkingSet (kernelbase.@)
1534 * K32QueryWorkingSet (kernelbase.@)
1536 BOOL WINAPI DECLSPEC_HOTPATCH QueryWorkingSet( HANDLE process, void *buffer, DWORD size )
1538 TRACE( "(%p, %p, %d)\n", process, buffer, size );
1539 return set_ntstatus( NtQueryVirtualMemory( process, NULL, MemoryWorkingSetList, buffer, size, NULL ));
1543 /***********************************************************************
1544 * QueryWorkingSetEx (kernelbase.@)
1545 * K32QueryWorkingSetEx (kernelbase.@)
1547 BOOL WINAPI QueryWorkingSetEx( HANDLE process, void *buffer, DWORD size )
1549 TRACE( "(%p, %p, %d)\n", process, buffer, size );
1550 return set_ntstatus( NtQueryVirtualMemory( process, NULL, MemoryWorkingSetExInformation,
1551 buffer, size, NULL ));
1555 /******************************************************************
1556 * QueryFullProcessImageNameA (kernelbase.@)
1558 BOOL WINAPI DECLSPEC_HOTPATCH QueryFullProcessImageNameA( HANDLE process, DWORD flags,
1559 char *name, DWORD *size )
1561 BOOL ret;
1562 DWORD sizeW = *size;
1563 WCHAR *nameW = HeapAlloc( GetProcessHeap(), 0, *size * sizeof(WCHAR) );
1565 ret = QueryFullProcessImageNameW( process, flags, nameW, &sizeW );
1566 if (ret) ret = (WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, *size, NULL, NULL) > 0);
1567 if (ret) *size = strlen( name );
1568 HeapFree( GetProcessHeap(), 0, nameW );
1569 return ret;
1573 /******************************************************************
1574 * QueryFullProcessImageNameW (kernelbase.@)
1576 BOOL WINAPI DECLSPEC_HOTPATCH QueryFullProcessImageNameW( HANDLE process, DWORD flags,
1577 WCHAR *name, DWORD *size )
1579 BYTE buffer[sizeof(UNICODE_STRING) + MAX_PATH*sizeof(WCHAR)]; /* this buffer should be enough */
1580 UNICODE_STRING *dynamic_buffer = NULL;
1581 UNICODE_STRING *result = NULL;
1582 NTSTATUS status;
1583 DWORD needed;
1585 /* FIXME: Use ProcessImageFileName for the PROCESS_NAME_NATIVE case */
1586 status = NtQueryInformationProcess( process, ProcessImageFileNameWin32, buffer,
1587 sizeof(buffer) - sizeof(WCHAR), &needed );
1588 if (status == STATUS_INFO_LENGTH_MISMATCH)
1590 dynamic_buffer = HeapAlloc( GetProcessHeap(), 0, needed + sizeof(WCHAR) );
1591 status = NtQueryInformationProcess( process, ProcessImageFileNameWin32, dynamic_buffer,
1592 needed, &needed );
1593 result = dynamic_buffer;
1595 else
1596 result = (UNICODE_STRING *)buffer;
1598 if (status) goto cleanup;
1600 if (flags & PROCESS_NAME_NATIVE)
1602 WCHAR drive[3];
1603 WCHAR device[1024];
1604 DWORD ntlen, devlen;
1606 if (result->Buffer[1] != ':' || result->Buffer[0] < 'A' || result->Buffer[0] > 'Z')
1608 /* We cannot convert it to an NT device path so fail */
1609 status = STATUS_NO_SUCH_DEVICE;
1610 goto cleanup;
1613 /* Find this drive's NT device path */
1614 drive[0] = result->Buffer[0];
1615 drive[1] = ':';
1616 drive[2] = 0;
1617 if (!QueryDosDeviceW(drive, device, ARRAY_SIZE(device)))
1619 status = STATUS_NO_SUCH_DEVICE;
1620 goto cleanup;
1623 devlen = lstrlenW(device);
1624 ntlen = devlen + (result->Length/sizeof(WCHAR) - 2);
1625 if (ntlen + 1 > *size)
1627 status = STATUS_BUFFER_TOO_SMALL;
1628 goto cleanup;
1630 *size = ntlen;
1632 memcpy( name, device, devlen * sizeof(*device) );
1633 memcpy( name + devlen, result->Buffer + 2, result->Length - 2 * sizeof(WCHAR) );
1634 name[*size] = 0;
1635 TRACE( "NT path: %s\n", debugstr_w(name) );
1637 else
1639 if (result->Length/sizeof(WCHAR) + 1 > *size)
1641 status = STATUS_BUFFER_TOO_SMALL;
1642 goto cleanup;
1645 *size = result->Length/sizeof(WCHAR);
1646 memcpy( name, result->Buffer, result->Length );
1647 name[*size] = 0;
1650 cleanup:
1651 HeapFree( GetProcessHeap(), 0, dynamic_buffer );
1652 return set_ntstatus( status );