Running Palm Desktop
If you can get Palm Desktop to install, chances are you'll want to see if it runs. Unfortunately, it doesn't because of a series of crashes.
WinMM Problems
The first problem you encounter with this is a crash in WinMM. This is a memory manager heap bug. As of Wine 20050725, this has been fixed. For older versions, Uwe Bonnes gave me a patch to fix it:
Index: wine/dlls/winmm/driver.c
===================================================================
RCS file: /home/wine/wine/dlls/winmm/driver.c,v
retrieving revision 1.32
diff -u -w -r1.32 driver.c
--- wine/dlls/winmm/driver.c 21 Mar 2005 10:28:39 -0000 1.32
+++ wine/dlls/winmm/driver.c 8 Jul 2005 07:47:59 -0000
@@ -75,7 +75,7 @@
{
LPWINE_DRIVER d = (LPWINE_DRIVER)hDrvr;
- if (hDrvr && HeapValidate(GetProcessHeap(), 0, d) && d->dwMagic == WINE_DI_MAGIC) {
+ if (hDrvr /* && HeapValidate(GetProcessHeap(), 0, d) */&& d->dwMagic == WINE_DI_MAGIC) {
return d;
}
return NULL;
That'll get you past this issue
. Now for some more fun...
Even more fun: A crash in MFC
After you try to run Palm Desktop, you may get this error:
err:seh:setup_exception stack overflow 496 bytes in thread 0009 eip 7bee164a esp 7b9d0e10 stack 0x7b9d0000-0x7bad0000
This is a bug in builtin msvcrt. Use native to get past it. And now it gets more interesting. Yet another crash happens. I fired up WineDbg and got this trace:
Backtrace: =>1 0x67cd7129 in palmui (+0x7129) (0x7b902dc0) 2 0x5d8924ec (0x83e58955) 3 0x00000000 (0x00000000) 0x67cd7129: movl 0x20(%esi),%eax
"palmui" refers to PalmUI.dll. I started up a disassembler and found the place where the crash is. I can't post the disassembly though. I'm told that it's OK to describe what happening in abstract terms.
The crash is due to a failing call to an MFC function, ord_1175 (which is actually AfxGetThread.) This function returns 0. The calling code checks for this, and then it's dumb enough to zero out the register containing the pointer. It then goes on its merry way trying to dereference it. (Wonderful error checking...
)
So What's with AfxGetThread?
Fortunately, MS provides the complete MFC source code with Visual C++, so that makes life a little easier here. Basically, MFC uses thread local storage (TLS) to store information about processes and threads managed by its library.
First, AfxGetThread tries to get the CWinThread pointer from AfxGetModuleThreadState. If that doesn't give anything useful, it tries to use AfxGetApp. Previously, I had thought that in PalmUI.dll's case, the call to AfxGetModuleThreadState didn't work, so it tried to use AfxGetApp, and that didn't work either, so the call fails.
I tested for the same behavior on Windows XP. I found that on Windows, the call to AfxGetModuleThreadState gives the thread pointer. But on WINE, both AfxGetModuleState and AfxGetApp return NULL values. Debugging shows that if MFC cannot find a thread value it tries to create the object that stores this information. Originally, I speculated that the problem was due to a failing allocation on the heap somewhere. While Wine does have some known heap issues, the allocations seem to be working fine. The data that this particular call is concerned with are abstracted in two internal MFC classes: _AFX_THREAD_STATE and AFX_MODULE_THREAD_STATE. I set breakpoints in the functions that create these classes, and I found that their creation happens well before AfxGetThread is called. In fact, AfxGetThread isn't concerned with these classes themselves, but member data they contain, specifically thread pointers. What's troubling here is that the constructors for these classes don't initialize this data, so it has to be set somewhere down the line. In all cases, the instances of these classes were themselves allocated properly on the heap, but their data is faulty.
