Wine Traffic #145 For 22�Nov�2002

By Brian Vincent

Table Of Contents

Introduction

This is the 145th release of the Wine's kernel cousin publication. It's main goal is to distribute widely what's going on around Wine (the Un*x windows emulator).

Mailing List Stats For This Week

We looked at 339 posts in 1233K.

There were 73 different contributors. 47 posted more than once. 35 posted last week too.

The top posters of the week were:

1. News: Fun Projects Slashdotted, Screenshots (Send More!)

16�Nov�2002�-�22�Nov�2002 (1 post) Archive Link: "News"

Topics: News

People: ,�News,�Dimitrie Paun

Dimitrie Paun's web site got Slashdotted (http://developers.slashdot.org/article.pl?sid=02/11/17/1648220&mode=thread&tid=125) on Sunday after someone pointed out he had a list of Fun Wine Projects (http://www.dssd.ca/wine/Wine-Fun.html) . Specifically they mentioned the virtualization projects. A lot of the discussion (http://developers.slashdot.org/comments.pl?sid=45298&cid=0&pid=0&startat=&threshold=2&mode=thread&commentsort=0&op=Change) (mod level 2) on Slashdot was actually geared more toward using Wine than anything else. Last year or a few years ago most of the discussion would have been a flamewar between the "Wine sucks" and the "No it doesn't" camps. I found it interesting there wasn't much of that.

Also, thanks to everyone who's sent in screenshots! Full credit will appear next week, but as sort of a preview of what I've gotten check out: http://www.theshell.com/~vinn/ss/ (http://www.theshell.com/~vinn/ss/) . Authors are noted in the directory. At this point I'd love to get some shots of the following:

Also, here's some guidelines to follow:

Send those to vinn -at- theshell.com

2. Porting PuTTY With Winelib

21�Nov�2002 (4 posts) Archive Link: "PuTTY update"

Topics: Winelib

People: Dimitrie Paun,�

Dimi Paun decided to try his hand at porting a Windows application using Winelib. The app he chose was PuTTY (http://www.chiark.greenend.org.uk/~sgtatham/putty/) , a free Win32 Telnet/SSH client who's source (http://www.tartarus.org/~simon/putty-snapshots/putty-src.zip) is available under a BSD-like license. Dimi wrote to the developers:

I'm one of the Wine (http://www.winehq.com) developers, and I just managed to build Putty under Winelib. That is, Putty now runs as a native Linux application.

The interesting part is that I've managed to do so with virtually no changes to the source code, just a few changes to the makefile.cyg file.

Now, my question to you: are you interested in supporting Putty under Wine, as a Winelib app? If so, I can clean up my changes, and send you a patch for the build system to incorporate in your tree.

BTW, the resulting executable is about 500K, so it's not that large, compared to the Windows one at 360K.

To the wine-devel list he outlined the status in more detail:

Here's a quick status update on PuTTY as a Winelib app:

  1. It compiles, links, and runs perfectly (Yay!)
  2. I've talked to the PuTTY folks, and they agreed to add Winelib as one of their targets in their build process (provided I do the patch :))
  3. I've modified they Makefile-generation Perl scrip to do just that.

However, there were still a couple of problems using Wine's tool chain to build the app. The first problem concerned compiling an app with different Wine source and build trees; that thread is covered next. The second problem concerned some linking semantics.

3. Building Apps With Different Wine Source/Build Trees

21�Nov�2002 (11 posts) Archive Link: "winewrapper"

Topics: Winelib

People: Dimitrie Paun,�Alexandre Julliard,�

Dimi outlined one of the problems he ran into while porting PuTTY using Winelib:

Another problem developing Winelibs app while using your Wine tree. Say you have the following:

Now, say you build your myapp.exe.so OK, and you now want to create a symlink myapp -> winewrapper so you can start your Winelib app. Problem is that winewrapper resides in the source tree, and there is no way for it to figure out where the build tree is, and it needs that.

Possible solution:

Alexandre, what do you say?

Alexandre's first thought was Dimi should be launching the app in a different way, " You shouldn't use winewrapper, you should copy wineapploader and adapt it to your situation. This is what winemaker is supposed to do too, though I think it's somewhat broken right now." With that in mind, Dimi felt he could make some small modifications to deal with the location of the tree. However, Alexandre didn't like that idea since the ultimate goal was to just have it work with a plain old installation of Wine and not some special developer configuration. Dimi explained why he thought it was important:

If Wine was a mature, stable project, I'd agree with you. But it's not. The ability to make a small change in Wine, go back to the Winelib app, and test it, is invaluable. I would have simply given up debugging PuTTY f I had to go through a wine install for every little test and experiment I was making.

But beyond that, the audience for these changes are *Windows* developers. These guys know Win32, and it's probably easier for them to fix a small header problem and submit a patch, rather then complain on wine-devel. These are exactly the guys we want experimenting with Wine to get their apps to work, and for this sort of thing, you have to work out of the tree. I know I always do, I'd waste way too much time to do an install every single time.

Alexandre was still unconvinced, " Sure, but as Wine developer it's easy for you to write a small wrapper script to run from inside the source tree. That doesn't mean we should encourage it or make that the default behavior. I think it's perfectly standard to expect that you need to install a library before building an app that uses it, all other libraries behave that way. And we are not going to stabilize our environment if nobody ever uses it the way it's intended to be used."

The discussion delved into the value of Winelib and the importance of attracting Windows' developers. At one point Alexandre discussed the status of porting with Winelib:

If we ask Windows developers to start porting their stuff now, they will run into major problems and they will leave in disgust, with or without your patch.

I agree that fixing Winelib is not the number one priority, but we have to recognize that we won't attract the Windows crowd until we fix it properly. A couple of hacks here and there won't cut it.

And really, I don't think it's necessarily that much work to fix it; the main issue is identifying the problems and defining exactly what we need it to do. And I think the right approach is to have Wine developers like you try to port apps, because you know how to work around the problems; giving that task to a Windows developer at this point is not going to work IMO.

In the end, Alexandre agreed to accept a patch if there was a relatively clean way for it to work. He also made it clear it was not the proper way for this to work.

4. Implementing Import Libraries

21�Nov�2002 (2 posts) Archive Link: "winspool.drv again"

Topics: Winelib

People: Dimitrie Paun,�Alexandre Julliard,�

So the second problem Dimi ran into with porting PuTTY concerned how the app expected to link libraries. PuTTY simply linked against "-lwinspool" while Wine expects "-lwinspool.drv". Dimi explained:

The winspool.drv issue is a lot more serious than the in-tree execution. This one screws things up badly for the PuTTY build system. Should we modify winebuild to try to link with winspool.drv, and if that fails with winspool.dll when -lwinspool is given? (or the other way around, I don't know)

Alexandre already knew the solution, " The right approach would be to implement import libraries. This is already on my TODO list, I'll bump the priority a bit... "

5. wintab.dll: Better Tablet Support

18�Nov�2002�-�20�Nov�2002 (3 posts) Archive Link: "Imporving support for graphics tablets in wine (wintab.dll)"

Topics: IO

People: Robert North,�Tony Lambregts,�

Rob North wanted some info on improving support for graphics tablets:

Modern graphics tablets also provide pressure and tilt information, essential for quality graphics editors such as Painter & Photoshop. Currently graphics tablets are treated as mice in wine, and so cannot provide this information to a Win16/32 app. To access pressure & tilt info in Windows, a programmer would use the wintab.dll.

Has anyone attempted to build a wintab.dll for Wine?

I'm interested in attempting an extremely limited implementation for Painter & Photoshop, but don't want to reinvent the wheel.

Assuming nobody has done this what's the first step?

Tony Lambregts told him to go ahead and work on it since no one else appeared to be doing so. Rob agreed and opened bug #1160 (http://bugs.winehq.com/show_bug.cgi?id=1160) .

6. Wineconsole Changes

19�Nov�2002�-�21�Nov�2002 (19 posts) Archive Link: "RFC: console & curses"

Topics: Status Updates

People: Eric Pouech,�

Eric Pouech asked for some comments on some planned changes to wineconsole:

I did send a couple of days ago a first patch about the (n)curses backend to wineconsole Alexandre commented a few implementation issues in it, which may change a bit what I started with and how the wineconsole should behave:

console creation can be invoked from different contexts:

  1. the program calls AllocConsole
  2. the user starts wine thru wineconsole for his/her (favorite) CUI app (using from command line something like 'wineconsole foo')
  3. (N1) the program forks a child with CREATE_NEW_CONSOLE flags set in CreateProcess
  4. the program doesn't request anything

on the other hand, wineconsole is now able to handle two types of backend for the user interface:

A. USER: the one already in place
B. Curses: the new one using (n)curses and a regular term for display (N2)
C. no wineconsole support => by default, the windows input & output streams are hooked to stdin and stdout, but we don't provide full console support - cursor motion, screen reading...

now the final question, how to choose between A, B and C. the proposal is to fix the choice with:

why such a directive proposal ?

4 => C
is rather natural and doesn't need further explanation (one day, we could envisage to support it no longer, but that's another story)
1 => A
greatly facilitates the console creation (ncurses requires both terminal control and moreover to keep the process group leader running as long as all the children - hooked to the same terminal - are running). Very few programs use AllocConsole (and even use it). The only issue may be with winedbg which may allocate its own console on startup (N3)
2 => B
we could easily add 2 => A too (with some wineconsole parameters). Moreover, if the user wants to have the console in a specific xterm, it's doable with xterm -e 'wineconsole blablabla'
3 => A
here again it's easier to deal with. if trying to run a curses backend, we should ensure that two different wineconsoles are not currently hooked to the same terminal

If you have any comments, speak up now !!

Specifically, the 2=>B addition is interesting. Eric also pointed out that having the ability to spawn the curses backend didn't necessarily mean using the old user backend was impossible. A couple of people also requested to be able to start commandline apps without having X running.

7. Passing Commandline Arguments

18�Nov�2002 (7 posts) Archive Link: "wine commandline options"

Topics: Fixes

People: Rick Romero,�Uwe Bonnes,�,�Unknown

Rick Romero experienced a problem passing commandline arguments to a program:

So, I tried to force Pegasus Mail to load winsock explicitly using the -Z 128 option:

but wine comes back with 'Unknown option -Z'.

I'm not quite sure how these are getting parsed

Several people pointed out he needed to tell Wine that there were commandline arguments to be passed on. Uwe Bonnes gave an example:

Options for the win-programm should be given after a blank "--" E.g.

After doing so, Rick reported success getting Pegasus Mail to work:

Doh. It's even in the Pmail KB article below, and I didn't see it.

Pegasus Mail TCP/IP works after reading the following KB article from pmail: [ LINK (http://kbase.pmail.gen.nz/viewfull.cfm?ObjectID=E1D7B847-576A-4BA3-BEE13F10C9FF1D02) ]

I think if you don't start Pmail the first time with the -Z 128, it sets an option to never load it.

The article referenced describes running Pegasus Mail with Wine.

8. Terminal Based Apps

15�Nov�2002 (5 posts) Archive Link: "Wine without any X11 environment"

Topics: Fixes

People: Michael Riedel,�Patrik Stridvall,�,�Patrik Stridval

Michael Riedel asked a question that might be helpful for others, " is it possible to use wine in a telnet session to start a (command line) windows application? I get the error that x11drv can't connect to a display (which is correct). I'm also not very sure that the windows program itself does not perform some graphic related queries (there were some fixme messages when I tried to use 'ttydrv'). Any ideas? Is there any workaround to use a dummy display or whatever? "

Patrik Stridvall explained a possible reason for the problem and possible alternative:

If the application directly or indirectly loads GDI32.DLL or USER32.DLL it also load the x11drv with the result above if DISPLAY isn't set.

In addition to the ttydrv (as you meantion above) you can use VNC like:

Other folks tried running some programs using the ttydrv graphics driver but ran into some problems with it bombing out.

9. Assumptions with autoconf

19�Nov�2002 (10 posts) Archive Link: "Configure question"

Topics: Build Process

People: Martin Wilck,�Patrik Stridvall,�Alexandre Julliard,�,�Patrik Stridval

Martin Wilck posed a question about the configure process:

I am thinking about some netapi32 improvements where I'd need to call the functions of the getpw/getgr family: getpwnam(), getpwent(), getgrent(), etc.

Configure checks for the "pwd.h" header and getpwuid(). Must I add more checks for all the functions I use, or is it ok to assume that getpwuid() presence implies getpwnam() presence?

Patrik Stridvall replied:

Good question. I'm don't think we have any policy concerning this. Perhaps we should have.

One thing that you shouldn't assume is for example that if a function exists its reentrant variant exists as well.

For example that fact getpwnam exists doesn't imply that getpwnam_r exists. And yes, you really should use the reentrent variant if present as well as having an alternative implementation if not.

As to the implict existance question: I'm not sure. First of all, to answer the related question: Should you have a alternative implementation for defined(HAVE_GETPWUID) && !defined(HAVE_GETPWNAM)?

IMHO the answer is no. It is not worth the effort to support hypotetical platforms unless we can verify the existance of one.

To return to the original question: I suggest that we should detect the presence or absence of ALL function we use that is verified not to exist on some platform and have for example code

Alexandre felt it was worth being cautious by making sure any called function was there, " it's trivial to check for both. If you use getpwnam() check for HAVE_GETPWNAM, if you use getpwuid() check for HAVE_GETPWUID. Simple, logical, and works even on strange platforms."

10. COM Objects Doc

13�Nov�2002�-�21�Nov�2002 (10 posts) Archive Link: "COM Enhancement patch"

People: Christian Costa,�,�Unknown

Christian Costa wrote a note to wine-devel and ended it with, " PS: I've joined a small doc that explains how to use objects with multiple interfaces. This docs is based on what has been done before with the ddraw code plus the enhancement I did. "

So I decided to take it and HTML-ify it:

COM OBJECTS MANAGEMENT

  1. Definitions
    1. Object Classes

      An object class is a structure wich defines the data of an object and all the interfaces that act on the object data

      Example :

        struct ObjectClass {
          INTERFACE 1;
          INTERFACE 2;
          ............
          INTERFACE N;

          DATA;
          } ;
        typedef struct ObjectClass ObjectClass;

    2. Objects

      An object is a instance of an object class.

      Example :

        An object is created as follows :
          ObjectClass* object = malloc(sizeof(ObjectClass),...)

    3. Interfaces

      An interface is a way for an application to interact with an object. It contains a pointer to a virtual table plus some other data than can help objects management.

      An interface is a structure, which is used internally, that can be defined with the INTERFACE macro :

        #define INTERFACE(iface) \
        struct { \
          iface interface; \ /* VTABLE */
          LPVOID object; \ /* pointer to the object the interface belongs to */
        }

      To add a field to the interface, just add it in this macro.

      For example, we could embed the version number inside an interface or a magic number to check if the interface's pointer points to a real interface. And, off course, modify some macros or create new ones to make use of them.

  2. Implementing COM objects
  3. Declaring a COM object with multiple interfaces

    To declare interfaces in a COM object the ICOM_VFIELD_MULTI must be used for each interface as shown below:

      struct IDirect3DImpl
      {
        /* IUnknown fields */
        ICOM_VFIELD_MULTI(IDirect3D);
        ICOM_VFIELD_MULTI(IDirect3D2);
        ICOM_VFIELD_MULTI(IDirect3D3);
        ICOM_VFIELD_MULTI(IDirect3D7);
        DWORD ref;
        /* IDirect3D fields */
        IDirectDrawImpl* ddraw;
        LPVOID private;
      };

  4. Creating an object

    Just declare an pointer to an object and allocate the memory for it. Example:

      IDirect3DImpl* object = malloc(sizeof(IDirect3DImpl),...)

  5. Initializing interfaces

    It is done with the ICOM_INIT_INTERFACE(object_pointer, interface_name, virtual_table)

      ICOM_INIT_INTERFACE(object,IDirect3D, VTABLE_IDirect3D);
      ICOM_INIT_INTERFACE(object,IDirect3D2,VTABLE_IDirect3D2);
      ICOM_INIT_INTERFACE(object,IDirect3D3,VTABLE_IDirect3D3);
      ICOM_INIT_INTERFACE(object,IDirect3D7,VTABLE_IDirect3D4);

  6. Retrieve an object from within an interface's function

    If we consider the function :

      IDirect3D_AddRef(IDirect3D iface,.......)

    To retrieve a pointer to an object within the function, both followings macro are used :

    1) ICOM_OBJECT(object_class,iface)

    This macro return an pointer to the object, the value is of object_class* type

    Example:

      IDirect3DImpl* d3d = ICOM_OBJECT(IDirect3DImpl,iface);

    2) ICOM_THIS_OBJECT(object class,iface)

    It simply declares a This pointer and initialize it with the object address.

      IDirect3DImpl* This = ICOM_OBJECT(IDirect3DImpl,iface);

  7. Sharing functions between multiple interfaces

    In the case where a function does no have to do specific actions depending on the interface, you can share directly a function.

    Example :

    If we consider the function :

      IDirect3D_AddRef(IDirect3D iface,.......)

    The different virtual tables would be :

      VTABLE_IDirect3D = {......,IDirect3D_AddRef,....);
      VTABLE_IDirect3D2 = {......,XCAST()IDirect3D_AddRef,....);
      VTABLE_IDirect3D3 = {......,XCAST()IDirect3D_AddRef,....);
      VTABLE_IDirect3D7 = {......,XCAST()IDirect3D_AddRef,....);

    Note that this is possible because the ICOM_OBJECT can retreive the object's pointer without knowing the interface involved.

  8. Thunking interface

    Interface thunking enable changing from one interface to another.

    The following macro COM_INTERFACE_CAST(impltype, ifnamefrom, ifnameto, ifaceptr) performs this task.

    • impltype = object class
    • ifnamefrom = interface type we have
    • ifnamefrom = interface type we want
    • ifaceptr = pointer to the interface to cast
    • return = pointer to the casted interface

    Interface thunking is a another way to shared a single function across different interfaces but as shown below this is required only when structures must be translated, interfaces returned casted or to handle prototype change :

    Example:

    You want to share the IDirect3D_CreateDevice across all IDirect3DX interfaces (with X above 1 because a device in Direct3D is created in a different way).

    IDirect3D2_CreateDevice(IDirect3D2* iface,.....) is the only one implementation of the function.

    The others are thunks to the IDirect3D2_CreateDevice.

      IDirect3D3_CreateDevice(IDirect3D3* iface, .....,LPDIRECT3DDEVICE3 *lpdevice, LPUNKNOWN lpUnk)
      {
      IDirect3DDevice3 *dev;
      IDirect3D_CreateDevice(ICOM_INTERFACE_CAST(IDirect3DImpl,IDirect3D2,IDirect3D3,iface),.....,&dev);
      *lpdevice = ICOM_INTERFACE_CAST((IDirect3DImpl,IDirect3D3,IDirect3D2,device)
      }

      IDirect3D7_CreateDevice(IDirect3D7* iface, .....,LPDIRECT3DDEVICE7 *lpdevice)
      {
      IDirect3DDevice2 *dev;
      IDirect3D_CreateDevice(ICOM_INTERFACE_CAST(IDirect3DImpl,IDirect3D2,IDirect3D7,iface),.....,&dev);
      *lpdevice = ICOM_INTERFACE_CAST((IDirect3DImpl,IDirect3D7,IDirect3D2,dev)
      }

    Here, we have to deal with a returned interface and a prototype change.

    The VTABLE should be:

      VTABLE_IDirect3D2 = {......,IDirect3D2_CreateDevice,....);
      VTABLE_IDirect3D3 = {......,IDirect3D3_CreateDevice,....);
      VTABLE_IDirect3D7 = {......,IDirect3D7_CreateDevice,....);

    Note that there are few functions that need this, for the others, thunks are not necessary and the way described in e) must be preferred.

  9. Getting an specific interface of an object

    With the ICOM_INTERFACE(implobj, ifacename) macro, any interfaces can be retreive from an object.

    • implobj = pointer to the object
    • ifacename = interface name we want
    • return = pointer to an interface

    Example:

      IDirect3DImpl* object;

      ............

      IDirect3D3* iface_d3d3 = ICOM_INTERFACE(object,IDirect3D3)

  10. Calling an COM object functions from another

    If a function is shared across multiple interfaces, you should write:

      IDirect3D3_CreateDevice(IDirect3D* iface,.....) { ICOM_THIS_OBJECT(iface); ................. IDirect3D_AddRef(ICOM_INTERFACE(This,IDirect3D),.....); ................. }

    If you know the nature of iface (i.e. thunking is used or the function is used in only one interface), you can write :

      IDirect3D3_CreateDevice(IDirect3D* iface,.....) { ICOM_THIS_OBJECT(iface); ................. IDirect3D3_AddRef(iface,.....); ................. }

11. Threads and CoInitialize

13�Nov�2002�-�19�Nov�2002 (5 posts) Archive Link: "CoInitialize"

Topics: Memory Management

People: Steve Lustbader,�Ove Kaaven,�,�Ove K�ven,�Greg Turner

Steve Lustbader was running into a problem with a threaded app, " One of the threads in my app calls CoInitialize, expecting it to return S_OK (in fact, it's followed by an assert statement requiring that it returns S_OK). When I run it in Wine, however, CoInitialize returns S_FALSE, implying that this thread has already initialized the COM library. Other threads call CoInitialize, but this is the first time that this thread calls it. Does Wine initialize COM differently from Windows? Are the other threads' calls to CoInitialize screwing up this thread's call? "

Ove K�ven thought he recognized the problem and diagnosed it as something not in the Wine tree yet:

Sort of, the problem is that Wine doesn't support apartments yet, so it doesn't try to keep track of the threads that has called CoInitialize.

Code to support apartments was part of a large code drop (sent to rewind-patches) a long time ago, along with a pile of rpcrt4 code, however this apartment code was never merged into Wine, and the rpcrt4 pieces was only merged recently when Greg Turner took an interest in it. And I don't really expect that COM apartment code to get merged in before proper interface marshalling (which is largely rpcrt4's job) is working either, though I suppose the pieces that keep track of them (so that CoInitialize gives the right return value) could be merged if someone wanted to.

Later he briefly explained a little more about the thread problem, " COM functions still works, but only in a process-wide fashion, oblivious to which thread calls them."

Sharon And Joy

Kernel Traffic is grateful to be developed on a computer donated by Professor Greg Benson and Professor Allan Cruse in the Department of Computer Science at the University of San Francisco. This is the same department that invented FlashMob Computing. Kernel Traffic is hosted by the generous folks at kernel.org. All pages on this site are copyright their original authors, and distributed under the terms of the GNU General Public License version 2.0.