Code Questions, Discussions and some Answers
From Wine-Wiki
[edit] Code Questions, Discussions and Some Answers
This is not official. Wine updates fast, so this will get out of date real quick. If you see an error, make a note with the date so others can see how recent it is.
[edit] Implementing Dlls
A Programmer asked about msxml: is [this] implementing
- msxml.dll (Version 1.0) comes with IE4.0 or
- msxml.dll (Version 2.0) or
- msxml2.dll (Version 2.5/2.6) or
- msxml3.dll (Version 3.0)
M.McCormack: It's aimed at implementing msxml3.dll, however the declarations should be independent of which version you're using. If you wish to extend the definitions, you should make sure to consult the Microsoft Windows SDK, which you can download from Microsoft free of charge.
[edit] Fake Dlls
A. Julliard: [May 06] I don't think we want to require creation of fake dlls for all builtins that contain icons. Fake dlls should only be created when real apps need them, not for internal Wine purposes. wine archive
[edit] RPCRT4
M. McCormack [May 06]: rpcrt4 seems to work something like:
- Client sends NTLMSSP_NEGOTIATE to server on first outgoing packet
- Server sends NTLMSSP_CHALLENGE to client on first incoming packet
- Client sends NTLMSSP_AUTHORIZE to server after receiving challenge
- Client attaches authorization context to further packets
Calling RPCRT4_AuthNegotiate() in the above code snippet is step 1 and as a side-effect, the Connection->ctx is set to something non-zero, and we won't go down that codepath again.
This scheme currently only works for NTLM authentication, and may need slight modification for other authentication schemes, but that's all I'm interested in at the moment.
Initially I was using the dcom98 version of secur32 for testing, as the builtin doesn't support SECURITY_NETWORK_DREP as yet. Now I'm using a hacked up builtin secur32 that generates the required NTLM exchange independently of ntlm_auth. I'm hoping to submit a patch for secur32 that works as above but falls back to ntlm_auth for exchanges its not capable of (ie. most of them). wine archive
[edit] Memory
[edit] Memory Leak Detection
A. Mohr: valgrind [should be] the default leak detection method in Wine.
Reasons:
- it catches many, many leaks *without any reprogramming effort*
- it catches many, many other problems
- it has other tools which are very useful, too (cache profiling, ...)
M. McCormack: The main disadvantages are:
- it slows down Wine and programs running Wine. (Office 2003 install already takes a minute or so) - it doesn't differenciate between Wine leaking memory and a program running in Wine leaking memory - it requires a patched version of Wine to run - it isn't built into Wine (ie. I could ship this patch with minimal overhead, and have my users point out memory leaks) - it has issues following forks, and being run from scripts
The patch is not meant to replace valgrind, just to provide another way of finding problems in Wine code.
Ed. According to some comments on the mailing list in 2005 Some progress has been made on running Valgrind with Wine.
Mike McCormack [Sept 05] came up with another way to find memory leaks in Wine's code. It needs to be adapted for each DLL to make use of it and Mike did it for MSI.
Mike: This patch is written for MSI, but could be adapted to other code. It keeps a linked list of allocated memory and removes free'd memory from the list. It requires that you change all the HeapAlloc's or mallocs in a dll to msi_alloc (for example), but can detect unfree'd memory and invalid free's. I have discovered quite a few problems in my own code with this patch, so hopefully somebody else will find it useful too.
Further reading
[edit] Graphics
[edit] Benchmarking
Winehq Bugzilla entry 21515 S. Dosinger: glxgears is a really lousy benchmark, but I guess everyone knows this by now. Quake 3 is a lousy benchmark for today's cards as well. No shaders, no FBOs, no nothing except a few textured triangles with fog. The game gets quite decent rendering results with that though. 3DMark2000 and 2k1 are pretty outdated as well. They do use shaders though.
For really informative driver benchmarking I recommend Half Life 2, Team Fortress 2, 3Dmark 2003, 3Dmark 2000, 3Dmark 2001, UT2004(native if you want to). 3Dmark2k is pointless on its own, but still good to test legacy features. It points out quite bad performance with fixed function rendering on fglrx for example that isn't spotted by HL2 and TF2.
http://84.112.174.163/~stefan/imac/halflife2/results.php http://84.112.174.163/~stefan/imac/3dmark2000/results.php (first-gen iMac running Linux)
The HL2 results are pretty combative for a radeon X1600(except the last few, due to a known wine regression), while the 5500 3dmarks are pretty bad.[..] Even more serious benchmarking, but those games run into a few Wine bugs, so they're less useful for Wine developers:
- Left 4 Dead
- Call of Duty: Modern Warfare 2
- Unreal Tournament 3
- 3Dmark 2006
[edit] Driver Quirks
Winehq Bugzilla entry 21515 S. Dosinger: There are no written rules towards which quirks are accepted into git, but it goes somewhat like this: A quirk is ok if:
- It is using an unspecified driver behavior to our advantage(e.g. the specular color quirk or the normalized texrect quirk)
- There's a driver bug that is unlikely to get fixed anytime soon(e.g. legacy proprietary driver, or Apple drivers) and it hurts a wide range of apps(e.g. NVTS disable quirk on OSX)
- A genuine hardware limitation that cannot be adequately queried from GL(NP2 texture disable on Geforce FX, NP2 texture disable on r300-r500)
- A driver bug that causes a kernel panic or X server crash when running the wine tests(Otherwise people are afraid of running "make test"). E.g. point
sprite quirk on fglrx.
Since it is comparably easy to get an open source driver fixed we try to avoid quirks for them, except if they're in the last category(People are often running old drivers, working on a non-d3d area of wine, run "make test" and get a kernel panic)
[edit] X vs win32
R. Shearman Aug 08 wine bug 14767: Due to various technical reasons and incompatibilities between win32 and X11 Wine only uses 1 X11 window for a program and does all subwindow drawing itself (on windows buttons, textboxes and so on are subwindows but on wine those aren't X11 subwindows). For OpenGL this caused major issues and the most problematic one is that the OpenGL window was shared with generic win32 gdi rendering.
Adding a X11 subwindow specially for OpenGL was not an option due to event issues and other technical reasons. In the end we decided to do windowed OpenGL rendering (with this I mean rendering as in apps like Google Earth which mix a win32 gui with OpenGL; this is something different than win32 apps with just a basic menubar or no win32 gui at all) to an offscreen buffer. The contents of the offscreen buffer is copied to the window.
The problem is the offscreen buffer. For that we are directly rendering to a toplevel X11 window which is made offscreen using the Composite extension. In other words we are using 'redirected GL rendering'. Not much display drivers support this yet. Nvidia has been offering it for some time and further I believe recent (experimental?) Intel drivers offer it. This same functionality is also needed to render e.g. a glxgears window on one of the faces of a Compiz cube.
[edit] how does windows drawing gets translated into X in wine
M.Hearn: x11drv is built like a graphics driver would be in real windows. It's loaded in dlls/user/user_main.c, and then the USER and GDI driver table is filled via GetProcAddress. The USER/GDI calls then delegate to the x11drv via function pointers when necessary.
V. Margolen when discussing a regression with PaintShopPro7 (May2005) gave further information: x11drv is more low-level interaction with X. Everything in windows/* belongs to dlls/user. And dlls/user/ is more of a top level type of things. Bellow all of this is server/ that tracks a number of things, but (as I understand) doesn't do anything itself. For example: SetWindowPos is defined in dlls/user/winpos.c, but all it does, is calls X11DRV_SetWindowPos in dlls/x11drv/winpos.c (for console apps it's somewhere else). Then X11DRV_SetWindowPos does the whole work itself, using some information from the server for that.
The [current] problem, as I see it, comes from two places:
- Wine does not have full implementation of number of things, or it's not correct (good enough for apps people where running when they implemented that part).
- Interaction with X and window manager (wm) puts some restrictions to what can and can not be done. If certain thing is missing from X then it can't be implemented in wine (like some of OpenGL stuff). Same goes for wm (like handling of WM_MINIMIZE/WM_MAXIMIZE). It requires closer interaction with wm which is not implemented yet.Wine Archive Link
[edit] Keeping DIBs syncronised between applications and the X server
A programmer [Nov 05] queried about the X11DRV_CoerceDIBSection function and the logic behind using 'DIB_Status_GdiMod' and 'DIB_Status_AppMod' stats?
R. Shearman: That code is designed to keep DIBs sync'ed between applications and the X server. When the application does a Win32 GDI call then the state of the DIB gets set to DIB_Status_GdiMod and the memory that backs the DIB is set to no-access so that a page fault occurs if the application tries to read it. A handler detects this and downloads the DIB from the X server and sets the state to DIB_Status_None. In this state the DIB memory is set to read-only, so that a page fault occurs if the application tries to write it. The same handler also detects this and consequentially sets the DIB state to DIB_Status_AppMod and allows full access to the DIB memory. wine archive
[edit] Wine d3d to WGL status
The official wine wiki has information on this topic
[edit] Keyboard
A programmer posted some research to the list: what scancode, keycode and vkey are! :)
Some references:
- ScanCode and KeyCode
http://lct.sourceforge.net/lct/x60.html http://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO-2.html http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
- Virtual-Key Codes (vkey)
I thought the problem was in TranslateMessage (dlls/user/message.c) and X11DRV_ToUnicodeEx (dlls/x11drv/keyboard.c) functions but I found others suspects: EVENT_event_to_vkey and X11DRV_InitKeyBoard (boths in dlls/x11drv/keyboard.c).
What is happening? (in brazilian abnt2 keyboard with wine-0.9.9)
The EVENT_event_to_vkey function return the wrong value 0x2E to X11DRV_KeyEvent which emits an event through X11DRV_send_keyboard_input.
On MSDN and dlls/user/spy.c VK_SEPARATOR virtual key code apears as 0x6C, however in trace below apears as 0x2E while in both cases keycodes are equals. The 0x2E virtual key code value corresponds to VK_DELETE. wine archive
[edit] Clipboard
A user asked: How do I get some graphics data from the Windows clipboard to the X (Linux) clipboard?
M. Hearn[May 05]: We probably need to change Wine so that we convert the format Windows programs use to store image data on the clipboard to the formats that Linux programs can understand. Usually Win32 programs paste as BMP, but this is a Win32 specific format. Linux apps usually expect PNG or JPEG.Wine Archives
The user suggested: ImageMagick would do nicely. Or, (easier to code, more flexible, but a bit kludgy): save it as a file in .bmp & let the user convert it. A more general problem is getting Windows specific formats into linux apps. E.g. if I recall correctly, formatted text goes into the Windows clipboard as RTF. A flat file that maps Windows format to Linux format, and provides the command line and any options to do the conversion would be a nice user configurable way to handle it.
In the present case: bmp.png /usr/local/bmp2png
where bmp2png is a shell script wrapper to play games with the extension and run the conversion. Would it be possible to keep the Windows format in the Wine clipboard and deliver the converted format to the X clipboard?
M. Hearn: Yes this is all possible, but the conversion should be done in C inside Wine rather than callouts to external apps like ImageMagik.
[edit] DirectX
1 bit stencil
A programmer noted the 1bit stencil
> + if (visual == NULL) {
> + /* fallback to a 1 bit stencil (opengl states that at least 1 bit of stencil must be provided for on of the available configurations) */
> + WARN("Failed to get a visual with at least 8 bits of stencil\n");
> + int dblBuf2[] = {GLX_RGBA,GLX_DEPTH_SIZE,16,GLX_STENCIL_SIZE,1,GLX_DOUBLEBUFFER,None};
> +
> + wine_tsx11_lock();
> + visual = pglXChooseVisual(display, DefaultScreen(display), dblBuf2);
> + wine_tsx11_unlock();
> + if (visual == NULL) {
> + /* This should only happen if we cannot fidn a match with a depth size 16 */
> + FIXME("Failed to find a suitable visual\n");
> + }
> + }
It's always nice to have a fallback, but in real life I've never seen PC hardware (even back to the 90s) which supports a 1-bit stencil buffer and not a 8-bit stencil buffer, so this may be over-redundant. (Would be interested in hearing of any consumer hardware which only does a 1-bit stencil.)
J. Ericksson: Sun ELC. Not exactly consumer hardware though.
Directx expert O. Stieber: OpenGL requires that a stencil is supported for at least on of the modes, the problem with creating a stencil buffer only when needed is that the windows and hence the visual ID is created before directx is loaded and I don't think that directx should be messing with anything that's come out of x11drv just incase it causes regression somewhere else. There it should only be the additional memory usage that causes a negitive impact on performance if the driver uses software for stencil buffers and the stencil buffer isn't used.[...]The fallback is there because 1 bit stencil is the minimum required by the opengl specification, so it is possible that somewhere there is a driver that only supports 1 bit stencil. [...] there's a good chance that some older applications may use a 1bit stencil to speed things up. applications that would generally be regarded as 2d can make use of a 1bit stencil buffer for masks and screen wipes. e.g.
I wouldn't expect someone with hardware that doesn't support 8bit+ stencils to be playing the latest games, but there's potential for them to be using other applications that require a simple stencil buffer, or simple 3D an no stencil at all, in which case they require some kind of fallback.
Further reading
[edit] Video
Video Capture
One programmer said: i would like to implement this function:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_cappreview.asp
Here fpProc is a pointer to the preview callback function. Applications use this to get access to the videodata. Right now i already have a preview window. So how could i pass the data in lpVideoHdr to the application?
E. Pouch: it seems that you open somehow a capture session.Within this session, you can set a user defined callback to be passed every frame captured. On the WM_CAP_SET_CALLBACK_FRAME message, your session should store the pointer to the function in the session data (you should have something for that somewhere). Everytime you complete the capture of a frame in a given session, and this callback has been defined, then you should call it (by passing the current LPVIDEOHDR which is likely to be the structure to contain the data for the captured frame).
R. Kalbermatter: avicap32 won't implement the callback function, but your application will do that. avicap32 only will call it. _win32_cappreview.asp function (or rather a macro) is only to enable or disable the preview mode. There isn't any callback function I can see here. It is rather about a preview of the actual capture data in the capture window itself. You can install a frame callback with capSetCallbackOnFrame() and this callback function will be called for every frame BEFORE it is diplayed in the preview. As far as I understand it, the preview callback as you call it is rather installed by the capSetCallbackOnFrame() macro and ultimately by the WM_CAP_SET_CALLBACK_FRAME message. MSDN doesn't directly specify the actual callback prototype of this callback, but it if you search further you can see that the capVideoStreamCallback() prototype is both used for the WM_CAP_SET_CALLBACK_FRAME and WM_CAP_SET_CALLBACK_VIDEOSTREAM callbacks.
To pass the data in lpVideoHdr to the application, it seems that you open somehow a capture session. Within this session, you can set a user defined callback to be passed every frame captured. On the WM_CAP_SET_CALLBACK_FRAME message, your session should store the pointer to the function in the session data (you should have something for that somewhere). Everytime you complete the capture of a frame in a given session, and this callback has been defined, then you should call it (by passing the current LPVIDEOHDR which is likely to be the structure to contain the data for the captured frame). I believe that the capture session is inherently tied to the capture window created with capCreateCaptureWindowA/W(). After all, the capture API dates back to Windows 3.x where it was common to do background processing by delegating the action to a window message loop, since no other multitasking method was available. Maybe that 32bit Windows has another implementation for this, but I'm not sure.
Further Reading
[edit] Colour
T. Wickline: The International Color Consortium specification is located here :http://www.color.org/icc_specs2.html as well btw.
[edit] Dialog Boxes
[edit] Automate a click on OK for dialog box using code
A Programmer asked: I'm trying to figure out if there is a way to short-circuit a dialog box [from code where the source is unavailable]. I've been developing against the Wine libraries (I don't use Windows natively). The tool I've been writing loads and runs DirectShow DLLs via the IFileSourceFilter APIs. Basically, I want to traps calls to DialogBoxParam, pump calls into lpDialogFunc for dialog init, and then clicking of the "Ok" button, and finally trap calls to EndDialog.
S.Shemesh: For simple things, merely sending the dialog a WM_COMMAND with the right parameters will do it for you. You can programatically find the dialog using "FindWindow". I've done such things before. For simple things, this works very well. As soon as things stop being simple, this gets very hairy very fast. Just hope that your case is a simple one.
Success was found: ah-ha, yes. I ended up using EnumWindows (filtering out the HWND from GetTopWindow). Thanks! WM_COMMAND, IDOK, 0 did the trick. Wine Archive Link
[edit] is there any way to stop a dialog from displaying itself?
Is there any way to stop a dialog from displaying itself? (i.e., let dialogs become active, but not draw themselves?) The ttydrv doesn't like trying to open the dialog:
fixme:ttydrv:TTYDRV_GetBitmapBits (0x7d, 0x76d3501c, 128): stub
A Wine Expert reported: YOu could trap it#s onshow event but be careful since most dlgs are created as modal , you could end up hanging your process.
[edit] Unicode Discussions
[edit] Automatic Ansi <> Unicode Translation
A Programmer [July 05] reported having a problem with an application: It posts WM_CHAR messages to a ANSI window with Unicode value in LOWORD(wParam). Wine automatically translates the character code to ANSI (producing a "?" when there is no such code in CP_ACP). Windows does not do it (contrary to documentation). [He posted a sample application which showed the problem and proposed a patch]
D. Timoshkov: All messages which potentially go through wineserver should be posted/sent via unicode
T. Rollo: If you call SendMessageW under native Windows the translation happens. If you call SendMessageA it does not. This is all exactly what I would expect. By my test, sending 0xf301 with SendMessageA gets 0xf301 on Windows, and with SendMessageW gets 0x003f. Sending with SendMessageA on Wine gets 0x0001 and with SendMessageW gets 0x003f.[...] Locale doesn't affect the A->W translation. I know that is counter-intuitive and it surprised me when I found out (and verified) this. The system dialogs where you can change these things tend to obscure this. I tested the CP_ACP conversions and the GetACP call. I also disassembled kernel32.dll to see how it populated CP_ACP (if I recall correctly it populated it from a registry key under either HKEY_CURRENT_CONFIG or HKEY_LOCAL_MACHINE, so perhaps a change in the registry could cause the same behaviour as a process calling SetCPGlobal, but threads within a single process can never have a different CP_ACP).
F. Nava clarified further: Actually it affects the CP_THREAD_ACP code page, but not CP_ACP.
T. Rollo: [currently] It isn't used anywhere in Wine (it's returned, but nothing ever calls a routine with CP_THREAD_ACP). I
suspect not a whole lot of apps use it either since it's Win2K and higher only. Its existence suggests a whole truckload of new tests needed to check its behaviour. Interestingly though, SetThreadLocale is NT3.1 or higher, so an app using it in Win2K and higher gets a different result to what it would get on earlier versions if CP_THREAD_ACP is used by Windows for internal A->W and W->A conversions.
A. Julliard: Since there is no way of knowing if the target window uses the same code page, or even if its code page won't change between the time the message is stored in the queue and when it is retrieved, the only sane approach is to store messages in the queue in Unicode. Only SendMessage calls that bypass the queue avoid the translation. I'm pretty sure that this is what Windows does too, if you have a test demonstrating the opposite I'd be very interested to see it. [A new patch was offered taking into account the various comments] Wine Archive
[edit] Themes
Theming support: When comctl32.dll is attached to a thread, a CBT hook is set up for the current thread which intercepts all window creations. There, the class name of the window is checked. In case of a known class, the window is subclassed, and the subclass is handling the theming-related stuff. Add initial theming support for the "Button" class.
This method of implementing themes was queried in the forum: Not that I am any kind of expert here but would it not make sense to implement things the way windows does it? From what I know, windows implements it via activation contexts and manifests.
F. Richter explained the rationale: Yes, doing it the exact Windows way would require to implement all that side-by-side DLL stuff - what you mentioned and probably more - first. Which requires significant effort. Doing it with hooks from comctl32 is an approximation of the Windows way (actually, they re-implement the controls in comctl32 6.0, we just partially) that works quite well - here and now.
[edit] Mouse
The official wiki has a number of pages which refer to Mouse issues. Since wine has made a lot of progress some of the issues listed here will be out of date.
- http://wiki.winehq.org/PatchMouseHack
- http://wiki.winehq.org/DInput
- http://wiki.winehq.org/VitaliyMargolen
[edit] WM_LBUTTONUP
After discovering a problem with a WM_LBUTTONUP msg that was never being sent, a patch was suggested to make sure all msg's are dispatched while tracking a WM_LBUTTONDOWN msg.
R. Klazes: Patches like this have been proposed before. They are wrong: Windows *does* eat the WM_LBUTTONUP in the mouse track message loop. There are cases when in Wine this mouse tracking is entered, where they are not under Windows thus causing loss of messages.Wine Archive Discussion Link
Further Reading
- http://www.winehq.org/hypermail/wine-devel/2004/05/0159.html
- http://www.winehq.org/hypermail/wine-devel/2004/09/0072.html
[edit] MouseMove and Listview
J. Hawkins: 'we [could] track the mouse by calling TrackMouse when the mouse moves.'
A. Julliard [May 05]: What you really want is to only start tracking if it moves by more than a certain amount, which is what LISTVIEW_TrackMouse already tries to do in a very inefficient way. So you should probably move all the logic from LISTVIEW_TrackMouse to the MouseMove handler.Wine Archive Link
Patch was then logged on cvs by J. Hawkins: dlls/comctl32 : listview.c
- Store the click point in LISTVIEW_INFO.
- Move mouse tracking to MouseMove.
- Use DragDetect instead of TrackMouse.
- Remove the unused TrackMouse function.
Patch: http://cvs.winehq.org/patch.py?id=17583
[edit] Mouseover
While working on Theming, a programmer submitted code for review:
> + /* internal stuff */ > +#define BUTTON_HOT 0x80000000 > +#define BUTTON_INTERNAL (BUTTON_HOT)
K. Koltzau: Under windows, the mouseover state is 0x200
The programmer asked for clarification: is there a constant or so for this? Is the mouseover state also returned by BM_GETSTATE?
K. Koltzau: There is no constant, but it is returned in BM_GETSTATE Wine Archive
[edit] Mouse Warp
Stefan: It looks like that the mouse warp is used for applications which read the mouse moves. But the cursor still exists and if it reaches the boarder of the screen X wouldn't report any changes in the mouse position, so wine constantly warps the mouse back to the middle of the screen.
MSDN states that there's no cursor handled by windows in ddraw fullscreen mode and that apps have to rely on mouse moves and draw the cursor themselves if they need one. Settler 3 seems to read the mouse moves and set the cusor, which is correct. But wine sets the cursor back to the center of the screen and thus eliminates the mouse move. Are my observations correct? In this case any game which uses DDSCL_FULLSCREEN, DirectInput and the mouse cursor this this way will fail.
Settlers 3 has a strange problem with the fullscreen mode. It sets WS_CAPTION in it's main window's style and the DDSCL_EXCLUSIVE and DDSCL_NORMAL flags when calling DirectDraw_SetCooperativeLevel. In Managed mode my window manager draws the window caption and the contents of the window are missplaced. In Desktop mode wine reserves space for a window caption and missplaces the contents of the window and I get a black window caption inside the Desktop window. I worked around this problem by filtering the WS_CAPTION flag in Main_DirectDraw_SetCooperativeLevel, which is not correct but works for that game. This doesn't influence the mouse warp problem, but I thought it might be worth mentioning.
L. Ulmer: Basically yeah. It comes mostly from the fact that DInput requires relative mouse movements (a mouse does not report any absolute axis in Windows and if you request absolute mode, it's completely broken, even on Windows). The problem is how to handle a case when the user continuously moves his mouse to - let's say - the right and that your mouse cursor reaches the edge of your screen ? X11 will always report the same X coordinate and thus even if the user moves his mouse, Wine will report to the game that the mouse did not move in the horizontal direction.
So a part from an X11 extension (which I plan to work on again one of these days with the X.org guys), the only way to support this is via mouse warping (note that DGA mouse exists, but well, it's a bit ugly and is a bit frowned upon by the X people now).[He then went on to mention a patch he would work on Wine Archive Link]
[edit] Sound
[edit] Alsa and Sound
D. McCall gave a description of the Alsa-driver and his patch [...for those ]who don't necessarily know how sound hardware works.
Basically, sound data is stored in a circular buffer. The hardware loops through the buffer and outputs the data as sound. When it gets to the end of the buffer, it immediately goes back to the beginning of the buffer and continues. So, after the hardware has gone past a particular point in the buffer it is up to software to fill buffer at that point with new data (otherwise the hardware will play the same sound again when it loops back). If the software doesn't provide the new data quickly enough, you have a situation known as a buffer underrun. Whatever sound or portion of sound was in the buffer might then be played several times as the hardware loops over the same data again and again (this may be why you heard "got it covered - ered - ered.." as mentioned in a previous post).
Previously Wine's Alsa driver was using an undocumented internal Alsa call to (_snd_pcm_hw_get_ptr, or something like that) to get the hardware's current buffer position (the "play position"). Apart from the fact that the method is only supposed to be used internally, there's the problem that Alsa provides "plug" devices (and others) which effectively insert another layer between the application and the hardware. The plug layer can do things like sample rate conversion (some hardware can only do a limited range of sample rates. AC'97 hardware for instance can generally only do 48000 samples per second or an integer division of that, whereas many software programs expect to be able to do 44100 samples/second. It's interesting that older hardware seems to be more flexible in this regard.) If the Alsa plug layer is in use (which it is by default[...]), a different buffer size may result and the raw hardware pointer value is less meaningful.
Alsa's model for buffer manipulation is that the application (i.e. Wine) requests a portion of the buffer using snd_pcm_mmap_begin() method, where you specify the maximum amount you want to work with at the moment. The call gives back the amount actually available, the location of the buffer, and the offset into the buffer of the available block. Then the application fills the block with sound samples and calls snd_pcm_mmap_commit() to tell Alsa that data is available. The key thing here is that the amount of buffer actually available depends on the hardware pointer position. When snd_pcm_mmap_begin() is called Alsa will only allocate from the currently committed region (so called "application pointer") up to the current hardware playback position (the "hardware pointer"), or it's equivalent position in the translation buffer (if direct hardware access is not used). If you request a sufficiently large space when you call snd_pcm_mmap_begin() you can, therefore, determine the current playback position within the buffer.
This is one of the things that my patch does - when snd_pcm_mmap_begin() is called, the returned offset is saved in This->mmap_ppos. (It would be more correct, technically, to save the offset plus the allocated size - but in practice this isn't really necessary, seeing as the allocated size is always small. Furthermore, the reported position will actually about a single period behind the actual position, which makes the line you pointed out - "if (hw_ptr >= period_size) hw_ptr -= period_size; else hw_ptr = 0;" - redundant, which is why I removed it. Though to be honest I'm not sure if keeping the value behind by a period is even necessary anymore).
Why then is the allocated size always small? The answer depends on whether direct hardware access is used. If so, the whole buffer is initially allocated and committed, then more is allocated and committed as it becomes available. It becomes available in small chunks ("periods" in Alsa speak), so, the allocated area must be small.
If direct hardware access is not used, the initial buffer allocate and commit does not occur. The reason for this is, a commit operation actually copies and translates data from the translation buffer to the real hardware buffer. If a whole-buffer commit was performed initially, a whole buffers worth of data would be thus copied and this would be incorrect because the buffer is not even filled at that point. Instead, only a small chunk (2 periods worth) is initially committed, and even smaller chunks (1 period) are committed as each period passes (i.e. as the callback function is called). In this case, it is Alsa's responsibility to map the real hardware pointer into the user buffer.
Another asked: Why do you even need the hardware play position? D. McCall: In short, you need it to know how much data in the buffer the hardware has already read, and therefore, up to which point in the buffer it is safe to overwrite. Because some sounds are longer than the buffer (including continuous sound which is actually composed of multiple seperate sounds), you need to load the buffer full of data for the first part of the sound, then wait until that portion has played, and then store the next part of the sound in the buffer.
In practice the buffer is divided into several periods, let's say 10 for example. Also, we might not fill the whole buffer before we tell the hardware to start playing the sound (to reduce latency, among other reasons). So say we fill the buffer with 4 periods worth of sound data. In general the software mixer likes to stay a specific number of periods in front of the hardware (4 in this case). It doesn't want to get too far ahead (mainly because sounds are often dynamic and if you store too much into the buffer, you might need to cancel or alter it later which consumes processing capacity). Neither does it want to get little ahead, or the hardware might overtake the software (buffer underrun). So, after the first period has been played, we want to fill in the next period (number 5 in the buffer) with data, and also to clear the period that has just played. Then when the next period (#2) plays we fill in another one (#6), and so one. We only know what periods have played be checking the hardware pointer.
Alsa tries to abstract this away somewhat. The good thing about the way Alsa does it is that the interface is (at least in theory) consistent regardless of whether you are using the hardware directly or you using Alsa's plug layer (or other virtual device). The problem is that at the moment, Wine's direct sound implementation (and Alsa driver) do not support the buffer locking interface for the primary buffer (the Alsa buffer, which may or may not also be the mapped hardware buffer). The locking interface provides a mechanism for direct sound to signal to the driver which parts of the buffer it has changed. This would allow committing only as much as was actually ready. Alsa also provides a "rewind" function for cases where changes occur to the buffer between the current hardware and application pointers. wine archive
[edit] Alsa device name
A programmer [Jun 05] made a change for configuring Sound: I have default overridden to pass through dmix/dsnoop, wine cannot access my card directly through plug:hw the majority of the time. Using the PlaybackDevice config option is a good enough hack for me for now
M. Hearn: There should - at minimum - be a comment here. I "fixed" this to use default months ago, it was fixed back to plughw:0,0 and now you submitted a patch to fix it back to default again! This thing just ping-pongs back and forth like there's no tomorrow :)
R. Reif: Setting the device to default sort of worked back when the wine ALSA driver only supported a single device no matter how many devices there actually were. Now that the wine ALSA driver supports more than a single device, the proper way to deal with this is to do what windows does. That is make all the sound device available in the sound control panel and have the user decide which one to make the default or use the first one in the list if the user doesn't specify one. This would require that wine have a multimedia control panel (which could be run from winecfg) or use a native one and that winmm and dsound use the registry entries set by the control panel.
dsound currently has a hack to select which device is to be used as the default but the proper windows registry entries should be used so the wave device also works the same way.
The problem with ALSA is that it doesn't provide a consistent device enumeration facility. ALSA is moving that way but backward compatibility will always be a problem even when ALSA comes up with a usable and stable solution.Wine Archive
J. White posted to the forums [Jun 05]: a fairly sizable patch that revamps the way Alsa initialization is done. Wine Archive
With this patch, Wine now does the following: scan all cards given by Alsa (not brute force 0-5), respect alsa defaults and environment variable overrides, probe to see if a reported Alsa device is useful (e.g. strip my Modem from the list of reported sound cards), and provide a mechanism for an end user to explicitly configure Wine to use Alsa.
The default configuration values should 'just work' in most cases, but the following registry values are permitted to provide finer control:
- [Software\Wine\Wine\Config\ALSA]
- AutoScanCards Whether or not to scan all known sound cards and add them to Wine's list (default yes)
- AutoScanDevices Whether or not to scan all known PCM devices on each card (default no)
- UsePlugDevice Whether or not to use the plug:hw device, which automagically handles rate conversion (def yes)
- DeviceCount If present, specifies the number of hard coded Alsa devices to add to Wine's list; default 0
- DevicePCMn Specifies the Alsa PCM devices to open for Device n (where n goes from 1 to DeviceCount)
- DeviceCTLn Specifies the Alsa control devices to open for Device n (where n goes from 1 to DeviceCount)
- Notes:
- Using AutoScanCards no, and then Devicexxx info is a way to exactly specify the devices used by Wine.
I'd appreciate anyone passionately interested in Alsa (Kevin? Robert?) taking the time to try this patch. [A discussion ensued]
[edit] Direct Sound
A programmer noticed some apparent glitches with the directsound tests and Alsa and asked for information.
R. Rief: Only the primary buffer supports hardware acceleration. The secondary buffer(s) are implemented in software and mixed into the primary buffer. The formats (mono/stereo, 8/16 bit samples, and sample rate) of the primary and secondary buffers are totally independent and can be anything.
One of the dsound tests keeps the primary buffer format constant and iterates through all secondary buffer formats and another keeps the secondary buffer format constant and iterates through all possible primary formats. This is probably what you are seeing. The secondary buffer format has nothing to do with what is sent to the hardware. Wine Archive
[edit] Sound Drivers
A developer posted a new driver.
D. Riekenberg [ Nov 06] cautiously said: I don't know, if wineaudio.drv this is still the way to go, but we have sound crackeling and Buffer-underun Bugs, and adding another copy of the "not very well working" code might be a "no go" for Alexandre.
A. Julliard [Nov 06]: Exactly, we already have 8 sound drivers, and not a single one actually works properly, so I'm pretty reluctant to add yet another copy of the same broken code. The openal dll can certainly go in, but you'll need to clean up the code first, right now it looks like a pretty bad case of macro abuse. [...] Judging from past experience, people for whom it doesn't work right will simply go out and implement yet another driver, with yet another set of bugs
[edit] Drives and their Paths
[edit] Cacheing the canonicalized Unix Paths
A programmer suggested to: Cache the canonicalized unix paths, which correspond to dos devices.
A. Julliard: I don't think you want to do that. The goal of the new symlink scheme is to make it possible to change drive config on the fly, caching it would defeat that.
He asked for clarification: You mean like while an application is running? Wouldn't that break a lot of applications, which store filenames in memory during runtime?
A. Julliard: No, you can remap drives on Windows too. I think the whole canonicalization thing is suspect; you should never compare Unix path strings. If you have to compare paths you should use stat and compare device/inode.
The programmer: In the current implementation, for every shitemid that is constructed, all drives are queried and their paths are canonicalized, which is a lot of disk i/o and string copying. Unixfs is really painfully slow. I guess we need some caching scheme, but if you don't like the current one, I'll give it some more thought.
Dimi Paun: Can't we just invalidate the cache if we notice things have changed? Wine Archive
[edit] IOCTL_ call
A programmer asked [Sept 05] for suggestions for a good "wineish" way to implement an IOCTL_ call for an IDE disk?
My winelib app is hosting a Windows DLL that is making an IOCTL_DISK_DRIVE_GET_GEOMETRY call on an IDE hard disk. ntdll/file.c NtDeviceIoControlFile is passing this off to ntdll/cdrom.c CDROM_DeviceIoControl and, of course, since it is not a cdrom disk, that fails.
V. Margolen: Use SCSI ioctls I think they should work on IDE drives as well.
U. Bonnes: I had a patch that splitted out IOCTL code handling to separate, loadable dlls, but the patch went by unnoticed. Look for Mail from around July 10 "Uniform SYS/VXD Handling x/6" In your case, when you did CreateFile("\\c:\"), in file.c it would be noticed that a raw handle on the disk is needed and something like "disk.sys" would be loaded, where you would implement the needed IOCTL. Wine archive
[edit] Error Handling
[edit] Wine's Exception Handler and the ESP
A Programmer noted [July 05]: I've been doing some debugging of the exception handler and have come across a problem for which I'm not sure what the best solution is. It involves an application using the ESP [Extended Stack Pointer? an x86 register used for the stack pointer?] for something other than the stack.
The current DIB [device independant bitmap? which contains all of the color information necessary to display a bitmap that is independant of the machines' display capabilities] code uses protection to detect when the application modifies the DIB bits and respond accordingly. It does this by disabling read and/or write access to pages and then catching exceptions when they are thrown so that it can keep the X11 and windows versions of the DIB seporate but reflect changes appropriately (There may be other pieces of Wine which use similar tactics).
The application I am debugging, however, uses the ESP as a counter/memory offset in it's updating of the DIB. While not the best selection of registers, the application relies on ESP not being used for anything else while the DIB updates take place (In Windows this assumption is true). A made-up example of assembly code is as follows:
- mov esp, [0x12345678] ; Save the ESP
- mov 0x128796, esp ; Set up ESP for the DIB modification
- mov 0, ebp
- loop:
- mov ebp, [sp + bp] ; Write out the byte to the DIB
- inc ebp
- sub esp, 0x10000 ; The high word is a counter
- jns loop
- mov [0x12345678], esp ; Restore the ESP
Now, one of the first things our exception handler in signal_i386.c does is set up the stack layout to deliver the exception to the application (see the setup_exception function), but in this case ESP definately does not point to the stack (and the application never intended for an exception to occurr). It instead contains a counter in the high word, and a memory offset in the low word. Because of this, there is a double fault which happens and Wine actually Segfaults as opposed to breaking into the debugger.
So, what I'm wondering is if anyone who has experiance with the exception handling code has any thoughts on how this problem can be fixed. If your interested in actual application code which does this, Alpha Centauri is what I found the initial problem with. You can download the demo at http://www.firaxis.com/downloads/Demo/smac_demo1_1.exe. The assembly code in the application which causes the crash is located starting at around offset 0x0060d954. As an interesting side-effect, if there are other applications which are using ESP in a "bad" manor, then we may be corrupting memory whenever we generate an exception within Wine. This issue would be very hard to track down, which makes me think that only exceptions which would normally be generated in Windows should cause Wine to modify the application stack.
F. Nawothnig: Our current DIB implementation is an ugly hack. We need a real DIB implementation, either as a complete GDI engine in Wine or as an X11 extension. Some work has been done on a GDI engine in Wine by Transgaming a couple of years ago but it wasn't merged. Then, some weeks ago someone suggested to port the ReactOS GDI engine to Wine.
However, in my opinion implementing a full-fledged GDI engine in Wine would be rather hackish and sub-optimal for several reasons:
- It would need a lot of code and a lot of work. - The X11 engine is captable enough for most of our purposes (except this DIB thingie) so we shouldn't duplicate all that stuff which has been stable and working for decades unless it's absolutely necessary. - Sometimes using the X11 engine and sometimes our DIB engine for the same GDI functions could cause problems for some apps if they used algorithms differ slightly (probably more than a Wine/Windows discrepancy) - we could use our DIB engine for everything but this would eliminate network transparency. [...]
The programmer asked for clarification: But is it the DIB implementation that is really at fault here or is it the fact that we are adding extra exceptions and can't be sure what the esp will be when they fire, especially since they don't occurr on Windows.
F. Nawothnig: Both are - the current DIB implementation wouldn't work without those extra exceptions.
The "real" DIB, used for GDI calls, is stored on X side but the DIB surface, used for direct access, is stored on Wine side and we need to keep them in sync by catching reads / writes to the DIB surface. We need to get rid of that seperation - either the DIB should be stored fully on X side (which would require to add some features to X) or fully on Wine side (by implementing a GDI renderer in Wine). And since we already got a full-flegded rendering engine in X11 we already use (and will continue to use unless we wanna drop network transparency) [we could] add the missing features to X (which would just be XPixmaps of arbitrary depth as we should be able to use SHM for direct memory access).
J. Eriksson pointed out that: Sharing code with ReactOS is easier if it's not done in the X server.
Dimi Paun pointed out another issue with only using X: You can't have it fully on the X side, since you need direct memory access (non-synchronized I might add) to the DIB data. The only way is to implement it in Wine.
He was then asked: Direct memory access can be done using X11 SHM, no?
Dimi Paun noted: But then you lose network transparency.
F. Nawothnig wondered if that would be a concern: I'd think that apps directly accessing the surface memory are either games or do some other kind of realtime graphics so network transparency isn't worth anything there (since we'd have to transfer the whole DIB all the time anyway).
F. Gourget: I don't remember any names off-hand but I am very sure that I have encountered 'office-style' applications that alternated direct access to the DIB with 'gdi' accesses to it. So yes, preserving network transparency is very much worth it.
Anon: GDI is a very good example of the problem of throwing an exception where the application never intended one to be thrown. If ESP is bad we clobber something. GDI, however, is not the only example. [...] Another example of a SEH exception is that of the DOS memory initialization (http://www.winehq.org/hypermail/wine-cvs/2005/04/0298.html). It relies now on an access violation to detect when to initalize the DOS and BIOS memory. If ESP was used for something other than the stack on the first access to DOS memory, then we'd experiance the same problem. There may be other examples outside of DIB in the code as well that I'm not aware of. As far as I can tell, the problem is that we have extra exceptions firing when the application is not expecting them and they would not occurr on Windows.[...] If we fix it so that GDI does not throw exceptions, then we have to fix it so that we only throw exceptions when windows throws exceptions. Nothing more, nothing less - otherwise we have the issue of potentially having a bad ESP and clobbering something. The issue of never throwing an exception unless Windows would have is a larger problem and involves more than just GDI code. We can't enforce ESP usage on windows programs, so we have to come to terms with the fact that they may not use the ESP register as we would like. That is what I am trying to get at. I know that GDI is far from optimal, but there are areas of code other than GDI in which the interaction between ESP and exceptions generated within Wine could pose a problem.[...] So, the two options are to enforce that Wine never throws exceptions other than those that occurr on windows (and I suspect people in general do not like this restriction for performance reasons) or to fix the exception handler to work in the face of a bad ESP. Perhaps exceptions fired due to wine can use a different stack so that they don't rely on an assumed state of the application? [He then asked for comments]
A. Julliard: Sure, but that's a very rare case, since messing with ESP means you can't debug the code on Windows either. It would of course be possible to use a separate stack for exceptions, in fact we used to do that, but it has other problems and it's not how Windows does it. So yes, the general rule is to avoid having exceptions where Windows doesn't. Things like DOS memory could be fixed if we found an app that really breaks because of that, but until we do I wouldn't worry too much about it. Wine Archive
Further Reading
[edit] kthread.c
What is the purpose of this function in kthread.c: static inline void writejump( const char *symbol, void *dest )
A Solaris Wine volunteer asked: In kthread.c there is this code that is only defined for I386 glibc, but the solaris port uses Solaris libc so the function does nothing. What is the purpose of this function and exactly what should the semantics be ?
static inline void writejump( const char *symbol, void *dest )
{
#if defined(__GLIBC__) && defined(__i386__)
unsigned char *addr = wine_dlsym( RTLD_NEXT, symbol, NULL, 0 );
if (!addr) return;
/* write a relative jump at the function address */
mprotect((void*)((unsigned int)addr & ~(getpagesize()-1)), 5, PROT_READ|
PROT_EXEC|PROT_WRITE);
addr[0] = 0xe9;
*(int *)(addr+1) = (unsigned char *)dest - (addr + 5);
mprotect((void*)((unsigned int)addr & ~(getpagesize()-1)), 5, PROT_READ|
PROT_EXEC);
# ifdef HAVE_VALGRIND_MEMCHECK_H
VALGRIND_DISCARD_TRANSLATIONS( addr, 5 );
# endif
#endif /* __GLIBC__ && __i386__ */
}
M. Meissner: It is overwriting the __errno_location() handler in libc with a WINE threadsafe one. I am not sure whether Solaris needs it. Wine Archive Link
[ed. update. wine announcement approx may 09 notes - Get rid of the no longer supported wine-kthread. http://www.winehq.org/announce/1.1.17 ]
[edit] Cryptography
What direction should I take this [encryption implementation on Wine]?
A. Julliard: You should do this as close to Windows as possible, so that it's easier to adapt it to work correctly later on. If you do everything right except you replace the encryption step by a dummy XOR, then it's obvious how to fix it. With the registry approach [starting a new Wine only registry entry to cover this], if someone wants to fix it they first have to rip out all the code and restart from scratch; that makes it much less likely that it ever will get fixed.
K. Cook: I'd really like to get my Crypt*Protect data patches in, so I want to make sure that I do this rewrite in a way that'll bet accepted. If I understand correctly, you want me to:
- parse the Windows data format as best I can
- produce output that looks like the Windows data format
- do some kind of encryption on the data so that nothing needs to be stored to the computer between calls of CryptProtectData and CryptUnprotectData. (The existing patches intentionally avoid any encryption.)
From looking at Wine's configure.ac, it seems safe to depend on openssl being available. Is that correct?
J. Lang: Someone previously posted pretty good information about the format of CryptProtectData on MSDN. I think it should be possible to implement a close facsimile, except that the user's credentials (password) would be missing in Wine since there isn't any at the moment. If you have time to do this, it would be ideal. Failing that, doing any stateless transformation (e.g. no change at all, or xor-ing with some magic value) would be preferrable to storing this data in the registry, if I understood Alexandre's comments correctly.
We're trying to avoid proliferation of OpenSSL in Wine. Relying on CryptoAPI is a safer bet.
A. Julliard clarified: The idea of using a XOR is not to provide any security, it's just to make sure the code goes through the proper motions so that plugging in real encryption later on is easier. If you simply pass the data through you are not really exercising the functionality. Of course it would be even better to do true encryption with a hardcoded key; it still doesn't provide any security, but it's much closer to the desired end result, which makes it more likely that someone will be able to plug in the missing step.
where I can find details on what's been completed in the CryptoAPI? The http://winehq.com/site/winapi_stats page say it's at "21%".
J. Hawkins: The easiest way to determine how much of CryptoAPI is implemented is to dig into the code and see what has been implemented. You can also look at the dll spec file to see which functions are 'implemented' and which are true stubs, where 'implemented' means either truly implemented or stubbed out (FIXME("stub\n") etc). Browsing the source will also help to familiarize you with CryptoAPI.
M. Jung:a pretty good introduction on how to derive a key from a password using CryptoAPI is here http://msdn.microsoft.com/library/default.asp?url=/library/en-us/seccrypto/security/example_c_program_deriving_a_session_key_from_a_password.asp
You should hash the following:
- A placeholder for the user's login password,
- the pszDescription parameter (if present) and
- the pEntropy (if present).
If you apply the user's login name as the placeholder for 1.) you are even closer to Windows in the sense that one user can't decrypt another users DATA_BLOB's. (Well, he can of course. But only with some hacking involved.)
[edit] Solaris
[edit] get_default_drive_device
What does get_default_drive_device do?
R. Lunnon has been making progress extending Wine for Solaris and asked in the forum: I am trying to Implement Get_default_drive_device for Solaris but its unclear to me what this is supposed to do. It get passed the links in ~/.wine/dosdevices then tries to determine a mount point for them. Reading the Linux code the function only seems to return a mount point if the dosdevices link actually points at a directory something is mounted on. Is this what is supposed to happen, or is it supposed to find the device that the symlinks target directory actually resides on ?
E. Pouch: it's supposed to return the path to the device where is mounted (or could be mounted) the directory of name 'root' ( your second option)
R. Lunnon noted that: currently the code is looking for the dev AND inode of the target of the link to be the same as the mount directory of a filesystem
if (stat( entry->mnt_mountp, &st ) =3D=3D -1) continue;
if (st.st_dev !=3D dev || st.st_ino !=3D ino) continue;
E. Pouch: You don't want to manipulate as a device if the root of the disk in Win32 isn't at the mount point (in Unix world), hence the test on the inode. Wine Archive Link
[edit] LibGL and Mesa
A programmer submitted a patch and noted: I've not used a simple "test -e" because http://www.winehq.org/hypermail/wine-patches/2002/01/0206.html says this does not work on Solaris.
A. Julliard: My guess is that if test -e doesn't work, test -L won't work either...
He resubmitted: What about the attached patch? It uses "ls" instead of "test" to test for file presence (assuming ls returns non-zero code on a non-present file, which is true for a POSIX compliant system).
Snippet: > > - - if test -f /usr/X11R6/lib/libGL.a -a ! -f > /usr/X11R6/lib/libGL.so -a ! -f /usr/X11R6/lib/libGL.dylib > + if ls /usr/X11R6/lib/libGL.a >/dev/null 2>&1 -a \ > + ! ls /usr/X11R6/lib/libGL.so >/dev/null 2>&1 -a \ > + ! ls /usr/X11R6/lib/libGL.dylib >/dev/null 2>&1
C. Hall clarified: On Solaris 9 and Solaris 10 the man page for test say -e checks if the file exists, and -L checks if the file exists and is a symbolic link. -e is not avaliable in the shell sh, there is no mention if -L works or not in sh. It might be a problem for just Solaris 8, or the tests are/were ran in the sh shell.
A programmer looked at the area in question and speculated: The current "test" check definitely does not ensure the system doesn't have this "broken" setup. [...]it should be better to let autoconf do the check properly with AC_CHECK_LIB.
However another explained it's workings: Certainly does. The broken setup is as follows:
/usr/lib/libGL.so <- belongs to nvidia
/usr/lib/libGL.a <- no such thing
/usr/X11R6/lib/libGL.so <- deleted by nvidia installer
/usr/X11R6/lib/libGL.a <- still exists, belongs to Mesa
Linking will succeed whatever you do, but if you don't check for this setup, Wine will be statically linked to Mesa here, and users will complain about no hardware acceleration. The AC_MSG_ERROR just puts this in terms that users understand, even though it's not an accurate message, and probably why you didn't see the point of the check. [A new patch was posted] Wine Archive
[edit] Odds & Ends; Discussions yet to find a place
The problem wtih strncpy(dst,src,n)
from the winehq.org Janitorial Page:
"strncpy(dst,src,n) has two subtle problems. The first is that it always fills the whole dst buffer (n characters). The second is that it doesn't always nul terminate the dst buffer that it's filling. Wine code should avoid the use of strncpy for these reasons, and instead use lstrcpynA/W or memcpy."
A. Julliard then posted: "Define strncpy to an error to make sure it doesn't creep back in." Patch: http://cvs.winehq.org/patch.py?id=17236
[edit] Obsolete API
A developer wrote May 10: if Microsoft has dropped that API from Vista, all apps that use it no more will function on Vista and newer Windows generation. Therefore Wine is free to drop it as well.
R. Dunn clarified: Not really. Wine is designed to run Windows programs on Linux, Mac, BSD and OpenSolaris platforms. That means that if an application is using this API, then Wine should support it.
If this is Wine making the call internally (and no applications explicitly depend on it), then the API can be dropped from Wine as well. http://permalink.gmane.org/gmane.comp.emulators.wine.devel/69495
[edit] Debugger
A programmer asked about the debugger workings.
E. Pouech: [Sept 05] basically what happens:
let's call P the process that sends the debug event (ie the process beingdebugger) and D the debugger
- P gets an exception, and first wants to notify the debugger - P calls queue_exception_event in wineserver - WS (wineserver) then suspends P (ie signals every thread of P with SIGUSR1) - WS queues debug event - D gets the event (wait_debug_event) - D handles the event - D informs WS it's done with the event (continue_debug_event) - WS then resumes every thread of P (that's the wakeup_thread function) - P (in fact the thread that queued the event) resumes and can fetch the result of the handling of the debug event
[edit] Subclassing
F. Richter [July 05] posted theming code and asked for reviews:
R. Shearman: If you are going to subclass a control, you should use the common control subclassing functions, but it's not clear to me that that is the best option.
F. commented: Well, my initial idea was to set up a window creation hook and subclass (the user32) controls from there, using the subclassing functions. Being that somewhat complicated, Kevin suggested to start with the simpler SetClassLong() subclassing, and change the method later as needed.
R. Shearman: That sounds like a good plan, but I would still recommend using SetWindowSubclass to do the subclassing. You can see the list of benfits here: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/subclassingcontrols.asp

