Re: WINE server messages
> Maintaining a section list in the server is certainly something we > could do, but I don't really see why you want to get rid of the > modules list. What would you gain by doing that?> NtMapViewOfSection/NtUnmapViewOfSection. Admittedly, these would be hard to implement fully in the current Wine userspace server I think (they can map a section handle into _another_ process's VM space). However, it's something I can do in kernel space reasonably easily. And then there's NtQueryVirtualMemory. This can return a handle to the backing section (assuming I'm recalling this correctly) in some other process. Actually, I see that you do maintain a view list in the client as well as the module list and section lists in the server. What I was thinking of was just consolidating the three into a single view list and a single section list in the server. In effect, Wine'd still have the module list, it's just that there'd be non-modules in the list too. This would mean that the debugger could query from the server what Windows VM mappings should be expected. And, of course, it'd make writing the kernel module slightly easier:-) David
WINE server messages
Hello Alexandre, I'm having a little trouble deciding exactly how to emulate the "module registration" functionality in my kernel module. It occurs to me that this might be easier to accomplish with a change to the current wine server message set. My idea is: * Have the server only deal with NT Section objects and views of Sections. * Have no separate module table attached to a process. * Implement NtQuerySectionInformation/NtSetSectionInformation calls (or whatever they're called) as wineserver messages. * Add an extra Wine-specific information class for the purpose of recording the extra module information. * The wineserver process structure can then be changed so that rather than keeping a separate list of process_dlls, they can just keep a list of section views, some of which will be images/modules. David
Re: STATUS_* codes
STATUS_INVALID_EXECUTABLE_IMAGE should have read: STATUS_INVALID_IMAGE_FORMAT and I'm told that the value is 0xC07B. Cheers, David
STATUS_* codes
Can someone pin numbers on the following codes: STATUS_FILE_IS_A_DIRECTORY STATUS_INVALID_EXECUTABLE_IMAGE At least I think that's what they're called (unfortunately, my book's at home where I can't check it). They're listed in my NT native API book (though that's no guarantee that they exist), but not in the Wine header files, and I don't have a copy of the DDK installed on top of MSDEV. David
Re: Speeding up wineserver syncronization objects with shared memory
Okay, I've thought about how to make the wine kernel module easier to use for Wine, and I've started adding another API to it - one that interprets Wine server messages. When I designed the module initially, I decided to make it possible to add as many API's as I liked, so in theory it's not too difficult. I'm currently performing a major rearrangement of the files that comprise the module: * Splitting the current win32 API bits out of the same files that contain the actual object class implementations. * Putting the core and the API's in separate subdirectories. * Abstracting name support, so that the internal API takes an "object name" which the user API is responsible for extracting from userspace and converting from WCS/MBS as necessary. * Fixing introduced bugs. This does not mean that I'm getting rid of the Win32 API I've already got! It will just be optional. Calling the new API will be by means of either: union generic_request msg; syscall(__NR_win32,WINESERVER_WINE_SERVER_MESSAGE,&msg); Or: union generic_request msg; int fd = open("/proc/wineserver"); struct WineserverIoctl wioc = { WINESERVER_WINE_SERVER_MESSAGE, &msg }; ioctl(fd,WINESERVER_IOCTL,&wioc); David
Re: Speeding up wineserver syncronization objects with shared memory
> OK, this has apparently changed in kernel 2.4; in kernel 2.2 block > size alignment is enough. That's unfortunate, but I guess it was > necessary to support large files or memory sizes. Then yes, in 2.4 > your patch will be more useful. As far as I know, it's the case on most Unices, though it maybe not be so on older versions of Linux. It's part of the definition of mmap() too, I think. David
Re: Speeding up wineserver syncronization objects with shared memory
> I'll have to write a small program to collect some statistics:-) Okay, I did a quick and dirty program to do that. It looked through the following products that I've got installed: Win2000 sp1 MSDEV 98 MS Office 2000 Using the following command: find /fs/win2000/WINNT \ "/fs/win2000/Program Files/Microsoft Visual Studio" \ "/fs/win2000/Program Files/Microsoft Office" -type f | ./scandll And came up with the following statistics: files accessed : 3985 valid PE images : 1752 - libraries : 1280 - badly VM aligned: 20 - standard image base : 42 - specific image base : 1218 - file align by sector: 976 - file align by page : 284 - executables : 472 - badly VM aligned: 133 - standard image base : 70 - specific image base : 269 - file align by sector: 287 - file align by page : 52 I've attached the program I used. As you can see, most DLLs actually have their image base set manually to avoid conflicts. Also a lot of EXEs have it set too... presumably so that they can also be used as DLLs. However! the majority of DLLs and EXEs are sector-aligned (512) in the files, not page-aligned (4096). David /* scandll.c: scan DLLs and EXEs * * Copyright (c) 2001 David Howells ([EMAIL PROTECTED]). */ #include #include #include #include #include #include typedef __u8BOOL, BYTE; typedef __u16 WORD; typedef __u32 DWORD, UINT; #define PAGE_SIZE 4096 #define _H_229A4E44_C7CC_11D4_8F92_C0005742 /* skip section.h */ #include "pefile.h" IMAGE_SECTION_HEADER sechdr; IMAGE_DOS_HEADER imghdr; IMAGE_NT_HEADERS nthdr; int files; int valid_image; int dlls; int exes; int bad_vm_align[2]; int file_align_sector[2]; int file_align_page[2]; int normal_image_base[2]; int specific_image_base[2]; /*/ /* * */ int main(int argc, char **argv) { char fname[1024], *cp; int fd = -1, tmp, isexe; while (close(fd), fd = -1, fgets(fname,sizeof(fname),stdin) ) { cp = strpbrk(fname,"\r\n"); if (cp) *cp = 0; fd = open(fname,O_RDONLY); if (!fd) { if (errno==EISDIR) continue; perror("open"); return 1; } /* get the DOS image header */ tmp = read(fd,&imghdr,sizeof(imghdr)); if (tmp<0) { if (errno==EISDIR) continue; perror("read doshdr"); return 1; } if (tmp
Re: Speeding up wineserver syncronization objects with shared memory
> Page alignment is needed for the address in memory, not for the offset > inside the file on disk; since section virtual addresses in PE files > are always page-aligned the memory address is never a problem. The > only problem comes from the alignment of the data inside the PE file, > and this is where we only need block-size alignment to make mmap > possible. Not so... The file offset must also be page aligned! Try the following program: #include #include #include #include int main(int argc, char **argv) { void *addr; int fd; fd = open("/bin/sh",O_RDONLY); if (fd<0) { perror("mmap"); return 1; } addr = mmap(NULL,512,PROT_READ,MAP_PRIVATE,fd,argc==1?512:4096); if (addr==MAP_FAILED) { perror("mmap"); return 1; } return 0; } If you don't run it with an argument, it fails (Invalid Argument), and if you do give it an argument, it works. If you look at the kernel: [arch/i386/kernel/sys_i386.c] asmlinkage int old_mmap(struct mmap_arg_struct *arg) { struct mmap_arg_struct a; int err = -EFAULT; if (copy_from_user(&a, arg, sizeof(a))) goto out; err = -EINVAL; if (a.offset & ~PAGE_MASK) goto out; err = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); out: return err; } Note that "a.offset" (the file offset) is checked for page alignment. Note also that the internal kernel routine do_mmap2() deals with the offset in terms of pages, not bytes. David
Re: Speeding up wineserver syncronization objects with shared memory
> Note that we are no longer doing that in the latest versions; the file > descriptor is only transferred once, Fair enough... I see that ZwClose/NtClose isn't actually a problem (since unlike most other Zw* calls, it can't affect other processes). Oh... I see how you're doing it... sending the handle->fd translate request to the server, which sends a response saying you've got it cached; then using dup() locally to emulate the old behaviour; and then closing the fd. So this saves you the cost of the fd transfer net packet. Though you still have to do the two context switches, which is my main contention. > and all further requests are done on a pipe which is faster than a socket. True, but I'd have thought that the context switches involved are still a cost you can't get rid of so easily. Out of interest, how do you plan on doing the locking stuff for Read/WriteFile? Cache it locally? It is unfortunate, but you can't really make use of UNIX file locking, since this is mostly advisory and as such doesn't actively stop read/write calls. > The kernel module itself may be hard to do incrementally, but you > should really consider reusing the existing server API so that your > module can be plugged in easily. For instance your module entry points > should be the same as the server requests, and use the same request > structures. What? Miss the opportunity to implement "int 0x2e" directly? *grin* Seriously, though, whilst this'd be a lot easier in many ways (and it would allow you to avoid the context-switch penalties), you wouldn't be able to take full advantage of the available support in the kernel, which is more capable than the standard UNIX userspace API suggests. It'd still have to paste handles to fds for most file operation calls, and you'd still have the PE Images soaking up a fair amount of memory. If this is what you want, then it might be better done as a network protocol module that just pretends to be a wineserver, and supports the same read/write/sendmsg/recvmsg interface. (It'd have to be a network protocol to be able to get sendmsg/recvmsg calls): int serv = socket(AF_WINE,SOCK_STREAM,0); short addr = AF_WINE; connect(serv,(struct sockaddr*)&addr,sizeof(addr)); > I still think that it should be possible to improve that by a small > kernel hack. It will never be as fast as doing everything in the > kernel of course, but it may just be fast enough to avoid the need to > reimplement the whole server. If you want to suggest exactly what you'd like to see as a hack... > Have you measured how many dirty pages you can avoid with your change? > It seems to me that in most cases, when the dll is loaded at its > preferred address, the number of pages made dirty by the fixups should > be quite small anyway. As far as I've observed (I've got Win2000 available), most Windows DLL's have 512-byte (sector) alignment internally, _not_ 4096-byte (page) alignment for the sections. This means that the separate sections can't be mmap'd (or else they'd lose their required relative relationships): VIRTUAL_mmap() { ... /* mmap() failed; if this is because the file offset is not*/ /* page-aligned (EINVAL), or because the underlying filesystem */ /* does not support mmap() (ENOEXEC,ENODEV), we do it by hand. */ ... } This appears to happen a lot. And then _all_ the pages in that section are dirty, irrespective of whether fixups are done or not. Also, since DLLs and EXEs are not compiled as PIC (the MSDEV compiler not having such an option as far as I can recall), the fixup tables usually seem to apply to just about every page in the code section. I'll have to write a small program to collect some statistics:-) As for the DLL being loaded at it's preferred address, the kernel module jumps around the fixup stuff, and doesn't even consider trying to perform it. Plus pages that have been altered by the fixup code are actually marked _clean_ by the VM subsystem, and can thus be simply discarded when physical memory needs to be reclaimed. David
Re: Speeding up wineserver syncronization objects with shared memory
Gavriel State <[EMAIL PROTECTED]> wrote: > As it stands, your approach won't be useful for general Wine usage until > you've got *everything* done. True. But I think there are valid reasons for doing it this way. One major problem is handles. Either the kernel must allocate all handles, or userspace must allocate all handles. Take something like the implementation of DuplicateHandle() - dead easy really in kernel space, including duplication to another process. If userspace tells the kernel to use handle X for a mutex, say, and handle Y for a semaphore, then userspace still has to go to atomic management code to (a) allocate a handle, and (b) access a handle. And to implement cross-process duplication, you either need some sort of interrupt & IPC mechanism, or an external process (the wineserver). This being the case, you lose any gains by putting the stuff in-kernel. Alternatively, if userspace is allowed to implement arbitrary handles that are allocated by the kernel, then the kernel waiting mechanism can get a little tricky. However, that said, for non-waitable objects, this might not be so bad. In fact, I'm planning on implementing the registry access handles this way and may well do some of the process and thread control this way too. Furthermore, the kernel would have to be given object handles not object pointers, otherwise you have a gaping security hole. And another major problem is context switches... they are horribly expensive really. They currently make Wine with at least 20 times the system call latency that the kernel method is capable of. > And then there will be boatloads of debugging to do. Perhaps not as much as you think... I'm doing as much debugging as I can as I go along, just making sure the kernel objects work as I'd expect (not necessarily the same thing, true, as having "compatible" behaviour). > If there's any way that you can implement your kernel module more within the > context of the existing server architecture - replacing objects on a piece > by piece fashion rather than all at once - that might make it easier to > adopt. See above for why the piece-by-piece method is difficult. One alternative would be to invent a new network protocol (say AF_WINE), but that again requires a complete implementation before it is really useful. > For example, you might try implementing the core object/handle management > and waiting code in the kernel module, and have the wine server rely on the > kernel module for that low-level functionality. By this, do you mean actually having the wineserver process talk to the kernel module on behalf of the Wine application? > Waiting for objects would be implemented on the client side through a call > to the kernel module. That's what I'm currently doing, though it's not fully implemented yet. > When something needs to be done with an object, we would call either the > wineserver or the kernel module, depending on how that object is > implemented. > For example, you could do mutexes entirely within the kernel module, but > leave file objects on the wine-server side initially. My main gripe is the slow speed of access to files... Every Read/WriteFile goes to the wineserver to convert the handle into a file descriptor and to check for locking. The FD is then passed back over a UNIX domain socket, used once and then closed. I suspect it can't really be done otherwise, particularly if ZwCloseObject (or whatever it is called) is implemented, since this allows handles in another process to be closed. Actually, I've done a fair amount of the file object stuff... Most of it involves mapping down to a "struct file *", which is how the kernel views files, and then invoking appropriate kernel method. > In my experience Alexandre far prefers incremental change to kind of > approach you're taking. Using that kind of approach will improve the > chances that your code will make it into Wine at some point. Hmmm... It's difficult to determine how to do it incrementally without making for even more work, but I think I know what you mean. > One thing I've been wondering that you might be able to answer is this: > exactly why is the current Wine Server architecture so slow? Is it just the > context switching? Context switching is the main element of it. Going to the wineserver and back again just for a ReadFile() call or a Wait*() function incurs a fairly serious penalty (particularly on an X86, I think). Plus there's no requirement for the kernel to pass the remains of your timeslice to the wineserver and back again. Also, you have to bundle lots of data through AF_UNIX network packets and/or copy lots of data into and out of _shared_ memory without killing other threads. One of the problems with the context switch is that you have to flush all the CPU caches, muck around with the MMU and execute scheduling algorithms. > Is it that the kernel isn't giving the wineserver a high enough priority > once the client blocks after having written to
Re: Speeding up wineserver syncronization objects with shared memory
I've got a lot of the wine support kernel module written now. Its system call latency seems to be down at near half that of Win2000 for mutexes, though there's no guarantee that my benchmark programs produce meaningful numbers. I've also got PE Image mapping done (with pages fixed up on demand and marked as discardable). So if anything, Wine might want to steal that if the module as a whole is not used. This bit requires virtually no changes to the kernel itself, just half a dozen or so extra symbols to be exported. The module image size stands currently at about 30K. Status: PARTSTATE == == General object infrastructure done HANDLE infrastructure mostly done Waiting calls partly done Exception handling not done Win32 error handlingnot done, uses UNIX errno UNICODE handlingignored, all ASCII Security handling ignored Mutex objects done Semaphore objects done Event objects done File objects (synchronous access) mostly done File objects (asynchronous access) not done Shared memory objects mostly done Process objects slightly done Thread objects slightly done Registry objectsnot done NT Port objects not done NT Token objectsnot done W2K Job objects not done Net Communications not done userspace access libraryup to date strace mostly up to date Cheers, David
Re: VxD and kernel module
Peter Hunnisett <[EMAIL PROTECTED]> wrote: > Just a question. With the wine server running as a linux kernel module > would we be able to support native VxDs? I'll be honest that I don't > understand the transition between rings but I'm guessing that it must > involve a trap of some descript which could then be passed off to the > kernel module to run in a more priviledged mode. It _might_ be possible to extend the kernel module to provide DDK APIs for VxD and NT drivers (more so for the latter case), but it probably wouldn't be easy. Certainly, the kernel module would be able to provide handle support, registry access, etc., but not swappable kernel memory for now. I have wondered myself about what'd be necessary to support NT/W2K display drivers in the Linux kernel, as that might make it possible to build XFree86 around them. David Howells
Re: wine-cvs mailing-list doesn't seem to work
I've noticed that the wine-devel has gone very slow. In fact, wine2.winehq.com has ben refusing connections and the backup mailserver at Corel has been bouncing messages for no obvious reason. I don't know whether this helps David Howells
Would it be possible...
Would it be possible for me to store a copy of my kernel module code on winehq? Or should I find somewhere else (eg: sourceforge)? Cheers, David Howells
Re: RFC - Winelib constructor init problem
Patrik Stridvall wrote: > Looking at the message again,... Fair Enuff. > Personally think that LD_PRELOAD should only be used for tests > and for kludging problems that need a fix _now_, not something > that should be used in normal cases. I was thinking along the lines of just getting it up and running with Wine for the moment. David Howells
Re: RFC - Winelib constructor init problem
Patrik Stridvall <[EMAIL PROTECTED]> wrote: > FYI I read linux-kernel too from time to time, but I don't > subscribe to it. I read it through the archive. Well, I wasn't to know. And in any case the message was meant to be copied to wine-devel, but it didn't work, somehow. > So what is the next step? Well, I'll keep on writing it, see how it goes... It occurs to me, though, that it can be used with wine through the LD_PRELOAD functionality. One thing that has to be worth doing is putting it up for ftp/CVS somewhere, probably separate from Wine, and probably giving some other people write access to it. > PS. Why did you mail only me in private? See above. David Howells
Linus Torvalds: Re: [RFC] Wine speedup through kernel module
--- Forwarded Message To: [EMAIL PROTECTED] From: [EMAIL PROTECTED] (Linus Torvalds) Subject: Re: [RFC] Wine speedup through kernel module Date: 7 Sep 2000 16:02:10 -0700 In article <[EMAIL PROTECTED]>, David Howells <[EMAIL PROTECTED]> wrote: > >I've done an implementation of some of the Win32 "system calls" in a kernel >module in an attempt to speed up Wine. Hmm.. I have this feeling that it would be much nicer to just implement the NT system calls directly. We used to have the iBCS2 project, and I was actually considering making it part of the standard kernel when it started becoming a non-issue simply because there started to be more native Linux programs than iBCS2 programs. And we've already had the vm86 mode and the BIOS trap stuff speedups for DOSEMU for a long time. It looks like if you want to do this, it would be better to just try to do it outright, and have the same kind of "emulate the ones we know about and care about performance" in the kernel that we already have with the vm86 mode emulation. I wouldn't be adverse to supporting Wine better - as long as it's fairly cleanly separated. This doesn't look too bad. Linus - - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] Please read the FAQ at http://www.tux.org/lkml/ --- End of Forwarded Message
Re: RFC - Winelib constructor init problem
Alexandre Julliard <[EMAIL PROTECTED]> wrote: > I told you what I wanted: basically a pipe with slightly different > semantics; no need to touch the scheduler for that. It should be > pretty easy to code for an experienced kernel hacker (which I'm not), > and then we can run benchmarks and see if the idea has any merit at > all. Perhaps you'd consider taking a look at the RPC mechanism that I designed and mostly implemented... It currently passes an address from the client to the server and accepts an integer and an error number back. What I haven't had time to write yet are the ptrace-style read/write functions that will allow the server to gain access to the client's memory space. An extra pair of functions could also be provided to paste fd's between the client and server. Patrik Stridvall <[EMAIL PROTECTED]> wrote: > Seriously, as I said above, I consider a Linux kernel Wine server > nothing more than a marketting gimmick. I would very much prefer > the user space Wine server to be maintainable and robust rather > than fast. 99.99% of all application that are likely to be run > under Wine will not care if mutexes are 900% slower as long as > they have the correct semantics. What I'm most concerned about with wine is the fact that every time a file operation is issued, the client makes a call to the server to convert the Win32 file handle into a UNIX fd (via sendmsg/recvmsg), which gets used once and then discarded. I've seen programs that do a lot of I/O (for instance PVCS) hammer the server lots with requests for file handle conversion, and so they run quite a bit slower on Linux than on Windows. I do also wonder about the server running out of fd slots, but I don't think that is too much of a problem. Of course the biggest reason for doing this is the technical challenge... and of course proving to the Windows nutters around that Linux can do Windows system calls faster than Windows itself *grin*. David Howells
Re: RFC - Winelib constructor init problem
As promised... I've attached a copy of the latest source for my kernel module. Note that I've implemented some support for file objects: CreateFile, ReadFile, WriteFile, SetFilePosition, SetEndOfFile, FlushFileBuffers However, I'm not sure it's necessary to go this far... just being able to attach fd's to handles and extract fd's from handles may be sufficient. I've also partially implemented the RPC mechanism I mentioned yesterday (which might also interest Alexandre for his idea of improved RPC). At the moment, all it can do is pass an address to the server and get an integer back. I didn't have time to write the read/write functions that directly access the client's memory space. It took longer than I thought to work out how to do a rendezvous between two processes and three objects without incurring deadlock or oopsing if one of the objects went away. David Howells wine server module
Re: RFC - Winelib constructor init problem
Patrik Stridvall <[EMAIL PROTECTED]> wrote: > Nothing specific, just a general feeling that some sort of selective > yielding is not a good idea and in order to avoid DoS something > not unlikely costly must be done to have a fair scheduling. Plus, I don't think you can do selective yielding at the moment. You might be able to get around the DoS attack by having the scheduler limit the amount of time you can trade to the remainder of your timeslice, after which the process to which you yield gets scheduled out anyway. But it sounds horribly complex. > Regardless of what syscalls you have, if you want good latency you must > have a guarantee that in average that kernel will schedule the server > after the client call as well as the reverse. > > For a lightly loaded machine this is likely to happend automatically > since few other processes want to run. But for a heavily loaded machine > you probably must have some sort of selective yield otherwise you will > get very bad latancy when other process get time slices in between. Agreed. > I'm not a kernel expert but I have a general feeling that you will > never get good performance unless the kernel gives you some kind > of selective yield guarantees which is not unlikely to be costily > for scheduler. Agreed... but you still have to pay the penalty on context switches. > IMHO putting the speed critical NT kernel object in the kernel > is a much better and more realistic solution. Also agreed. The kernel has good support for synchronisation, providing a wealth of types of synchronisation object. David Howells
Re: RFC - Winelib constructor init problem
Alexandre Julliard <[EMAIL PROTECTED]> wrote: > Patrik Stridvall <[EMAIL PROTECTED]> writes: > > > Everything that is speed critical should be in kernel, > > things that are not should not. Trying to do it > > some other way is doomed to failure I think. > > That's *exactly* what I'm proposing: the speed critical part (the > request mechanism, since it is used for all server calls) in the > kernel, all the rest in user space. But the time and CPU usage overhead comes from the context switches and the waiting for the "other" process to be scheduled. We can improve the client memory access mechanism to reduce the whole thing to only two context switches, but they still impose a severe penalty. > Obviously I'm not suggesting that we add these two functions as system > calls; this is only the conceptual interface. The actual > implementation should probably be based on file descriptors; basically > it is a kind of pipe with slightly different semantics (you could even > achieve most of that with normal pipes, but you'd need to always > transfer 4096 bytes to keep the buffer full which would be a bit > slow). Not nice... Imagine you want to just grab a mutex... you'd have to transfer 4K of data each direction, the vast majority of which would be totally wasted. I have to agree with Patrik again, sendmsg+recvmsg are better options there. A better way to do this is just to pass an address in the clients VM and have the server access it directly. David Howells
Re: RFC - Winelib constructor init problem
Alexandre Julliard <[EMAIL PROTECTED]> wrote: > I think what we need is: > > - on the client side, a wake_server_and_sleep() call that combines the > write()+read() on the socket in a single syscall. > > - on the server side, a wake_client_and_wait_for_next_one() that wakes > the client whose request was last processed, and waits until some > other client sends a request. This is fairly pointless... the Linux system call overhead isn't all that major - issuing separate send & receive calls loses you very little. Beyond the fact that the server may be busy doing something else, the real killer is the pair of context switches and the fact that there is no guarantee that the server will immediately be scheduled after the client, and the client again after the server. Indeed, it may be necessary to swap the server back in, depending on system load. > This should enable doing a complete server round-trip with only two > syscalls (one in the client one in the server), and avoid any > unnecessary context switch. Like the two switches to get to the server and back again? > If we combine this with an efficient way to read/write the client > memory space from the server, I think we should be able to achieve > good performance while still reusing nearly all the existing code. True, some sort of ptrace-type access mechanism may help speed things up without tying up ptrace. > And if the mechanism is small enough and generic enough, we can even > hope to have it included in the standard kernel, which I doubt would > ever be possible with the complete server kernel module. As Patrik implied... Unlikely (though he said it more eloquently). David Howells
Re: RFC - Winelib constructor init problem
> No, I don't think it has anything to with exec_domain/personality. All that this has to do is determine how some signals and syscalls are handled, but you are probably right. > What happens if the module goes away? > The application segfaults I hope. Depends... if you don't manage it properly then "OOPS"! Otherwise, it's a matter of making sure that the module _won't_ go away - make the module register and unregister a handler and its "module definition" structure (similarly to how the vfs deals with things). This means: (1) A new call can't start if there is no handler registered. (2) Whilst a call is in progress, the module's usage counter is kept incremented. (3) Obviously, the module can't be removed whilst the counter is non-zero. (4) There is protection available to make sure you can't tweak a module count whilst the module is being loaded/unloaded (so you can't slip in a new usage between counter-is-zero-check and actual-removal). David Howells
Re: RFC - Winelib constructor init problem
> Note that if you layout the call structure _exactly_ the same > way as the stack layout (which is fixed for all Windows API functions). > You will get an even faster call mechanism that you currently have. > Just load a register with the call id another with the offset:ed > stack pointer and then sys call. > > I wonder how many percent faster that will be? Out of interest, did you get this idea from looking at the source code I sent out earlier? It's changed since then... I'll have to distribute my revised stuff tomorrow. David Howells
Re: RFC - Winelib constructor init problem
Patrik Stridvall <[EMAIL PROTECTED]> wrote: > I think it is because the Linux syscall mechanism is faster. > In any case a totally meaningless benchmark since there is > no practial use in doing a tight mutex loop. > > However, it might be useful for marketing Wine. :-) True... It is however 900% or better faster than straight wine. > The registry is a file system (almost). The main difference > is that the "directories" can have content as well. > > It would be nice to be able to mount (loopback mount) the > registry files. This means that Are you thinking of mounting Windows registry hives directly? If so, don't forget: (1) the windows registry spans several hive files, (2) hives can be added by user processes, (3) what about change notifications, (4) what about dynamic data, and (5) what about meta-data (type, etc.). Admittedly, some this might be solved by a filesystem, particularly if you can mount registry filesystems on registry filesystems (equivalent to adding hives) and use symbolic links to emulate registry symlinks. > The fact that "the set of functions available in the two > spaces is different" does not nessary mean that sharing > source is ruled out it depend largely on how many #ifdef > you need to hide the differences. Note that many things > can be hidden in the header files. Hmmm... You have to emulate all the locking stuff it you want to be able to multithread your userspace-only server. Actually, what you can probably do is write the server as a kernel module, and then emulate the kernel services in userland. I did this to some extent in a small testbed program that I wrote so I could trace the kernel module easily with gdb. > Yes, I think should have a special syscall for this. > ... > However, I think, with the exception of the overhead, > that the ioctl interface is good in principle. > > Just add a syscall called > int winecall(int id, void *data); > this gives flexibillity. We can add as many new "winecall":s > as we like using this interface. We'd have to persuade Linus to part with one. Maybe attaching it to the exec_domain/personality stuff. We'd also have to be _very_ careful using it if the wineserver is in a module, otherwise the module might go away whilst we're using it, but that shouldn't be a problem. > I use ioctl because (a) it already exists, (b) I don't have to change the > kernel to use it, and (c) I'm using a file descriptor to control the lifetime > of the handle map. > > Somebody earlier mentioned using the mechnism that NT (int 2e IIRC), > the problem with this is that IIRC the syscall numbers are not > constant they are dependent on the version of the NT kernel. > They are IIRC sorted in alphabetic order. This means that the > native NTDLL.DLL will not run under Wine regardless so it > is not much use in doing that. Plus, you'd have to be able to change the interrupt table, not just a system call table entry, since NT goes through a currently unimplemented interrupt. > Note that if you layout the call structure _exactly_ the same > way as the stack layout (which is fixed for all Windows API functions). > You will get an even faster call mechanism that you currently have. > Just load a register with the call id another with the offset:ed > stack pointer and then sys call. > > I wonder how many percent faster that will be? I rewrote the userspace interface to work this way, giving me 10%-20% extra performance. One thing that I had to be careful of though is how the corresponding structures are laid out. Two BOOL arguments in a row in a function call parameter list take 8 bytes, but in a structure take only two. So I came up with something like: #define __pad__ __attribute__((aligned(4))) struct WiocCreateEventA { LPSECURITYATTRIBUTES __pad__ lpEventSecAttr; BOOL __pad__ bManualReset; BOOL __pad__ bInitialState; LPCSTR __pad__ lpName; }; When any userspace stub function invokes the ioctl, it passes the address of the first argument to the kernel, which casts it to the appropriate structure type. > PS. Perhaps you should ask Linus about reserving a syscall for > Wine before 2.4 is released in order to miniminze support > problems. Yep... assuming we want to do this. David Howells
Re: RFC - Winelib constructor init problem
Alexandre Julliard <[EMAIL PROTECTED]> wrote: > The kernel module approach is interesting, but I'm afraid it's not > really practical to reimplement the complete server in the kernel, > unless we can somehow build both the kernel module and the user-mode > server from the same sources. I have to agree with that... I have implemented mutexes, events, semaphores and some of the file handling in a kernel module, plus CloseHandle and most of WaitForMultipleObjects. I can see also process and thread handling and socket handling working quite well, and I might even be able to manage overlapped I/O. (I have to report, I think, that I rewrote the userspace interface, and I managed to get something like a 20% better turn around time in a tight mutex loop than Win2000 executing the same loop *evil grin*). However, I don't think that, for instance, the registry is particularly suitable to Linux kernel space. If it was stored in specially allocated slab memory caches (making it trivial to dispose of), with all the keys as unicode and linkage blocks forming a tree structure, it would take rather a lot of unswappable memory. As for building from the same sources, I don't think that's practical either, since the set of functions available in the two spaces is different (though you can make system calls from kernel-space, I don't recommend it in this case). > An intermediate approach that may be worth investigating is to keep the > server in user-space but implement a faster request mechanism with a small > kernel module; Unix sockets are not very well suited to the request/reply > model that we need, and I think it should be possible to make the > communication much faster with a specialized kernel call. Basically, I too am thinking of an intermediate approach... (1) Put the bits that call the server all into one place in the source (as is mostly done now). Note that the kernel module I have produced _entirely_ implements the Mutex, Semaphore and Event system calls, so things like CreateMutex and WaitForMultipleObjects would have to go in there. (2) The kernel module takes over handle management, with no userspace intervention required. Reference counting, handle number allocation, etc. all done in kernel space. (3) Provide a sort of RPC mechanism for those services that are impractical to implement in kernel space (such as the registry). I've outlined such a mechanism in an attachment to this message. And some miscellaneous optional extra bits: (1) We could use a spare system call to provide access to the kernel module, rather than using ioctl as I do now. This will bypass the overhead of ioctl looking for standard, internal commands to deal with first. (2) Provide calls to map UNIX fd's into file handles, and vice versa. (3) Make CreateFileHandle walk the directory tree itself (rather than relying on filp_open in the kernel), thus allowing much faster support for case-independent matching. And for cases where a kernel module can't be used (such as a non-Linux platform) switch to a different directory in the source tree, that uses the current UNIX socket based approach. David Howells Here's an idea for RPC mechanism. I think this should be fairly easy to implement, given the basic kernel module I've already got. This is, I think, very similar to the Solaris door mechanism. SERVER IMPLEMENTATION = (a) Use the handle management capability of the kernel module to look after keeping track of requests and replies in the server. (b) Have the server create a Service object, which it can then wait on and accept requests through (similar to server sockets). Multiple threads will be able to wait in this way. hServer = CreateWineService("registry-access"); WaitForMultipleObjects(1,&hServer,0,INFINITE); /* optional */ void *params; hRequest = AcceptWineServiceRequest(hServer,¶ms); (c) Either: (1) allow the server process to access the memory space of the client via a direct ptrace-type mechanism. This should be very fast, and require minimal copying. RegistryRequest rr; ReadWineServiceData(hRequest,params,rr,sizeof(rr)); WriteWineServiceData(hRequest,...); (2) or actually have the service request acceptor take a buffer into which the request is copied, and then have the request reply function take a buffer which holds the reply. (d) Finally, have a reply/result function that closes the handle and finishes the request: ReplyWineServiceRequest(hRequest,reqerrno,result); CLIENT IMPLEMENTATION = (a) As far as the client is concerned, some requests will be handled internally inside the kernel module, for instance, RegOpenKey. The kernel module may make a handle for use by the client, keeping some context informa
Re: possibility for massive wineserver speedup
> There's documentation included in the attached archive, including some rough > preliminary benchmarks. As a quick off the cuff reading, it beats Win2000 by > ~3% and Wine by ~900% on a dual CPU box. Actually, on one of the benchmark programs, it beats Win2000 by ~20% not ~3%, assuming I've calculated the percentages correctly. I've attached the benchmark data to the bottom of this message. David Howells - Machine: Dual PII 400MHz, 384Mb RAM Linux compiler: gcc version 2.96 2724 Windows compiler: MSDEV 6 FIVE THREADS/PROCESSES, ONE MUTEX = rapidmutex.c - Linux 2.4.0-test7 [2] obtained the mutex 62525 times (15631 times per second) [1] obtained the mutex 64156 times (16039 times per second) [0] obtained the mutex 64909 times (16227 times per second) [3] obtained the mutex 70250 times (17562 times per second) [4] obtained the mutex 67967 times (16991 times per second) == 329807 over 4s period rapidmutex-win.c - Win2000 [0] obtained the mutex 54563 times (13640 times per second) [1] obtained the mutex 54553 times (13638 times per second) [2] obtained the mutex 54529 times (13632 times per second) [3] obtained the mutex 54503 times (13625 times per second) [4] obtained the mutex 54481 times (13620 times per second) == 272629 over 4s period rapidmutex-win.c - Wine-2716/Linux 2.4.0-test7 [0] obtained the mutex 6753 times (1688 times per second) [1] obtained the mutex 6743 times (1685 times per second) [2] obtained the mutex 6725 times (1681 times per second) [3] obtained the mutex 6719 times (1679 times per second) [4] obtained the mutex 6714 times (1678 times per second) = 33654 over 4s period FIVE THREADS/PROCESSES, FIVE MUTEXES (Hungry philosophers problem = fivemutex.c - Linux 2.4.0-test7 [0] ate 45638 times (11409 times per second) [1] ate 51196 times (12799 times per second) [2] ate 53221 times (13305 times per second) [3] ate 79667 times (19916 times per second) [4] ate 61109 times (15277 times per second) == 290831 over 4s period fivemutex-win.c - Win2000 [0] ate 38675 times (9668 times per second) [1] ate 50682 times (12670 times per second) [2] ate 56600 times (14150 times per second) [3] ate 97662 times (24415 times per second) [4] ate 39870 times (9967 times per second) == total 283489 over 4s period fivemutex-win.c - Wine-2716/Linux 2.4.0-test7 [0] ate 4965 times (1241 times per second) [1] ate 5664 times (1416 times per second) [2] ate 5729 times (1432 times per second) [3] ate 5748 times (1437 times per second) [4] ate 4954 times (1238 times per second) = 27060 over 4s period
Re: possibility for massive wineserver speedup
Jeremy White <[EMAIL PROTECTED]> wrote: >Wow. This is the coolest new idea I've seen posted >to wine-devel for a while. Thanks *grin*. >I suspect it has many hurdles and may never be practical with Wine, >but I would really love to run winbench with Wine >and have the numbers be faster than that of NT... > >(I'm not going to try to address the issues; I suspect >that better minds than mine [e.g. Alexandre] will weigh >in with a more complete analysis). Oh, I don't know, I think in some ways it is very practical. My thought is that anything it can't handle easily or quickly can be passed transparently to a server process to be done in userspace (ie: registry maintainance and access). As for not currently being compilable against Linux 2.2, I think that can be solved fairly easily. >Do you mind if I ask what prompted you to undertake this >process? I like kernel programming, I'd like to see Wine go faster (I've tried stracing it and seen the absolute mass of wineserver interactions flying past). On a more practical note, I run the PVCS command line tools (version control) under Wine at work, and they could be faster (they're implemented in threaded Java - yuk), so I recon this could speed them up a bit. I also occaisonally run the MSDEV command line compiler under Wine, and that could be a lot faster too. David Howells
possibility for massive wineserver speedup
Well, I've made a start on a kernel module implementing some wineserver-type functionality, and I think that I've reached a reasonable point to put it up for discussion. Note that you will need one of the later development Linux kernels to use it with (I use 2.4.0-test7) - I've attached the a tar-bzip2 archive of the code to this document. At the moment it does the following: CreateEvent OpenEvent PulseEvent ResetEvent SetEvent CreateMutex OpenMutex ReleaseMutex CreateSemaphore OpenSemaphore ReleaseSemaphore WaitForMultipleObjects (mostly) CloseHandle Unfortunately, it can't actually be integrated into Wine just yet, since it only supports three of the many 'kernel' object types, and WaitFor*() can't be shared between implementations. There's documentation included in the attached archive, including some rough preliminary benchmarks. As a quick off the cuff reading, it beats Win2000 by ~3% and Wine by ~900% on a dual CPU box. Note that WaitForMultipleObjects() is implemented internally in the same way as poll and select, and thus is a restartable system call (can be interrupted by signals). I've pasted part of the Why? section out of my documentation: WHY === Because the current wineserver interface involves each wine process making a socket connection to a separate server process, which then arbitrates access to synchronisation objects and various other things. All this involves message passing and lots of process context switching (slow). By moving this into the kernel, advantage can be taken of kernel services for handling synchronisation, scheduling and concurrency. As an additional minor benefit, the "strace" program can be modified to read these specific system calls. === So comments please... Have fun, David Howells wineserver kernel module source
Re: why does wine use stdin, stdout & stderr streams from wineserver?
> did you wrote a .spec file specifying this is a console app =3F A spec file? MSDEV doesn't use such beasts, does it? Do you mean a .def file? But that doesn't seem to be much use either. However, I have tried compiling with "/D_CONSOLE /link /SUBSYSTEM:CONSOLE" and also generating a complete console project from MSDEV's IDE, and the same thing happens in all cases - output goes through wineserver. David
Re: why does wine use stdin, stdout & stderr streams from wineserver?
'Scuse me for being persistent, but can someone answer the following: Why does a simple program like the following use wineserver's stdin/out/err channels, not wine's? #include int main() { printf("hello\n"); return 0; } I've compiled this with MSDEV6 and run it under wine in a different xterm to where wineserver was running, and the output definitely appears to come out of wineserver (the appropriate fd is passed over a UNIX domain socket for every I/O operation wine performs). Marcus Meissner wrote: > They could have been changed using SetStdHandle(). Not so... I put a breakpoint in wine's implementation of this, and it execution didn't pass through that. > And the plain stdio stdin/stderr/stdout are not affected. Also not so... see above test program. Thanks, David Howells
Re: wine .spec file autogenerator
> - the shell32 exports many functions by ordinal withou a name. > Your tool likely can't cope with it - or it would need to use *.dbg > and *.pdb files to get symboles from. (have not tryed it jet) It can cope with it - or at least it emits a symbol constructed from the name of the DLL and the ordinal. Furthermore, the whole thing agrees with the output from "dumpbin /exports", except that that doesn't construct names for anonymous ordinals. David
wine .spec file autogenerator
Since no-one out there seems to have one, I've written a small perl script that reads the output of "objdump -x" run on a windows DLL and turns it into a .spec file with all the function stubbed out (handy when you want to deal with a DLL with over a thousand entry points). However, I've noticed that it doesn't appear to correlate with the already existing shell32.spec file based on a dump of the WinNT4 shell32.dll (at least as far as ordinals go). Can anyone explain this? David Howells #!/usr/bin/perl -w # # Format: #objdump -x | genspec.pl >.spec # (using objdump from binutils-2.10) # # # search for the beginning of the import table specification # while (<>) { chomp; if ($_ =~ /^The Import Tables/ ) { last; } } # # pull imported DLL specifications out of the import table # my @imports; while (<>) { chomp; if ($_ =~ /^The Export Tables/ ) { last; } # pull out an import specification if ($_ =~ /^\tDLL Name:/ ) { $_ =~ s/^[^:]*[:][ ]*//; $_ =~ y/A-Z/a-z/; push(@imports,$_); } } # # search for the beginning of the export address table # $name = ""; $ordbase = 0; while (<>) { chomp; if ($_ =~ /^Export Address Table/ ) { last; } if ($_ =~ /^Name/ ) { @_ = split; $name = $_[2]; } if ($_ =~ /^Ordinal Base/ ) { @_ = split; $ordbase = $_[2]; } } # # pull imported DLL specifications out of the import table # my %exportvmas; while (<>) { chomp; if ( $_ =~ /^ *$/ ) { last; } # pull out an import specification @_ = split("[][]"); $_[1] =~ s/ //g; $_[4] =~ s/^ *//; $_[4] =~ s/ .*$//; $ord = $_[1] + $ordbase; $exportvmas{$ord} = $_[4]; } # # search for the beginning of the ordinal naming table # while (<>) { chomp; if ($_ =~ /^.Ordinal.Name Pointer. Table/ ) { last; } } # # pull ordinal -> name mappings out # my %exportnames; while (<>) { chomp; if ( $_ =~ /^ *$/ ) { last; } # break into bits @_ = split("[][]"); $_[1] =~ s/ //g; $_[2] =~ s/ //g; $ord = $_[1] + $ordbase; $exportnames{$ord} = $_[2]; } ### # # render the spec file # $name =~ y/A-Z/a-z/; $dll = $name; $dll =~ s/.dll//; print "name\t" . $name . "\n"; print "type\twin32\n"; print "init\t" . $dll . "LibMain\n"; print "rsrc\t" . $dll . "rsrc\n"; print "\n"; foreach (@imports) { print "import " . $_ . "\n"; } print "\n"; @exports = sort {$a <=> $b} keys %exportvmas; foreach $export (@exports) { $name = $exportnames{$export}; $name = defined $name ? $name . " " : $dll . "_" . $export; printf("%4d stub %s\n",$export,$name); }
Re: why does wine use stdin, stdout & stderr streams from wineserver?
> They could have been changed using SetStdHandle(). Not so. > And the plain stdio stdin/stderr/stdout are not affected. Again, apparently not so. I compiled the following program up with MSDEV6 and ran it under wine: #include int main() { printf("hello\n"); return 0; } The output of the program comes out of wineserver's stdout not wine's (I ran wineserver in one xterm, and wine in another). I checked to see if SetStdHandle() is called - it is not (at least, I ran wine under gdb and set a breakpoint, which didn't trip). David Howells
why does wine use stdin, stdout & stderr streams from wineserver?
Can someone explain why wineserver passes it's UNIX stdin/out/err fd's to a running wine program by socket-based FD transfer every time a wine application wants to do an operation on it's idea of stdin/out/err? This has some annoying effects: * It's very difficult to redirect stdin/out/err on wine applications. * The appropriate FD is passed _every_ time such an operation is issued (so if a lot of lines are being printed to stderr, say, a sendmsg/recvmsg pair is issued for every line). * It costs a small fortune in context switches and message passing overhead. To see what I mean, take a look at this "strace wine -- cl -?" excerpt... write(3, "&\0\0\0", 4) = 4 recvmsg(3, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0", 4}], msg_controllen=16, msg_control=0x406f68a4, , msg_flags=0}, 0) = 4 write(6, "\r\n", 2) = 2 close(6)= 0 write(3, "&\0\0\0", 4) = 4 recvmsg(3, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0", 4}], msg_controllen=16, msg_control=0x406f68a4, , msg_flags=0}, 0) = 4 write(6, ""..., 44) = 44 close(6)= 0 write(3, "&\0\0\0", 4) = 4 recvmsg(3, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0", 4}], msg_controllen=16, msg_control=0x406f68a4, , msg_flags=0}, 0) = 4 write(6, "\r\n", 2) = 2 close(6)= 0 write(3, "&\0\0\0", 4) = 4 recvmsg(3, {msg_name(0)=NULL, msg_iov(1)=[{"\0\0\0\0", 4}], msg_controllen=16, msg_control=0x406f68a0, , msg_flags=0}, 0) = 4 write(6, "(press to continue)", 28) = 28 close(6)= 0 Every time it wants to write a line, it goes to wineserver (fd 3) and asks to be sent a fd for stderr (fd 6). David Howells
creating a new DLL .spec file
I'd like to create a builtin DLL for cygwin, and I was wondering if there is a script or program for autogenerating an initial spec file given a DLL to look at. I can see that it could be done, given that the objdump program from the binutils-2.10.0 package running on Linux can be used to get at the import and export tables from the DLL. David Howells
Re: Windows system DLLs without Windows installation
Hi Andreas, Quick question for you (or anyone else who knows)... How difficult would it be to emulate in software a PE DLL/EXE file with only a resource section (no text, data or relocation sections), such that if wine OpenFile opens a known wine elf-dll file or a builtin-dll, it then does an effective cut'n'paste of the resource section from the wine-dll to an emulated PE file? I know its not a nice way to do things, but it would solve the problem of handling both elf-dlls and builtin-dlls without having to compile up and keep in sync stub PE DLLs. David
Re: Windows system DLLs without Windows installation
> I just want to make sure that programs that check for the presence > of a DLL file by means of OpenFile() find what they want. > And I think adding a small NE/PE header is good, too. > But don't let this get out of hand... > (sorry for not really explaining it before...) Do many programs do that? I must admit I'm a bit suprised... I had an idea of subverting OpenFile() to mask the contents of an ELF DLL by pretending to return a PE header, but I'm not sure that that's a good idea. > The GetFileVersion*() thing will have to wait a bit, as it will require > massive support in the loader to figure out the loadorder correctly. > But maybe I'll forget about the loadorder for the beginning and try to > always parse the builtin DLL first and if that fails I branch to the old > NE/PE parser. > Of course that'll need a big FIXME "loadorder stuff missing" then ;-) Yuk. What about non-builtin elfdlls? Like libshell32.so.1.0... ELF parsing is fairly straight forward, so you could divert the DLL parser from, say, shell32.dll to libshell32.so where appropriate, and read the resource block out of there. Of course, this'd be easier if the resources were contained in a special section (called .rsrc probably) and padded out with the bits of fluff that MSDEV's RC program puts in. David
Re: Windows system DLLs without Windows installation
Andreas Mohr wrote: >> Out of interest, why do you want fake NE/PE DLLs? Is it because some programs >> try to 'manually' parse the DLLs rather than using system routines? >I thought that it's better to include a header (which would be small anyway) >for these files instead of just "touch"ing them. > >And I previously thought of adding different VS_VERSION_INFO resources for >different Windows versions to the fake DLLs. >But this is not good, I think. >... This still doesn't tell me why you want to use NE/PE DLL stubs... Is it so that you can find the resources easily? If so, would it be possible to tell gcc to store the resources in a .rsrc section as MSDEV does, and then just parse the ELF directly to find the resources. > How do we implement the reading of the VERSION_INFO ? > ... > And a GetFileVersionInfo*() normally happens directly before a LoadLibrary() > anyway. > Hmm, a question about that: > If we do the LoadLibrary() in GetFileVersionInfo*() and do a FreeLibrary() > at the end (usage count down to 0 again ! -> removal), I don't think you can make GetFileVersionInfo*() do LoadLibrary() as this will need to drag in and initialise _all_ the dependency libraries too, which could take nearly forever. Plus, I'm sure you can do this on EXE files as well as DLL files. I'd have thought your better off writing a simplified NE/PE parser that just locates the resource block and pulls the version info out of it. If you do this, then you can also use it to implement the convenience functions for getting other resources, such as string tables, and also implement the functions to _change_ those resources. Also if you do a NE/PE parser as I've suggested, why not make it able to handle ELF files too? :-) David
Re: Windows system DLLs without Windows installation
Andreas Mohr wrote: > Sure, that's what I'll be working on soon. > However most probably that won't be libraries (.so), but rather completely > new NE or PE "fake DLLs" with a complete header and version resources. Will you then be building the wine code into these DLL files rather than into real .so files? And if not, will there be some mechanism by which if someone tries to dynamically load one of these DLLs, it will dynamically load the real .so file in addition or instead? Out of interest, why do you want fake NE/PE DLLs? Is it because some programs try to 'manually' parse the DLLs rather than using system routines? David Howells
Windows system DLLs without Windows installation
[Wine Weekly News] > System DLLs > > The Wine team has determined that it is necessary to create fake DLL files to > trick many applications that check for file existence to determine whether a > particular feature (such as Winsock and its TCP/IP networking) is > available. If this is a problem for you, you can create empty files in the > "system" directory to make the application think it's there, and Wine's > built-in DLL will be loaded when the application actually asks for it. > (Unfortunately, tools/wineinstall does not create such empty files itself.) > > Applications sometimes also try to inspect the version resources from the > physical files (for example, to determine the DirectX version). Empty files > will not do in this case, it is rather necessary to install files with > complete version resources. This problem is currently being worked on. In the > meantime, you may still need to grab some real DLL files to fool these apps > with. > ... Can you instead construct a system32 directory and populate it with symlinks to appropriate wine DLL replacements, for example: ln -s /opt/wine/lib/libshell32.so /opt/wine/share/system32/shell32.dll The people can dynamically load them for resources or code without wine having to anything more special than check the magic number on the front of the DLL to see what type it is. David Howells