/*********************************************************************** * init_user_process_params * * Fill the RTL_USER_PROCESS_PARAMETERS structure from the server. */ static NTSTATUS init_user_process_params( SIZE_T data_size, HANDLE *exe_file ) { void *ptr; WCHAR *src, *dst; SIZE_T info_size, env_size, size, alloc_size; NTSTATUS status; startup_info_t *info; RTL_USER_PROCESS_PARAMETERS *params = NULL; if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, data_size ))) return STATUS_NO_MEMORY; SERVER_START_REQ( get_startup_info ) { wine_server_set_reply( req, info, data_size ); if (!(status = wine_server_call( req ))) { data_size = wine_server_reply_size( reply ); info_size = reply->info_size; env_size = data_size - info_size; *exe_file = wine_server_ptr_handle( reply->exe_file ); } } SERVER_END_REQ; if (status != STATUS_SUCCESS) goto done; size = sizeof(*params); size += MAX_NT_PATH_LENGTH * sizeof(WCHAR); size += info->dllpath_len + sizeof(WCHAR); size += info->imagepath_len + sizeof(WCHAR); size += info->cmdline_len + sizeof(WCHAR); size += info->title_len + sizeof(WCHAR); size += info->desktop_len + sizeof(WCHAR); size += info->shellinfo_len + sizeof(WCHAR); size += info->runtime_len + sizeof(WCHAR); alloc_size = size; status = NtAllocateVirtualMemory( NtCurrentProcess(), (void **)¶ms, 0, &alloc_size, MEM_COMMIT, PAGE_READWRITE ); if (status != STATUS_SUCCESS) goto done; NtCurrentTeb()->Peb->ProcessParameters = params; params->AllocationSize = alloc_size; params->Size = size; params->Flags = PROCESS_PARAMS_FLAG_NORMALIZED; params->DebugFlags = info->debug_flags; params->ConsoleHandle = wine_server_ptr_handle( info->console ); params->ConsoleFlags = info->console_flags; params->hStdInput = wine_server_ptr_handle( info->hstdin ); params->hStdOutput = wine_server_ptr_handle( info->hstdout ); params->hStdError = wine_server_ptr_handle( info->hstderr ); params->dwX = info->x; params->dwY = info->y; params->dwXSize = info->xsize; params->dwYSize = info->ysize; params->dwXCountChars = info->xchars; params->dwYCountChars = info->ychars; params->dwFillAttribute = info->attribute; params->dwFlags = info->flags; params->wShowWindow = info->show; src = (WCHAR *)(info + 1); dst = (WCHAR *)(params + 1); /* current directory needs more space */ get_unicode_string( ¶ms->CurrentDirectory.DosPath, &src, &dst, info->curdir_len ); params->CurrentDirectory.DosPath.MaximumLength = MAX_NT_PATH_LENGTH * sizeof(WCHAR); dst = (WCHAR *)(params + 1) + MAX_NT_PATH_LENGTH; get_unicode_string( ¶ms->DllPath, &src, &dst, info->dllpath_len ); get_unicode_string( ¶ms->ImagePathName, &src, &dst, info->imagepath_len ); get_unicode_string( ¶ms->CommandLine, &src, &dst, info->cmdline_len ); get_unicode_string( ¶ms->WindowTitle, &src, &dst, info->title_len ); get_unicode_string( ¶ms->Desktop, &src, &dst, info->desktop_len ); get_unicode_string( ¶ms->ShellInfo, &src, &dst, info->shellinfo_len ); /* runtime info isn't a real string */ params->RuntimeInfo.Buffer = dst; params->RuntimeInfo.Length = params->RuntimeInfo.MaximumLength = info->runtime_len; memcpy( dst, src, info->runtime_len ); /* environment needs to be a separate memory block */ ptr = NULL; alloc_size = max( 1, env_size ); status = NtAllocateVirtualMemory( NtCurrentProcess(), &ptr, 0, &alloc_size, MEM_COMMIT, PAGE_READWRITE ); if (status != STATUS_SUCCESS) goto done; memcpy( ptr, (char *)info + info_size, env_size ); params->Environment = ptr; done: RtlFreeHeap( GetProcessHeap(), 0, info ); return status; }
/*********************************************************************** * GetUserObjectInformationW (USER32.@) */ BOOL WINAPI GetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed ) { static const WCHAR desktopW[] = { 'D','e','s','k','t','o','p',0 }; static const WCHAR winstationW[] = { 'W','i','n','d','o','w','S','t','a','t','i','o','n',0 }; BOOL ret; switch(index) { case UOI_FLAGS: { USEROBJECTFLAGS *obj_flags = info; if (needed) *needed = sizeof(*obj_flags); if (len < sizeof(*obj_flags)) { SetLastError( ERROR_BUFFER_OVERFLOW ); return FALSE; } SERVER_START_REQ( set_user_object_info ) { req->handle = wine_server_obj_handle( handle ); req->flags = 0; ret = !wine_server_call_err( req ); if (ret) { /* FIXME: inherit flag */ obj_flags->dwFlags = reply->old_obj_flags; } } SERVER_END_REQ; } return ret; case UOI_TYPE: SERVER_START_REQ( set_user_object_info ) { req->handle = wine_server_obj_handle( handle ); req->flags = 0; ret = !wine_server_call_err( req ); if (ret) { size_t size = reply->is_desktop ? sizeof(desktopW) : sizeof(winstationW); if (needed) *needed = size; if (len < size) { SetLastError( ERROR_INSUFFICIENT_BUFFER ); ret = FALSE; } else memcpy( info, reply->is_desktop ? desktopW : winstationW, size ); } } SERVER_END_REQ; return ret; case UOI_NAME: { WCHAR buffer[MAX_PATH]; SERVER_START_REQ( set_user_object_info ) { req->handle = wine_server_obj_handle( handle ); req->flags = 0; wine_server_set_reply( req, buffer, sizeof(buffer) - sizeof(WCHAR) ); ret = !wine_server_call_err( req ); if (ret) { size_t size = wine_server_reply_size( reply ); buffer[size / sizeof(WCHAR)] = 0; size += sizeof(WCHAR); if (needed) *needed = size; if (len < size) { SetLastError( ERROR_INSUFFICIENT_BUFFER ); ret = FALSE; } else memcpy( info, buffer, size ); } } SERVER_END_REQ; } return ret; case UOI_USER_SID: FIXME( "not supported index %d\n", index ); /* fall through */ default: SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } }
/****************************************************************************** * WaitForDebugEvent (KERNEL32.@) * * Waits for a debugging event to occur in a process being debugged before * filling out the debug event structure. * * PARAMS * event [O] Address of structure for event information. * timeout [I] Number of milliseconds to wait for event. * * RETURNS * * Returns true if a debug event occurred and false if the call timed out. */ BOOL WINAPI WaitForDebugEvent( LPDEBUG_EVENT event, DWORD timeout) { BOOL ret; DWORD res; int i; for (;;) { HANDLE wait = 0; debug_event_t data; SERVER_START_REQ( wait_debug_event ) { req->get_handle = (timeout != 0); wine_server_set_reply( req, &data, sizeof(data) ); if (!(ret = !wine_server_call_err( req ))) goto done; if (!wine_server_reply_size(reply)) /* timeout */ { wait = wine_server_ptr_handle( reply->wait ); ret = FALSE; goto done; } event->dwDebugEventCode = data.code; event->dwProcessId = (DWORD)reply->pid; event->dwThreadId = (DWORD)reply->tid; switch(data.code) { case EXCEPTION_DEBUG_EVENT: if (data.exception.exc_code == DBG_PRINTEXCEPTION_C && data.exception.nb_params >= 2) { event->dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT; event->u.DebugString.lpDebugStringData = wine_server_get_ptr( data.exception.params[1] ); event->u.DebugString.fUnicode = FALSE; event->u.DebugString.nDebugStringLength = data.exception.params[0]; break; } else if (data.exception.exc_code == DBG_RIPEXCEPTION && data.exception.nb_params >= 2) { event->dwDebugEventCode = RIP_EVENT; event->u.RipInfo.dwError = data.exception.params[0]; event->u.RipInfo.dwType = data.exception.params[1]; break; } event->u.Exception.dwFirstChance = data.exception.first; event->u.Exception.ExceptionRecord.ExceptionCode = data.exception.exc_code; event->u.Exception.ExceptionRecord.ExceptionFlags = data.exception.flags; event->u.Exception.ExceptionRecord.ExceptionRecord = wine_server_get_ptr( data.exception.record ); event->u.Exception.ExceptionRecord.ExceptionAddress = wine_server_get_ptr( data.exception.address ); event->u.Exception.ExceptionRecord.NumberParameters = data.exception.nb_params; for (i = 0; i < data.exception.nb_params; i++) event->u.Exception.ExceptionRecord.ExceptionInformation[i] = data.exception.params[i]; break; case CREATE_THREAD_DEBUG_EVENT: event->u.CreateThread.hThread = wine_server_ptr_handle( data.create_thread.handle ); event->u.CreateThread.lpThreadLocalBase = wine_server_get_ptr( data.create_thread.teb ); event->u.CreateThread.lpStartAddress = wine_server_get_ptr( data.create_thread.start ); break; case CREATE_PROCESS_DEBUG_EVENT: event->u.CreateProcessInfo.hFile = wine_server_ptr_handle( data.create_process.file ); event->u.CreateProcessInfo.hProcess = wine_server_ptr_handle( data.create_process.process ); event->u.CreateProcessInfo.hThread = wine_server_ptr_handle( data.create_process.thread ); event->u.CreateProcessInfo.lpBaseOfImage = wine_server_get_ptr( data.create_process.base ); event->u.CreateProcessInfo.dwDebugInfoFileOffset = data.create_process.dbg_offset; event->u.CreateProcessInfo.nDebugInfoSize = data.create_process.dbg_size; event->u.CreateProcessInfo.lpThreadLocalBase = wine_server_get_ptr( data.create_process.teb ); event->u.CreateProcessInfo.lpStartAddress = wine_server_get_ptr( data.create_process.start ); event->u.CreateProcessInfo.lpImageName = wine_server_get_ptr( data.create_process.name ); event->u.CreateProcessInfo.fUnicode = data.create_process.unicode; break; case EXIT_THREAD_DEBUG_EVENT: event->u.ExitThread.dwExitCode = data.exit.exit_code; break; case EXIT_PROCESS_DEBUG_EVENT: event->u.ExitProcess.dwExitCode = data.exit.exit_code; break; case LOAD_DLL_DEBUG_EVENT: event->u.LoadDll.hFile = wine_server_ptr_handle( data.load_dll.handle ); event->u.LoadDll.lpBaseOfDll = wine_server_get_ptr( data.load_dll.base ); event->u.LoadDll.dwDebugInfoFileOffset = data.load_dll.dbg_offset; event->u.LoadDll.nDebugInfoSize = data.load_dll.dbg_size; event->u.LoadDll.lpImageName = wine_server_get_ptr( data.load_dll.name ); event->u.LoadDll.fUnicode = data.load_dll.unicode; break; case UNLOAD_DLL_DEBUG_EVENT: event->u.UnloadDll.lpBaseOfDll = wine_server_get_ptr( data.unload_dll.base ); break; } done: /* nothing */ ; } SERVER_END_REQ; if (ret) return TRUE; if (!wait) break; res = WaitForSingleObject( wait, timeout ); CloseHandle( wait ); if (res != STATUS_WAIT_0) break; } SetLastError( ERROR_SEM_TIMEOUT ); return FALSE; }