This is an alternate solution to avoid creating shared memory and thread in the server. A new service is introduced and started as early as possible. It will setup read-only shared memory for other processes when they request it through an ioctl, initializing the pages with the provided data, and then update the timestamps there on a regular basis.
If the service is not yet started - which can happen for the initial processes and other services, then the process uses the current user shared data implementation, where no timestamp update is done.
Andrew Wesie (1): ntdll/tests: Test updating TickCount in user_shared_data.
Rémi Bernon (2): wineusd.sys: Add new service to update user shared data continuously. ntdll: Use the new WineUsd service to map user shared data.
configure.ac | 1 + dlls/ntdll/ntdll_misc.h | 1 + dlls/ntdll/server.c | 2 + dlls/ntdll/tests/time.c | 26 +++ dlls/ntdll/thread.c | 34 ++++ dlls/wineusd.sys/Makefile.in | 6 + dlls/wineusd.sys/wineusd.sys.spec | 1 + dlls/wineusd.sys/wineusd_main.c | 274 ++++++++++++++++++++++++++++++ include/wine/usd.h | 27 +++ loader/wine.inf.in | 12 ++ 10 files changed, 384 insertions(+) create mode 100644 dlls/wineusd.sys/Makefile.in create mode 100644 dlls/wineusd.sys/wineusd.sys.spec create mode 100644 dlls/wineusd.sys/wineusd_main.c create mode 100644 include/wine/usd.h
From: Andrew Wesie awesie@gmail.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/tests/time.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
diff --git a/dlls/ntdll/tests/time.c b/dlls/ntdll/tests/time.c index 5382a952d8d..be6859fe3e1 100644 --- a/dlls/ntdll/tests/time.c +++ b/dlls/ntdll/tests/time.c @@ -18,7 +18,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#define NONAMELESSUNION #include "ntdll_test.h" +#include "ddk/wdm.h"
#define TICKSPERSEC 10000000 #define TICKSPERMSEC 10000 @@ -29,6 +31,7 @@ static VOID (WINAPI *pRtlTimeFieldsToTime)( PTIME_FIELDS TimeFields, PLARGE_IN static NTSTATUS (WINAPI *pNtQueryPerformanceCounter)( LARGE_INTEGER *counter, LARGE_INTEGER *frequency ); static NTSTATUS (WINAPI *pRtlQueryTimeZoneInformation)( RTL_TIME_ZONE_INFORMATION *); static NTSTATUS (WINAPI *pRtlQueryDynamicTimeZoneInformation)( RTL_DYNAMIC_TIME_ZONE_INFORMATION *); +static ULONG (WINAPI *pNtGetTickCount)(void);
static const int MonthLengths[2][12] = { @@ -153,12 +156,35 @@ static void test_RtlQueryTimeZoneInformation(void) wine_dbgstr_w(tzinfo.DaylightName)); }
+static void test_NtGetTickCount(void) +{ + KSHARED_USER_DATA *user_shared_data = (void *)0x7ffe0000; + LONG diff; + int i; + + if (!pNtGetTickCount) + { + win_skip("NtGetTickCount is not available\n"); + return; + } + + for (i = 0; i < 5; ++i) + { + diff = (user_shared_data->u.TickCountQuad * user_shared_data->TickCountMultiplier) >> 24; + diff = pNtGetTickCount() - diff; + todo_wine + ok(diff < 100, "NtGetTickCount - TickCountQuad too high, expected < 100 got %d\n", diff); + Sleep(50); + } +} + START_TEST(time) { HMODULE mod = GetModuleHandleA("ntdll.dll"); pRtlTimeToTimeFields = (void *)GetProcAddress(mod,"RtlTimeToTimeFields"); pRtlTimeFieldsToTime = (void *)GetProcAddress(mod,"RtlTimeFieldsToTime"); pNtQueryPerformanceCounter = (void *)GetProcAddress(mod, "NtQueryPerformanceCounter"); + pNtGetTickCount = (void *)GetProcAddress(mod,"NtGetTickCount"); pRtlQueryTimeZoneInformation = (void *)GetProcAddress(mod, "RtlQueryTimeZoneInformation"); pRtlQueryDynamicTimeZoneInformation = @@ -169,5 +195,6 @@ START_TEST(time) else win_skip("Required time conversion functions are not available\n"); test_NtQueryPerformanceCounter(); + test_NtGetTickCount(); test_RtlQueryTimeZoneInformation(); }
This service is started at boot, and hopefully before any process that might rely on the timestamp update. If the service is not yet started, then the opening the device will fail and the process should continue and use its private user shared data instead.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- configure.ac | 1 + dlls/wineusd.sys/Makefile.in | 6 + dlls/wineusd.sys/wineusd.sys.spec | 1 + dlls/wineusd.sys/wineusd_main.c | 274 ++++++++++++++++++++++++++++++ include/wine/usd.h | 27 +++ loader/wine.inf.in | 12 ++ 6 files changed, 321 insertions(+) create mode 100644 dlls/wineusd.sys/Makefile.in create mode 100644 dlls/wineusd.sys/wineusd.sys.spec create mode 100644 dlls/wineusd.sys/wineusd_main.c create mode 100644 include/wine/usd.h
diff --git a/configure.ac b/configure.ac index 64721e96449..b1463d69823 100644 --- a/configure.ac +++ b/configure.ac @@ -3793,6 +3793,7 @@ WINE_CONFIG_MAKEFILE(dlls/wineps.drv) WINE_CONFIG_MAKEFILE(dlls/wineps16.drv16,enable_win16) WINE_CONFIG_MAKEFILE(dlls/winepulse.drv) WINE_CONFIG_MAKEFILE(dlls/wineqtdecoder) +WINE_CONFIG_MAKEFILE(dlls/wineusd.sys) WINE_CONFIG_MAKEFILE(dlls/winevulkan) WINE_CONFIG_MAKEFILE(dlls/winex11.drv) WINE_CONFIG_MAKEFILE(dlls/wing.dll16,enable_win16) diff --git a/dlls/wineusd.sys/Makefile.in b/dlls/wineusd.sys/Makefile.in new file mode 100644 index 00000000000..0792860c09b --- /dev/null +++ b/dlls/wineusd.sys/Makefile.in @@ -0,0 +1,6 @@ +MODULE = wineusd.sys +IMPORTS = ntoskrnl +EXTRADLLFLAGS = -Wl,--subsystem,native -mno-cygwin + +C_SRCS = \ + wineusd_main.c diff --git a/dlls/wineusd.sys/wineusd.sys.spec b/dlls/wineusd.sys/wineusd.sys.spec new file mode 100644 index 00000000000..76421d7e35b --- /dev/null +++ b/dlls/wineusd.sys/wineusd.sys.spec @@ -0,0 +1 @@ +# nothing to export diff --git a/dlls/wineusd.sys/wineusd_main.c b/dlls/wineusd.sys/wineusd_main.c new file mode 100644 index 00000000000..f4f1132e24c --- /dev/null +++ b/dlls/wineusd.sys/wineusd_main.c @@ -0,0 +1,274 @@ +/* + * User shared data update service + * + * Copyright 2019 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <assert.h> +#include <stdarg.h> +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "winternl.h" +#include "winioctl.h" +#include "ddk/wdm.h" +#include "wine/debug.h" +#include "wine/heap.h" +#include "wine/usd.h" +#include "wine/list.h" + +static DEVICE_OBJECT *device_obj; + +WINE_DEFAULT_DEBUG_CHANNEL(wineusd); + +#define DECLARE_CRITICAL_SECTION(cs) \ + static CRITICAL_SECTION cs; \ + static CRITICAL_SECTION_DEBUG cs##_debug = \ + { 0, 0, &cs, { &cs##_debug.ProcessLocksList, &cs##_debug.ProcessLocksList }, \ + 0, 0, { (DWORD_PTR)(__FILE__ ": " # cs) }}; \ + static CRITICAL_SECTION cs = { &cs##_debug, -1, 0, 0, 0, 0 }; + +DECLARE_CRITICAL_SECTION(wineusd_cs); + +static struct list wineusd_entries = LIST_INIT(wineusd_entries); +static HANDLE wineusd_thread, wineusd_thread_stop; + +struct wineusd_entry +{ + struct list link; + CLIENT_ID cid; + HANDLE process; + HANDLE section; + void *page; +}; + +static DWORD WINAPI wineusd_thread_proc(void *arg) +{ + struct wineusd_entry *entry; + ULARGE_INTEGER interrupt; + ULARGE_INTEGER tick; + LARGE_INTEGER now; + + TRACE("Started user shared data thread.\n"); + + while (WaitForSingleObject(wineusd_thread_stop, 16) == WAIT_TIMEOUT) + { + EnterCriticalSection(&wineusd_cs); + + NtQuerySystemTime(&now); + RtlQueryUnbiasedInterruptTime(&interrupt.QuadPart); + + tick = interrupt; + tick.QuadPart /= 10000; + + LIST_FOR_EACH_ENTRY(entry, &wineusd_entries, struct wineusd_entry, link) + { + KSHARED_USER_DATA *usd = entry->page; + + usd->SystemTime.High2Time = now.u.HighPart; + usd->SystemTime.LowPart = now.u.LowPart; + usd->SystemTime.High1Time = now.u.HighPart; + + usd->InterruptTime.High2Time = interrupt.HighPart; + usd->InterruptTime.LowPart = interrupt.LowPart; + usd->InterruptTime.High1Time = interrupt.HighPart; + + usd->TickCount.High2Time = tick.HighPart; + usd->TickCount.LowPart = tick.LowPart; + usd->TickCount.High1Time = tick.HighPart; + usd->TickCountLowDeprecated = tick.LowPart; + usd->TickCountMultiplier = 1 << 24; + } + + LeaveCriticalSection(&wineusd_cs); + } + + TRACE("Stopped user shared data thread.\n"); + + return 0; +} + +static NTSTATUS wineusd_initialize(struct wineusd_entry *entry, IRP *irp) +{ + const KSHARED_USER_DATA *init = irp->AssociatedIrp.SystemBuffer; + void *user_shared_data_address = (void *)0x7ffe0000; + NTSTATUS status = STATUS_SUCCESS; + LARGE_INTEGER section_size; + SIZE_T view_size; + + entry->cid.UniqueProcess = PsGetCurrentProcessId(); + entry->cid.UniqueThread = (HANDLE)0; + if ((status = NtOpenProcess(&entry->process, PROCESS_VM_OPERATION, NULL, &entry->cid))) + { + ERR("Failed to open target process, status: %x.\n", status); + return status; + } + + section_size.HighPart = 0; + section_size.LowPart = 0x10000; + if ((status = NtCreateSection(&entry->section, SECTION_ALL_ACCESS, NULL, §ion_size, + PAGE_READWRITE, SEC_COMMIT, NULL))) + { + ERR("Failed to create section, status: %x.\n", status); + return status; + } + + view_size = 0; + if ((status = NtMapViewOfSection(entry->section, NtCurrentProcess(), &entry->page, 0, 0, 0, + &view_size, ViewShare, 0, PAGE_READWRITE))) + { + ERR("Failed to map section to driver memory, status: %x.\n", status); + return status; + } + memcpy(entry->page, init, sizeof(*init)); + + view_size = 0; + if ((status = NtMapViewOfSection(entry->section, entry->process, &user_shared_data_address, 0, 0, 0, + &view_size, ViewShare, 0, PAGE_READONLY))) + { + ERR("Failed to map user shared data to target process, status: %x.\n", status); + return status; + } + + EnterCriticalSection(&wineusd_cs); + list_add_head(&wineusd_entries, &entry->link); + LeaveCriticalSection(&wineusd_cs); + + TRACE("Initialized user shared data for process %04x.\n", HandleToULong(PsGetCurrentProcessId())); + + return STATUS_SUCCESS; +} + +static void wineusd_close(struct wineusd_entry *entry) +{ + void *user_shared_data_address = (void *)0x7ffe0000; + + TRACE("Closing user shared data for process %04x.\n", HandleToULong(entry->cid.UniqueProcess)); + + EnterCriticalSection(&wineusd_cs); + list_remove(&entry->link); + LeaveCriticalSection(&wineusd_cs); + + NtUnmapViewOfSection(entry->process, user_shared_data_address); + NtUnmapViewOfSection(NtCurrentProcess(), entry->page); + + NtClose(entry->section); + NtClose(entry->process); + heap_free(entry); +} + +static NTSTATUS WINAPI wineusd_dispatch_create(DEVICE_OBJECT *device, IRP *irp) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); + struct wineusd_entry *entry; + NTSTATUS status; + + status = STATUS_NO_MEMORY; + if (!(entry = heap_alloc_zero(sizeof(*entry)))) + { + ERR("Failed to allocate memory.\n"); + goto done; + } + stack->FileObject->FsContext = entry; + + list_init(&entry->link); + entry->process = INVALID_HANDLE_VALUE; + entry->section = INVALID_HANDLE_VALUE; + entry->page = NULL; + + TRACE("Created user shared data for process %04x.\n", HandleToULong(PsGetCurrentProcessId())); + +done: + irp->IoStatus.Status = status; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return status; +} + +static NTSTATUS WINAPI wineusd_dispatch_close(DEVICE_OBJECT *device, IRP *irp) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); + struct wineusd_entry *entry = stack->FileObject->FsContext; + + if (entry) wineusd_close(entry); + + irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +static NTSTATUS WINAPI wineusd_dispatch_ioctl(DEVICE_OBJECT *device, IRP *irp) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); + struct wineusd_entry *entry = stack->FileObject->FsContext; + NTSTATUS ret; + + switch (stack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_WINEUSD_INITIALIZE: + ret = wineusd_initialize(entry, irp); + break; + default: + FIXME("Unhandled ioctl %#x.\n", stack->Parameters.DeviceIoControl.IoControlCode); + ret = STATUS_NOT_IMPLEMENTED; + break; + } + + irp->IoStatus.Status = ret; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return ret; +} + +static void WINAPI wineusd_unload(DRIVER_OBJECT *driver) +{ + struct wineusd_entry *entry, *cursor; + + SetEvent(wineusd_thread_stop); + WaitForSingleObject(wineusd_thread, INFINITE); + CloseHandle(wineusd_thread); + CloseHandle(wineusd_thread_stop); + + LIST_FOR_EACH_ENTRY_SAFE(entry, cursor, &wineusd_entries, struct wineusd_entry, link) + wineusd_close(entry); + + IoDeleteDevice(device_obj); +} + +NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *path) +{ + static const WCHAR device_nameW[] = {'\','D','e','v','i','c','e','\','W','i','n','e','U','s','d',0}; + OBJECT_ATTRIBUTES attr = {sizeof(attr)}; + UNICODE_STRING string; + NTSTATUS ret; + + TRACE("Driver %p, path %s.\n", driver, debugstr_w(path->Buffer)); + + RtlInitUnicodeString(&string, device_nameW); + if ((ret = IoCreateDevice(driver, 0, &string, FILE_DEVICE_UNKNOWN, 0, FALSE, &device_obj))) + { + ERR("Failed to create user shared data device, status %#x.\n", ret); + return ret; + } + + driver->MajorFunction[IRP_MJ_CREATE] = wineusd_dispatch_create; + driver->MajorFunction[IRP_MJ_CLOSE] = wineusd_dispatch_close; + driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = wineusd_dispatch_ioctl; + driver->DriverUnload = wineusd_unload; + + wineusd_thread_stop = CreateEventW(NULL, FALSE, FALSE, NULL); + wineusd_thread = CreateThread(NULL, 0, wineusd_thread_proc, NULL, 0, NULL); + + return STATUS_SUCCESS; +} diff --git a/include/wine/usd.h b/include/wine/usd.h new file mode 100644 index 00000000000..e92efa5e29e --- /dev/null +++ b/include/wine/usd.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_WINE_USD_H +#define __WINE_WINE_USD_H + +#include <windef.h> +#include <winioctl.h> + +#define IOCTL_WINEUSD_INITIALIZE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#endif /* __WINE_WINE_USD_H */ diff --git a/loader/wine.inf.in b/loader/wine.inf.in index c0f6e0a3917..4c95c4e7fe2 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -161,6 +161,7 @@ AddService=FontCache3.0.0.0,0,WPFFontCacheService AddService=LanmanServer,0,LanmanServerService AddService=FontCache,0,FontCacheService AddService=Schedule,0,TaskSchedulerService +AddService=WineUsd,0,WineUsdService AddService=Winmgmt,0,WinmgmtService AddService=wuauserv,0,wuauService
@@ -178,6 +179,7 @@ AddService=FontCache3.0.0.0,0,WPFFontCacheService AddService=LanmanServer,0,LanmanServerService AddService=FontCache,0,FontCacheService AddService=Schedule,0,TaskSchedulerService +AddService=WineUsd,0,WineUsdService AddService=Winmgmt,0,WinmgmtService AddService=wuauserv,0,wuauService
@@ -195,6 +197,7 @@ AddService=FontCache3.0.0.0,0,WPFFontCacheService AddService=LanmanServer,0,LanmanServerService AddService=FontCache,0,FontCacheService AddService=Schedule,0,TaskSchedulerService +AddService=WineUsd,0,WineUsdService AddService=Winmgmt,0,WinmgmtService AddService=wuauserv,0,wuauService
@@ -213,6 +216,7 @@ AddService=LanmanServer,0,LanmanServerService AddService=FontCache,0,FontCacheService AddService=Schedule,0,TaskSchedulerService AddService=WineBus,0,WineBusService +AddService=WineUsd,0,WineUsdService AddService=Winmgmt,0,WinmgmtService AddService=wuauserv,0,wuauService
@@ -3641,6 +3645,14 @@ ServiceType=32 StartType=3 ErrorControl=1
+[WineUsdService] +Description="User shared data update service" +DisplayName="Wine User Shared Data" +ServiceBinary="%12%\WineUsd.sys" +ServiceType=1 +StartType=0 +ErrorControl=1 + [WinmgmtService] Description="Provides access to Windows Management Instrumentation" DisplayName="Windows Management Instrumentation Service"
If the device cannot be opened, then the service may not be started yet, or the current process is the service itself. In which case, we can ignore the error and continue as before without timestamp updates.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
Notes: When submitting the patch on testbot, the service was not started and the test failed. It may be the same there and I think the wine.inf update requires a server restart to be accounted for. I'm not sure how to force the new service to start right away.
dlls/ntdll/ntdll_misc.h | 1 + dlls/ntdll/server.c | 2 ++ dlls/ntdll/tests/time.c | 1 - dlls/ntdll/thread.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index ac146941236..e4e2de86a42 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -195,6 +195,7 @@ extern void virtual_set_large_address_space(void) DECLSPEC_HIDDEN; extern void virtual_fill_image_information( const pe_image_info_t *pe_info, SECTION_IMAGE_INFORMATION *info ) DECLSPEC_HIDDEN; extern struct _KUSER_SHARED_DATA *user_shared_data DECLSPEC_HIDDEN; +extern void user_shared_data_init(void);
/* completion */ extern NTSTATUS NTDLL_AddCompletion( HANDLE hFile, ULONG_PTR CompletionValue, diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index 204370a1b77..58d23e3e27e 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -1471,6 +1471,8 @@ void server_init_process_done(void) } SERVER_END_REQ;
+ user_shared_data_init(); + assert( !status ); signal_start_process( entry, suspend ); } diff --git a/dlls/ntdll/tests/time.c b/dlls/ntdll/tests/time.c index be6859fe3e1..3c5fbbb857d 100644 --- a/dlls/ntdll/tests/time.c +++ b/dlls/ntdll/tests/time.c @@ -172,7 +172,6 @@ static void test_NtGetTickCount(void) { diff = (user_shared_data->u.TickCountQuad * user_shared_data->TickCountMultiplier) >> 24; diff = pNtGetTickCount() - diff; - todo_wine ok(diff < 100, "NtGetTickCount - TickCountQuad too high, expected < 100 got %d\n", diff); Sleep(50); } diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 621aaddfe34..f52cc2599b1 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -46,10 +46,12 @@ #include "wine/server.h" #include "wine/debug.h" #include "ntdll_misc.h" +#include "wine/usd.h" #include "ddk/wdm.h" #include "wine/exception.h"
WINE_DEFAULT_DEBUG_CHANNEL(thread); +WINE_DECLARE_DEBUG_CHANNEL(wineusd);
#ifndef PTHREAD_STACK_MIN #define PTHREAD_STACK_MIN 16384 @@ -212,6 +214,38 @@ static void set_process_name( int argc, char *argv[] ) #endif /* HAVE_PRCTL */ }
+void user_shared_data_init(void) +{ + static const WCHAR device_nameW[] = {'\','D','e','v','i','c','e','\','W','i','n','e','U','s','d',0}; + struct _KUSER_SHARED_DATA data = *user_shared_data; + OBJECT_ATTRIBUTES attr = {sizeof(attr)}; + UNICODE_STRING string; + IO_STATUS_BLOCK io; + NTSTATUS status; + HANDLE device; + void *addr = user_shared_data; + SIZE_T size = 0; + + RtlInitUnicodeString( &string, device_nameW ); + attr.ObjectName = &string; + if ((status = NtCreateFile( &device, 0, &attr, &io, NULL, + FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, + FILE_NON_DIRECTORY_FILE, NULL, 0 ))) + { + WARN_(wineusd)( "Failed to open user shared data device, status: %x.\n", status ); + return; + } + + NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE ); + + if ((status = NtDeviceIoControlFile( device, NULL, NULL, NULL, &io, + IOCTL_WINEUSD_INITIALIZE, + &data, sizeof(data), NULL, 0 ))) + { + MESSAGE( "wine: failed to map the shared user data: %08x\n", status ); + exit(1); + } +}
/*********************************************************************** * thread_init
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=61208
Your paranoid android.
=== debian10 (32 bit report) ===
ntdll: time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216498995 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499045 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499095 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499145 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499196
=== debian10 (32 bit French report) ===
ntdll: time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216498987 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499037 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499088 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499138 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499188
=== debian10 (32 bit Japanese:Japan report) ===
ntdll: time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216498988 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499038 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499088 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499139 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499189
=== debian10 (32 bit Chinese:China report) ===
ntdll: time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216498982 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499032 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499082 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499133 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216499183
=== debian10 (32 bit WoW report) ===
ntdll: time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216314624 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216314674 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216314725 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216314775 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216314825
=== debian10 (64 bit WoW report) ===
ntdll: time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216314624 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216314674 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216314724 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216314774 time.c:175: Test failed: NtGetTickCount - TickCountQuad too high, expected < 100 got 216314825
Am 02.12.19 um 14:32 schrieb Rémi Bernon:
If the service is not yet started - which can happen for the initial processes and other services, then the process uses the current user shared data implementation, where no timestamp update is doneWouldn't that mean things fail if I run wine Starcraft.exe? I know it is
modern that all games are started from launchers, but having the initial process behave differently is a bigger issue than you make it seem.
On 12/2/19 6:04 PM, Stefan Dösinger wrote:
Am 02.12.19 um 14:32 schrieb Rémi Bernon:
If the service is not yet started - which can happen for the initial processes and other services, then the process uses the current user shared data implementation, where no timestamp update is done > Wouldn't that mean things fail if I run wine Starcraft.exe? I know it is
modern that all games are started from launchers, but having the initial process behave differently is a bigger issue than you make it seem.
As far as I can tell, no. Services are started before the main process startup completes, but some services may be started before this service is. I don't have a very clear understanding of the process startup order though to be honest.