> > Writable shared memory is unacceptable, but as long as it's read-only > from the client there's no problem in principle. >
Excellent, thanks Alexandre. I'm attaching my current shared memory diff. It uses shm_open + mmap in wineserver to map the shared memory area read/write, and shm_open + NtCreateSection + NtMapViewOfSection in wine to map read only. A thread is run in wineserver which does a clock_nanosleep to set the times without drift. The wineserver code appears to work, and successfully writes to shared memory. The wine code fails in NtMapViewOfSection with error C0000018, which is STATUS_CONFLICTING_ADDRESSES. Can someone who understands NtMapViewOfSection look at my code and tell me if I've done something stupid? I thought there might be code buried in NtMapViewOfSection which tries to reserve that code block, but I didn't see it when I looked. Some notes: I didn't use CreateFileMapping/MapViewOfFile because that lives in kernel32.dll, so I pulled the code in and called NtCreateSection/NtMapViewOfSection directly. I also had to pull out all of the ntdll code which writes to USER_SHARED_DATA, and move that to wineserver. I had to link ntdll and wineserver against -lrt; this should of course be done more clealy via configure. Finally, the mmap call in wineserver only succeeds if I pass in a candidate address; if I pass in NULL, it fails with 'Operation not permitted'. cheers, Joey
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index 0047731..80d7f5a 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -2,7 +2,7 @@ EXTRADEFS = -D_NTSYSTEM_ MODULE = ntdll.dll IMPORTLIB = ntdll IMPORTS = winecrt0 -EXTRALIBS = @IOKITLIB@ @LIBPTHREAD@ +EXTRALIBS = @IOKITLIB@ @LIBPTHREAD@ -lrt EXTRADLLFLAGS = -nodefaultlibs -Wl,--image-base,0x7bc00000 C_SRCS = \ diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 381e2ac..e6112eb 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2812,7 +2812,7 @@ void CDECL __wine_init_windows_dir( const WCHAR *windir, const WCHAR *sysdir ) PLIST_ENTRY mark, entry; LPWSTR buffer, p; - strcpyW( user_shared_data->NtSystemRoot, windir ); + /* strcpyW( user_shared_data->NtSystemRoot, windir ); */ DIR_init_windows_dir( windir, sysdir ); /* prepend the system dir to the name of the already created modules */ diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index 3ed8038..dea32ee 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -1038,6 +1038,7 @@ void fill_cpu_info(void) } if (!strcasecmp(line, "flags") || !strcasecmp(line, "features")) { +#if 0 if (strstr(value, "cx8")) user_shared_data->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE; if (strstr(value, "cx16")) @@ -1062,6 +1063,7 @@ void fill_cpu_info(void) user_shared_data->ProcessorFeatures[PF_PAE_ENABLED] = TRUE; if (strstr(value, "ht")) cached_sci.FeatureSet |= CPU_FEATURE_HTT; +#endif continue; } } diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index e328c5f..eb926d2 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -23,6 +23,8 @@ #include <assert.h> #include <stdarg.h> +#include <stdint.h> +#include <errno.h> #include <sys/types.h> #ifdef HAVE_SYS_MMAN_H #include <sys/mman.h> @@ -183,6 +185,98 @@ done: return status; } +static void map_user_shared_data(void) +{ + int shmfd; + void *addr; + + FIXME("open KUSER_SHARED_DATA\n"); + shmfd = shm_open("/KUSER_SHARED_DATA", O_RDONLY | O_CREAT, 0600); + + FIXME("shmfd %d\n", shmfd); + + if(shmfd != -1) { + HANDLE fdh = NULL, cfmh = NULL; + NTSTATUS mstatus = STATUS_SUCCESS, cstatus = STATUS_SUCCESS; + LARGE_INTEGER offset; + ULONG protect = PAGE_READONLY; + //ULONG protect = PAGE_READWRITE; + SIZE_T count; + + if(0) + { + addr = (void *)0x7ffe0000; + count = 0x10000; + addr = mmap(addr, count, PROT_READ, MAP_FILE|MAP_SHARED|MAP_FIXED, shmfd, 0); + + if(addr == MAP_FAILED) { + FIXME("mmap(addr, SZ, PROT_READ, MAP_FILE|MAP_SHARED|MAP_FIXED, fd, 0) failed: %s\n", strerror(errno)); + return; + } + + FIXME("mapped USER_SHARED_DATA to %p\n", addr); + user_shared_data = addr; + return; + } + + FIXME("calling wine_server_fd_to_handle( shmfd, GENERIC_READ|SYNCHRONIZE, OBJ_INHERIT, &fdh )\n"); + + wine_server_fd_to_handle( shmfd, GENERIC_READ|SYNCHRONIZE, OBJ_INHERIT, &fdh ); + + FIXME("fdh %p\n", fdh); + { + static const int sec_flags = SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_COMMIT | SEC_NOCACHE; + + DWORD access, sec_type; + LARGE_INTEGER size; + + sec_type = protect & sec_flags; + protect &= ~sec_flags; + if (!sec_type) sec_type = SEC_COMMIT; + + /* Win9x compatibility */ + if (!protect && (GetVersion() & 0x80000000)) protect = PAGE_READONLY; + + access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE; + + size.u.LowPart = 0x10000; + size.u.HighPart = 0; + + cstatus = NtCreateSection( &cfmh, access, NULL, &size, protect, sec_type, fdh ); + if(cstatus != STATUS_SUCCESS) { + FIXME("NtCreateSection failed: %X\n", cstatus); + return; + } + } + + + FIXME("cfmh %p\n", cfmh); + + //cfmh = CreateFileMappingA( fdh, NULL, PAGE_READONLY, 1, 0, NULL ); + + addr = (void *)0x7ffe0000; + + offset.u.LowPart = 0; + offset.u.HighPart = 0; + + count = 0x10000; + protect = PAGE_READONLY; + + mstatus = NtMapViewOfSection( cfmh, GetCurrentProcess(), &addr, 0, 0, &offset, + &count, ViewShare, 0, protect ); + + if(mstatus != STATUS_SUCCESS) { + FIXME("NtMapViewOfSection failed: %X\n", mstatus); + return; + } + + + FIXME("mapped USER_SHARED_DATA to %p\n", addr); + + user_shared_data = addr; + } +} + /*********************************************************************** * thread_init * @@ -196,19 +290,11 @@ HANDLE thread_init(void) void *addr; SIZE_T size, info_size; HANDLE exe_file = 0; - LARGE_INTEGER now; struct ntdll_thread_data *thread_data; static struct debug_info debug_info; /* debug info for initial thread */ virtual_init(); - /* reserve space for shared user data */ - - addr = (void *)0x7ffe0000; - size = 0x10000; - NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ); - user_shared_data = addr; - /* allocate and initialize the PEB */ addr = NULL; @@ -260,6 +346,7 @@ HANDLE thread_init(void) debug_init(); /* setup the server connection */ + server_init_process(); info_size = server_init_thread( peb ); @@ -287,17 +374,11 @@ HANDLE thread_init(void) wine_server_fd_to_handle( 2, GENERIC_WRITE|SYNCHRONIZE, OBJ_INHERIT, ¶ms.hStdError ); } - /* initialize time values in user_shared_data */ - NtQuerySystemTime( &now ); - user_shared_data->SystemTime.LowPart = now.u.LowPart; - user_shared_data->SystemTime.High1Time = user_shared_data->SystemTime.High2Time = now.u.HighPart; - user_shared_data->u.TickCountQuad = (now.QuadPart - server_start_time) / 10000; - user_shared_data->u.TickCount.High2Time = user_shared_data->u.TickCount.High1Time; - user_shared_data->TickCountLowDeprecated = user_shared_data->u.TickCount.LowPart; - user_shared_data->TickCountMultiplier = 1 << 24; - + map_user_shared_data(); fill_cpu_info(); + FIXME("InterruptTime: %lu %ld\n", user_shared_data->InterruptTime.LowPart, user_shared_data->InterruptTime.High1Time); + return exe_file; } diff --git a/dlls/ntdll/version.c b/dlls/ntdll/version.c index 0185d7f..9294136 100644 --- a/dlls/ntdll/version.c +++ b/dlls/ntdll/version.c @@ -529,11 +529,13 @@ done: NtCurrentTeb()->Peb->OSBuildNumber = current_version->dwBuildNumber; NtCurrentTeb()->Peb->OSPlatformId = current_version->dwPlatformId; + /* user_shared_data->NtProductType = current_version->wProductType; user_shared_data->ProductTypeIsValid = TRUE; user_shared_data->NtMajorVersion = current_version->dwMajorVersion; user_shared_data->NtMinorVersion = current_version->dwMinorVersion; user_shared_data->SuiteMask = current_version->wSuiteMask; + */ TRACE( "got %d.%d platform %d build %x name %s service pack %d.%d product %d\n", current_version->dwMajorVersion, current_version->dwMinorVersion, diff --git a/loader/Makefile.in b/loader/Makefile.in index 41d69c7..9c3d4f6 100644 --- a/loader/Makefile.in +++ b/loader/Makefile.in @@ -39,10 +39,10 @@ wine-preloader wine64-preloader: preloader.o Makefile.in $(CC) -o $@ -static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x7c400000 preloader.o $(LIBPORT) $(LDFLAGS) $(MAIN_BINARY): main.o Makefile.in - $(CC) -o $@ $(LDEXECFLAGS) main.o $(LIBWINE) $(LIBPORT) $(LIBPTHREAD) $(EXTRALIBS) $(LDFLAGS) $(LDRPATH_LOCAL) + $(CC) -o $@ $(LDEXECFLAGS) main.o $(LIBWINE) $(LIBPORT) $(LIBPTHREAD) $(EXTRALIBS) $(LDFLAGS) $(LDRPATH_LOCAL) -lrt wine-installed: main.o Makefile.in - $(CC) -o $@ $(LDEXECFLAGS) main.o $(LIBWINE) $(LIBPORT) $(LIBPTHREAD) $(EXTRALIBS) $(LDFLAGS) $(LDRPATH_INSTALL) + $(CC) -o $@ $(LDEXECFLAGS) main.o $(LIBWINE) $(LIBPORT) $(LIBPTHREAD) $(EXTRALIBS) $(LDFLAGS) $(LDRPATH_INSTALL) -lrt $(EXTRA_BINARIES:%=__install__%): $(EXTRA_BINARIES) $(DESTDIR)$(bindir) dummy f=`expr $@ : '__install__\(.*\)'` && $(INSTALL_PROGRAM) $$f $(DESTDIR)$(bindir)/$$f diff --git a/server/Makefile.in b/server/Makefile.in index a2f1a52..bfe5175 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -1,5 +1,5 @@ DEFS = -D__WINESRC__ -EXTRALIBS = @LIBPOLL@ +EXTRALIBS = @LIBPOLL@ -lrt -lpthread C_SRCS = \ async.c \ @@ -43,6 +43,7 @@ C_SRCS = \ trace.c \ unicode.c \ user.c \ + user_shared_data.c \ window.c \ winstation.c @@ -62,10 +63,10 @@ all: $(PROGRAMS) @MAKE_RULES@ wineserver: $(OBJS) - $(CC) -o $@ $(OBJS) $(LIBWINE) $(LIBPORT) $(LDFLAGS) $(LIBS) $(LDRPATH_LOCAL) + $(CC) -o $@ $(OBJS) $(LIBWINE) $(LIBPORT) $(LDFLAGS) $(LIBS) $(LDRPATH_LOCAL) -lrt -lpthread wineserver-installed: $(OBJS) - $(CC) -o $@ $(OBJS) $(LIBWINE) $(LIBPORT) $(LDFLAGS) $(LIBS) $(LDRPATH_INSTALL) + $(CC) -o $@ $(OBJS) $(LIBWINE) $(LIBPORT) $(LDFLAGS) $(LIBS) $(LDRPATH_INSTALL) -lrt -lpthread install install-lib:: wineserver-installed $(DESTDIR)$(bindir) install-man-pages $(INSTALL_PROGRAM) wineserver-installed $(DESTDIR)$(bindir)/wineserver diff --git a/server/main.c b/server/main.c index 2d841e8..fc9bae8 100644 --- a/server/main.c +++ b/server/main.c @@ -32,12 +32,18 @@ # include <getopt.h> #endif +#include <pthread.h> +#include <sys/mman.h> +#include <sys/stat.h> + #include "object.h" #include "file.h" #include "thread.h" #include "request.h" #include "wine/library.h" +#include "user_shared_data.h" + /* command-line options */ int debug_level = 0; int foreground = 0; @@ -138,6 +144,8 @@ int main( int argc, char *argv[] ) signal( SIGTERM, sigterm_handler ); signal( SIGABRT, sigterm_handler ); + init_shm(); + sock_init(); open_master_socket(); diff --git a/server/user_shared_data.c b/server/user_shared_data.c new file mode 100644 index 0000000..5f0c7f8 --- /dev/null +++ b/server/user_shared_data.c @@ -0,0 +1,377 @@ +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> + +#include "user_shared_data.h" + +#include "wine/library.h" + +struct _KUSER_SHARED_DATA *user_shared_data = NULL; + +typedef enum +{ + WIN20, /* Windows 2.0 */ + WIN30, /* Windows 3.0 */ + WIN31, /* Windows 3.1 */ + WIN95, /* Windows 95 */ + WIN98, /* Windows 98 */ + WINME, /* Windows Me */ + NT351, /* Windows NT 3.51 */ + NT40, /* Windows NT 4.0 */ + NT2K, /* Windows 2000 */ + WINXP, /* Windows XP */ + WIN2K3, /* Windows 2003 */ + WINVISTA,/* Windows Vista */ + WIN2K8, /* Windows 2008 */ + WIN2K8R2,/* Windows 2008 R2 */ + WIN7, /* Windows 7 */ + NB_WINDOWS_VERSIONS +} WINDOWS_VERSION; + +/* FIXME: compare values below with original and fix. + * An *excellent* win9x version page (ALL versions !) + * can be found at www.mdgx.com/ver.htm */ +static const RTL_OSVERSIONINFOEXW VersionData[NB_WINDOWS_VERSIONS] = +{ + /* WIN20 FIXME: verify values */ + { + sizeof(RTL_OSVERSIONINFOEXW), 2, 0, 0, VER_PLATFORM_WIN32s, + {'W','i','n','3','2','s',' ','1','.','3',0}, + 0, 0, 0, 0, 0 + }, + /* WIN30 FIXME: verify values */ + { + sizeof(RTL_OSVERSIONINFOEXW), 3, 0, 0, VER_PLATFORM_WIN32s, + {'W','i','n','3','2','s',' ','1','.','3',0}, + 0, 0, 0, 0, 0 + }, + /* WIN31 */ + { + sizeof(RTL_OSVERSIONINFOEXW), 3, 10, 0, VER_PLATFORM_WIN32s, + {'W','i','n','3','2','s',' ','1','.','3',0}, + 0, 0, 0, 0, 0 + }, + /* WIN95 */ + { + /* Win95: 4, 0, 0x40003B6, "" + * Win95sp1: 4, 0, 0x40003B6, " A " (according to doc) + * Win95osr2: 4, 0, 0x4000457, " B " (according to doc) + * Win95osr2.1: 4, 3, 0x40304BC, " B " (according to doc) + * Win95osr2.5: 4, 3, 0x40304BE, " C " (according to doc) + * Win95a/b can be discerned via regkey SubVersionNumber + */ + sizeof(RTL_OSVERSIONINFOEXW), 4, 0, 0x40003B6, VER_PLATFORM_WIN32_WINDOWS, + {0}, + 0, 0, 0, 0, 0 + }, + /* WIN98 (second edition) */ + { + /* Win98: 4, 10, 0x40A07CE, " " 4.10.1998 + * Win98SE: 4, 10, 0x40A08AE, " A " 4.10.2222 + */ + sizeof(RTL_OSVERSIONINFOEXW), 4, 10, 0x40A08AE, VER_PLATFORM_WIN32_WINDOWS, + {' ','A',' ',0}, + 0, 0, 0, 0, 0 + }, + /* WINME */ + { + sizeof(RTL_OSVERSIONINFOEXW), 4, 90, 0x45A0BB8, VER_PLATFORM_WIN32_WINDOWS, + {' ',0}, + 0, 0, 0, 0, 0 + }, + /* NT351 */ + { + sizeof(RTL_OSVERSIONINFOEXW), 3, 51, 0x421, VER_PLATFORM_WIN32_NT, + {'S','e','r','v','i','c','e',' ','P','a','c','k',' ','5',0}, + 5, 0, 0, VER_NT_WORKSTATION, 0 + }, + /* NT40 */ + { + sizeof(RTL_OSVERSIONINFOEXW), 4, 0, 0x565, VER_PLATFORM_WIN32_NT, + {'S','e','r','v','i','c','e',' ','P','a','c','k',' ','6','a',0}, + 6, 0, 0, VER_NT_WORKSTATION, 0 + }, + /* NT2K */ + { + sizeof(RTL_OSVERSIONINFOEXW), 5, 0, 0x893, VER_PLATFORM_WIN32_NT, + {'S','e','r','v','i','c','e',' ','P','a','c','k',' ','4',0}, + 4, 0, 0, VER_NT_WORKSTATION, 30 /* FIXME: Great, a reserved field with a value! */ + }, + /* WINXP */ + { + sizeof(RTL_OSVERSIONINFOEXW), 5, 1, 0xA28, VER_PLATFORM_WIN32_NT, + {'S','e','r','v','i','c','e',' ','P','a','c','k',' ','3',0}, + 3, 0, VER_SUITE_SINGLEUSERTS, VER_NT_WORKSTATION, 30 /* FIXME: Great, a reserved field with a value! */ + }, + /* WIN2K3 */ + { + sizeof(RTL_OSVERSIONINFOEXW), 5, 2, 0xECE, VER_PLATFORM_WIN32_NT, + {'S','e','r','v','i','c','e',' ','P','a','c','k',' ','2',0}, + 2, 0, VER_SUITE_SINGLEUSERTS, VER_NT_SERVER, 0 + }, + /* WINVISTA */ + { + sizeof(RTL_OSVERSIONINFOEXW), 6, 0, 0x1772, VER_PLATFORM_WIN32_NT, + {'S','e','r','v','i','c','e',' ','P','a','c','k',' ','2',0}, + 2, 0, VER_SUITE_SINGLEUSERTS, VER_NT_WORKSTATION, 0 + }, + /* WIN2K8 */ + { + sizeof(RTL_OSVERSIONINFOEXW), 6, 0, 0x1772, VER_PLATFORM_WIN32_NT, + {'S','e','r','v','i','c','e',' ','P','a','c','k',' ','2',0}, + 2, 0, VER_SUITE_SINGLEUSERTS, VER_NT_SERVER, 0 + }, + /* WIN7 */ + { + sizeof(RTL_OSVERSIONINFOEXW), 6, 1, 0x1DB1, VER_PLATFORM_WIN32_NT, + {'S','e','r','v','i','c','e',' ','P','a','c','k',' ','1',0}, + 1, 0, VER_SUITE_SINGLEUSERTS, VER_NT_WORKSTATION, 0 + }, + /* WIN2K8R2 */ + { + sizeof(RTL_OSVERSIONINFOEXW), 6, 1, 0x1DB1, VER_PLATFORM_WIN32_NT, + {'S','e','r','v','i','c','e',' ','P','a','c','k',' ','1',0}, + 1, 0, VER_SUITE_SINGLEUSERTS, VER_NT_SERVER, 0 + }, + +}; + +static const char * const WinVersionNames[NB_WINDOWS_VERSIONS] = +{ /* no spaces in here ! */ + "win20", /* WIN20 */ + "win30", /* WIN30 */ + "win31", /* WIN31 */ + "win95", /* WIN95 */ + "win98", /* WIN98 */ + "winme", /* WINME */ + "nt351", /* NT351 */ + "nt40", /* NT40 */ + "win2000,win2k,nt2k,nt2000", /* NT2K */ + "winxp", /* WINXP */ + "win2003,win2k3", /* WIN2K3 */ + "vista,winvista", /* WINVISTA*/ + "win2008,win2k8", /* WIN2K8 */ + "win2008r2,win2k8r2", /* WIN2K8R2 */ + "win7", /* WIN7 */ +}; + +/* initialized to null so that we crash if we try to retrieve the version too early at startup */ +static const RTL_OSVERSIONINFOEXW *current_version; + + +extern void fill_cpu_info(void) +{ + char line[200]; + FILE *f = fopen ("/proc/cpuinfo", "r"); + + if (!f) + return; + while (fgets(line,200,f) != NULL) + { + char *s,*value; + + /* NOTE: the ':' is the only character we can rely on */ + if (!(value = strchr(line,':'))) + continue; + + /* terminate the valuename */ + s = value - 1; + while ((s >= line) && ((*s == ' ') || (*s == '\t'))) s--; + *(s + 1) = '\0'; + + /* and strip leading spaces from value */ + value += 1; + while (*value==' ') value++; + if ((s = strchr(value,'\n'))) + *s='\0'; + + if (!strcasecmp(line, "fdiv_bug")) + { + if (!strncasecmp(value, "yes",3)) + user_shared_data->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = TRUE; + continue; + } + if (!strcasecmp(line, "fpu")) + { + if (!strncasecmp(value, "no",2)) + user_shared_data->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = TRUE; + continue; + } + if (!strcasecmp(line, "flags") || !strcasecmp(line, "features")) + { + if (strstr(value, "cx8")) + user_shared_data->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE; + if (strstr(value, "cx16")) + user_shared_data->ProcessorFeatures[PF_COMPARE_EXCHANGE128] = TRUE; + if (strstr(value, "mmx")) + user_shared_data->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE; + if (strstr(value, "nx")) + user_shared_data->ProcessorFeatures[PF_NX_ENABLED] = TRUE; + if (strstr(value, "tsc")) + user_shared_data->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE; + if (strstr(value, "3dnow")) + user_shared_data->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = TRUE; + /* This will also catch sse2, but we have sse itself + * if we have sse2, so no problem */ + if (strstr(value, "sse")) + user_shared_data->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE; + if (strstr(value, "sse2")) + user_shared_data->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = TRUE; + if (strstr(value, "pni")) + user_shared_data->ProcessorFeatures[PF_SSE3_INSTRUCTIONS_AVAILABLE] = TRUE; + if (strstr(value, "pae")) + user_shared_data->ProcessorFeatures[PF_PAE_ENABLED] = TRUE; + /* + if (strstr(value, "ht")) + cached_sci.FeatureSet |= CPU_FEATURE_HTT; + */ + continue; + } + } + fclose(f); +} + +void version_init(void) +{ + static const WCHAR default_windirW[] = {'C',':','\\','w','i','n','d','o','w','s',0}; + static const WCHAR default_sysdirW[] = {'\\','s','y','s','t','e','m','3','2',0}; + + strcpyW( user_shared_data->NtSystemRoot, default_windirW ); + + current_version = &VersionData[WINXP]; /* default if nothing else is specified */ + + user_shared_data->NtProductType = current_version->wProductType; + user_shared_data->ProductTypeIsValid = TRUE; + user_shared_data->NtMajorVersion = current_version->dwMajorVersion; + user_shared_data->NtMinorVersion = current_version->dwMinorVersion; + user_shared_data->SuiteMask = current_version->wSuiteMask; +} + + +#define TICKSPERSEC 10000000 +#define TICKSPERMSEC 10000 +#define SECSPERDAY 86400 +#define SECSPERHOUR 3600 +#define SECSPERMIN 60 +#define MINSPERHOUR 60 +#define HOURSPERDAY 24 +#define EPOCHWEEKDAY 1 /* Jan 1, 1601 was Monday */ +#define DAYSPERWEEK 7 +#define EPOCHYEAR 1601 +#define DAYSPERNORMALYEAR 365 +#define DAYSPERLEAPYEAR 366 +#define MONSPERYEAR 12 +#define DAYSPERQUADRICENTENNIUM (365 * 400 + 97) +#define DAYSPERNORMALCENTURY (365 * 100 + 24) +#define DAYSPERNORMALQUADRENNIUM (365 * 4 + 1) + +/* 1601 to 1970 is 369 years plus 89 leap days */ +#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY) +#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC) + +static void update_shared_data_time(void) +{ + LARGE_INTEGER now, start, irq; + struct timeval tv; + + gettimeofday( &tv, 0 ); + now.QuadPart = tv.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970; + now.QuadPart += tv.tv_usec * 10; + + fprintf(stderr, "%lld\n", now.QuadPart); + + irq.QuadPart = (now.QuadPart - server_start_time); + + user_shared_data->InterruptTime.High2Time = irq.HighPart; + user_shared_data->InterruptTime.LowPart = irq.LowPart; + user_shared_data->InterruptTime.High1Time = irq.HighPart; + + user_shared_data->SystemTime.High2Time = now.HighPart; + user_shared_data->SystemTime.LowPart = now.LowPart; + user_shared_data->SystemTime.High1Time = now.HighPart; + + start.QuadPart = irq.QuadPart / 10000; + + user_shared_data->TickCount.High2Time = start.HighPart; + user_shared_data->TickCount.LowPart = start.LowPart; + user_shared_data->TickCount.High1Time = start.HighPart; + user_shared_data->TickCountLowDeprecated = start.LowPart; +} + +static void* shared_data_thread(void *arg) +{ + struct timespec req, rem; + + req.tv_sec = 0; + req.tv_nsec = 15600000; + + while(1) { + update_shared_data_time(); + nanosleep(&req, &rem); + } + + return NULL; +} + + +extern void init_shm(void) +{ + int fd; + void *addr; + const SIZE_T SZ = 0x10000; + SIZE_T size; + char buf[SZ]; + int e; + pthread_t thread; + + memset(buf, 0, SZ); + + fd = shm_open("/KUSER_SHARED_DATA", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if(fd == -1) { + fprintf(stderr, "shm_open(\"/KUSER_SHARED_DATA\", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR) failed\n"); + return; + } + + e = read(fd, buf, SZ); + if(e != SZ) { + fprintf(stderr, "Unable to read %ld bytes from shm, try writing them\n", SZ); + e = write(fd, buf, SZ); + if(e != SZ) { + fprintf(stderr, "Unable to write %ld bytes to shm, give up\n", SZ); + return; + } + } + + /* reserve space for shared user data */ + + addr = (void *)0x7ffe0000; + size = SZ; + addr = mmap(addr, SZ, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, 0); + + if(addr == MAP_FAILED) { + fprintf(stderr, "mmap(addr, SZ, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0) failed: %s\n", strerror(errno)); + return; + } + + fprintf(stderr, "mapped USER_SHARED_DATA to %p\n", addr); + + user_shared_data = addr; + + user_shared_data->TickCountMultiplier = 1 << 24; + + fill_cpu_info(); + version_init(); + + update_shared_data_time(); + + if(!(e = pthread_create(&thread, NULL, &shared_data_thread, NULL))) { + if(pthread_detach(thread)) + fprintf(stderr, "Unable to detach thread\n"); + } else { + fprintf(stderr, "unable to spawn thread: %s (%d)\n", strerror(e), e); + } + +} + diff --git a/server/user_shared_data.h b/server/user_shared_data.h new file mode 100644 index 0000000..9de82af --- /dev/null +++ b/server/user_shared_data.h @@ -0,0 +1,111 @@ +#ifndef WINESERVER_USER_SHARED_DATA_H +#define WINESERVER_USER_SHARED_DATA_H + +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> + +#include "request.h" +#include "wine/library.h" + +/* Processor feature flags. */ +#define PF_FLOATING_POINT_PRECISION_ERRATA 0 +#define PF_FLOATING_POINT_EMULATED 1 +#define PF_COMPARE_EXCHANGE_DOUBLE 2 +#define PF_MMX_INSTRUCTIONS_AVAILABLE 3 +#define PF_PPC_MOVEMEM_64BIT_OK 4 +#define PF_ALPHA_BYTE_INSTRUCTIONS 5 +#define PF_XMMI_INSTRUCTIONS_AVAILABLE 6 +#define PF_3DNOW_INSTRUCTIONS_AVAILABLE 7 +#define PF_RDTSC_INSTRUCTION_AVAILABLE 8 +#define PF_PAE_ENABLED 9 +#define PF_XMMI64_INSTRUCTIONS_AVAILABLE 10 +#define PF_SSE_DAZ_MODE_AVAILABLE 11 +#define PF_NX_ENABLED 12 +#define PF_SSE3_INSTRUCTIONS_AVAILABLE 13 +#define PF_COMPARE_EXCHANGE128 14 +#define PF_COMPARE64_EXCHANGE128 15 +#define PF_CHANNELS_ENABLED 16 +#define PF_XSAVE_ENABLED 17 + +typedef struct _KSYSTEM_TIME { + ULONG LowPart; + LONG High1Time; + LONG High2Time; +} KSYSTEM_TIME, *PKSYSTEM_TIME; + +typedef enum _NT_PRODUCT_TYPE { + NtProductWinNt = 1, + NtProductLanManNt, + NtProductServer +} NT_PRODUCT_TYPE, *PNT_PRODUCT_TYPE; + +#define PROCESSOR_FEATURE_MAX 64 + +typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE +{ + StandardDesign, + NEC98x86, + EndAlternatives +} ALTERNATIVE_ARCHITECTURE_TYPE; + +#define NX_SUPPORT_POLICY_ALWAYSOFF 0 +#define NX_SUPPORT_POLICY_ALWAYSON 1 +#define NX_SUPPORT_POLICY_OPTIN 2 +#define NX_SUPPORT_POLICY_OPTOUT 3 + +#define MAX_WOW64_SHARED_ENTRIES 16 + +typedef struct _KUSER_SHARED_DATA { + ULONG TickCountLowDeprecated; + ULONG TickCountMultiplier; + volatile KSYSTEM_TIME InterruptTime; + volatile KSYSTEM_TIME SystemTime; + volatile KSYSTEM_TIME TimeZoneBias; + USHORT ImageNumberLow; + USHORT ImageNumberHigh; + WCHAR NtSystemRoot[260]; + ULONG MaxStackTraceDepth; + ULONG CryptoExponent; + ULONG TimeZoneId; + ULONG LargePageMinimum; + ULONG Reserved2[7]; + NT_PRODUCT_TYPE NtProductType; + BOOLEAN ProductTypeIsValid; + ULONG NtMajorVersion; + ULONG NtMinorVersion; + BOOLEAN ProcessorFeatures[PROCESSOR_FEATURE_MAX]; + ULONG Reserved1; + ULONG Reserved3; + volatile ULONG TimeSlip; + ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture; + LARGE_INTEGER SystemExpirationDate; + ULONG SuiteMask; + BOOLEAN KdDebuggerEnabled; + UCHAR NXSupportPolicy; + volatile ULONG ActiveConsoleId; + volatile ULONG DismountCount; + ULONG ComPlusPackage; + ULONG LastSystemRITEventTickCount; + ULONG NumberOfPhysicalPages; + BOOLEAN SafeBootMode; + ULONG TraceLogging; + ULONGLONG TestRetInstruction; + ULONG SystemCall; + ULONG SystemCallReturn; + ULONGLONG SystemCallPad[3]; + union { + volatile KSYSTEM_TIME TickCount; + volatile ULONG64 TickCountQuad; + } DUMMYUNIONNAME; + ULONG Cookie; + ULONG Wow64SharedInformation[MAX_WOW64_SHARED_ENTRIES]; +} KSHARED_USER_DATA, *PKSHARED_USER_DATA; + + +extern struct _KUSER_SHARED_DATA *user_shared_data; + +extern void fill_cpu_info(void); +extern void init_shm(void); + +#endif