|  | WineLib HOWTO | 
|  | Version 30-Jul-2000 | 
|  |  | 
|  | AUTHOR: | 
|  | Wilbur Dale | 
|  | Lumin Software BV | 
|  | Zandheuvel 52 B | 
|  | 4901 HW Oosterhout (NB) | 
|  | The Netherlands | 
|  |  | 
|  | wilbur.dale@lumin.nl | 
|  |  | 
|  | WARNING: This HOWTO is incomplete. I expect to add to it on a weekly | 
|  | basis until it is complete. | 
|  |  | 
|  | ===================================================================== | 
|  |  | 
|  | Table of Contents | 
|  |  | 
|  | I. Introduction: Wine vs. WineLib | 
|  |  | 
|  | II. Legal Issues | 
|  |  | 
|  | III. How Much Work? | 
|  |  | 
|  | IV. File Format Conversion | 
|  |  | 
|  | V. Compiling A Simple Win32 Program | 
|  |  | 
|  | VI. Compiling A Win32 Program With Resources | 
|  |  | 
|  | VII. DLLs | 
|  | A. Windows executable and Windows DLL. | 
|  | B. Windows executable and WineLib DLL. | 
|  | C. WineLib executable and Windows DLL. | 
|  | D. WineLib executable and WineLib DLL. | 
|  |  | 
|  | VIII. How to use MFC | 
|  | A. Using a native MFC DLL | 
|  | B. Compiling MFC | 
|  |  | 
|  | VIII. Trademarks | 
|  | Windows 3.x, Windows 95, Windows 98, Windows NT are trademarks of | 
|  | Microsoft Corporation. | 
|  |  | 
|  | Unix is a trademark of ???? FIXME: who has the trademark this week? | 
|  |  | 
|  | CrypKey is a trademark of Kenonic Controls Ltd. | 
|  |  | 
|  | FIXME: Codewright copyright ??? | 
|  |  | 
|  | All other trademarks are the property of their respective owners. | 
|  |  | 
|  | ===================================================================== | 
|  |  | 
|  | I. Introduction: Wine vs. WineLib | 
|  |  | 
|  | WineLib provides the Win32 API to a non-Microsoft operating | 
|  | system. The WineLib Win32 functions use X11 functions to perform the | 
|  | actual drawing on the screen. Wine and WineLib are based on the same | 
|  | set of functions that implement the Win32 API. The difference between | 
|  | Wine and WineLib is the type of executable that is loaded into memory | 
|  | and executed. If an executable and any associated DLLs were compiled | 
|  | for x86 hardware running the Windows 95, 98, or Windows NT (TM) | 
|  | operating systems, then Wine can use a special binary loader to load | 
|  | the program and the libraries into memory and execute it. WineLib on | 
|  | the other hand allows you to take the source for such a program and | 
|  | DLLs and compile it into the native format of a x86 Unix or Linux | 
|  | operating system. WineLib also allows you to partially compile the | 
|  | program and DLLs into the native format. For example, if you use a DLL | 
|  | from a vendor to provide some functions to your program and the vendor | 
|  | does not give you source, then you can use the Windows version of the | 
|  | DLL to provide the functions and compile the rest of your program in | 
|  | the native form for your system. [1] | 
|  |  | 
|  | Windows compilers and linkers generate executables with a different | 
|  | structure than standard compilers. Windows has two executable formats: | 
|  | the NE format and the PE format. The NE executable format provides for | 
|  | two entry points and the PE format provides for three entry points | 
|  | while a standard executable has a single entry point. Usually, a NE or | 
|  | a PE executable will use one of the entry points for your program and | 
|  | the other entry points will print an error message and exit. However, | 
|  | a linker can link 16 bit objects into one or both of the alternate | 
|  | entry points of a NE or PE executable. | 
|  |  | 
|  | Standard compilers assume that the function main() exists. The entry | 
|  | point for a standard program is constructed from the C runtime | 
|  | library, initialization code for static variables in your program, the | 
|  | initialization code for your classes (C++), and your function main(). | 
|  | On the other hand, windows compilers assume WinMain() exists. The | 
|  | entry point for a windows program is constructed from the C runtime | 
|  | library, initialization code for static variables in your program, the | 
|  | initialization code for your classes (C++), and your function | 
|  | WinMain(). [4] | 
|  |  | 
|  | Since main() and WinMain() have different type signatures (parameter | 
|  | types), WineLib provides certain aids to generate code so that your | 
|  | program can be compiled and run as written for windows. For example, | 
|  | WineLib generates a main() to initialize the windows API, to load any | 
|  | necessary DLLs and then call your WinMain(). Therefore, you need to | 
|  | learn four basic operations to compile a windows program using | 
|  | WineLib: compiling a simple program, compiling resources, compiling | 
|  | libraries, and compiling MFC (if you will be using MFC). Each of these | 
|  | skills or operations are explained in later sections of this HOWTO. | 
|  |  | 
|  | Before you start porting your windows code to WineLib, you need to | 
|  | consider whether you are allowed to port your program to WineLib. As | 
|  | you compile your program using WineLib, you will be combining software | 
|  | from several sources and you need to ensure that the licenses for the | 
|  | components are compatible. Hence, in the next section, we will examine | 
|  | several legal issues. | 
|  |  | 
|  | II. Legal Issues | 
|  |  | 
|  | Disclaimer! I am not a lawyer. The purpose of this section is to make | 
|  | you aware of potential legal problems. Be sure to read your licenses | 
|  | and to consult your attorney. | 
|  |  | 
|  | During the compilation of your program, you will be combining code | 
|  | from several sources: your code, WineLib code, code from your vendor's | 
|  | DLLs (if any), and Microsoft MFC code (if used). As a result, you must | 
|  | ensure that the licenses of all code sources are obeyed. What you are | 
|  | allowed and not allowed to do can vary depending on how you compile | 
|  | your program and if you will be distributing it. For example, if you | 
|  | are releasing your code under the GPL, you cannot link your code to | 
|  | MFC code because the GPL requires that you provide ALL sources to your | 
|  | users. The MFC license forbids you from distributing the MFC source so | 
|  | you can not comply with the GPL license except by not distributing you | 
|  | program. On the other hand, if your code is released under the LGPL, | 
|  | you cannot statically link your program to MFC and distribute it, but | 
|  | you can dynamically link your LGPL code and MFC code and distribute | 
|  | it. | 
|  |  | 
|  | Wine/WineLib is distributed under an X11-like license. It places few | 
|  | restrictions on the use and distribution of Wine/WineLib code. I doubt | 
|  | the Wine license will cause you any problems. On the other hand, MFC | 
|  | is distributed under a very restrictive license and the restrictions | 
|  | vary from version to version and between service packs. | 
|  |  | 
|  | If you plan on using MFC, there are three hurdles to legally using | 
|  | MFC. The first hurdle is how to legally get MFC source code on your | 
|  | computer. MFC source code comes as a part of Visual Studio. The | 
|  | license for Visual Studio implies it is a single product that can not | 
|  | be broken up into its components. The cleanest way to get MFC on you | 
|  | system is to use a dual boot Linux box with the windows partition | 
|  | visible to the Linux OS. Boot into windows and install Visual | 
|  | Studio. Since Visual Studio is installed on the computer, you have not | 
|  | broken it into its components. There may be other solutions, but I | 
|  | think this is the easiest. | 
|  |  | 
|  | FIXME: quote relevant sections of EULA in above paragraph. | 
|  |  | 
|  | The second hurdle for MFC is the legality of compiling MFC on a | 
|  | non-Microsoft operating system. This varies with the version of MFC. | 
|  |  | 
|  | MFC license from Visual Studio 6.0: | 
|  |  | 
|  | 1.1 General License Grant. Microsoft grants to you as an | 
|  | individual, a personal, nonexclusive license to make and use | 
|  | copies of the SOFTWARE PRODUCT for the sole purposes of designing, | 
|  | developing, and testing your software product(s) that are designed | 
|  | to operate in conjunction with any Microsoft operating system | 
|  | product. [Other unrelated stuff deleted.] | 
|  |  | 
|  | So it appears you cannot compile MFC for WineLib using this | 
|  | license. On the other hand, Visual Studio 6.0 service pack 3 (Visual | 
|  | Studio 5.0 is similar): | 
|  |  | 
|  | 1.1 General License Grant. Microsoft grants to you as an | 
|  | individual, a personal, nonexclusive license to make and use | 
|  | copies of the SOFTWARE PRODUCT for the purpose of designing, | 
|  | developing, and testing your software product(s). [Other unrelated | 
|  | stuff deleted] | 
|  |  | 
|  | So it appears you can compile MFC for WineLib using this license. | 
|  |  | 
|  | The third hurdle is your legal right to distribute an MFC | 
|  | library. Check the relevant section of the license on redistributables | 
|  | and your redistribution rights. As I read the license, you only have | 
|  | the right to distribute binaries of the MFC library if it has no debug | 
|  | information and if you distribute it with an application that provides | 
|  | significant added functionality to the MFC library. | 
|  |  | 
|  | FIXME: quote relevant sections of EULA in above paragraph. | 
|  |  | 
|  | Once you have examined the licenses for all of the sources used in | 
|  | compiling your program and have decided you can legally compile you | 
|  | program using WineLib, you should probably experiment with your | 
|  | program running under Wine to determine how much work will be involved | 
|  | in the port. The next section will give advice on estimating the | 
|  | amount of work required for porting your program to WineLib. | 
|  |  | 
|  | III. How Much Work? | 
|  |  | 
|  | Wine and WineLib use the same functions to implement the windows API; | 
|  | hence, if your program correctly runs under Wine, it should run under | 
|  | WineLib. However, Wine/WineLib is incomplete; you may have trouble | 
|  | running your program under Wine. Many people have successfully run many | 
|  | programs under Wine, so there is a good chance you will have no | 
|  | trouble. | 
|  |  | 
|  | Wine executes the binary program that was compiled for a windows | 
|  | operating system. There are differences between the windows operating | 
|  | system and Unix/Linux operating systems. For example, in Windows 95 | 
|  | and Windows 98, the program has direct access to the hardware. A copy | 
|  | protection program that you purchased for your windows executable may | 
|  | use direct hardware access to write data to the disk. Hence, you may | 
|  | need to disable the copy protection in order to test your executable | 
|  | under Wine. | 
|  |  | 
|  | As a specific example, CrypKey is a copy protection program we use at | 
|  | Lumin Software. Our program does not execute under Wine with the copy | 
|  | protection enabled. We disabled the copy protection, recompiled the | 
|  | windows executable, and our program works fine. CrypKey also works for | 
|  | Windows NT where it creates a service. Using Wine with the --winver | 
|  | nt40 option "almost" gets the our program working with copy | 
|  | protection. At a later date, we intend to either implement the system | 
|  | calls in Wine that are missing for CrypKey or to use another copy | 
|  | protection program that does work under Linux. | 
|  |  | 
|  | During the execution of your program, Wine prints error messages to | 
|  | standard error. These error messages include "stubs", which are | 
|  | windows API functions that have not been completely | 
|  | implemented. Depending on the the system call, these could be harmless | 
|  | or crash your program. Most of the common windows API functions have | 
|  | already been implemented, so you should have no missing API functions | 
|  | or only a few missing functions. If you intend to continue with the | 
|  | port to WineLib, you will need to implement these API | 
|  | functions. After running your program for a while, you should have a | 
|  | good feel for the number of windows API functions that you need to | 
|  | implement. | 
|  |  | 
|  | FIXME: give info on Wine command line options to control error | 
|  | messages. | 
|  |  | 
|  | During the compilation of Wine, you can control the amount of error | 
|  | messages and debug information that will be be generated by Wine and | 
|  | WineLib. For the version released to your customers, you may want to | 
|  | use the following command line to configure the Wine/WineLib | 
|  | libraries. | 
|  |  | 
|  | ./configure --disable-debug --disable-trace | 
|  |  | 
|  | The option --disable-debug compiles out all debugging messages and the | 
|  | option --disable-trace compile out TRACE messages. [2] | 
|  |  | 
|  | It is not necessary for you to implement the entire documented | 
|  | behavior of an API function in order to get your program to work. For | 
|  | example, many API functions have pointer parameters that are NULL in | 
|  | the common cases. If you always call the function with a NULL pointer | 
|  | for the default behavior, you can save yourself some effort by | 
|  | implementing a function that only works for the NULL pointer | 
|  | parameter. If you do this, make sure you test if the parameter is | 
|  | non-null and issue a warning for the non-null case. Also document in | 
|  | the source that the API function is incomplete. | 
|  |  | 
|  | FIXME: give info on the FIXME (macro/function?) for partially | 
|  | implemented API functions. | 
|  |  | 
|  | Once you have implemented an API function, submit the change back to | 
|  | the Wine project so the next person to need the same function does not | 
|  | need to repeat your work. Remember, someone else wrote all of the | 
|  | other API functions that you are using, so you are benefiting from | 
|  | their work. Let other people benefit from your work as well. If you | 
|  | work for a company, you may need your company's permission to "give | 
|  | away" your work. | 
|  |  | 
|  | IV. File Format Conversion | 
|  |  | 
|  | Before you can compile your program, you must deal with one major | 
|  | difference between Windows and WineLib. Window sources are in DOS | 
|  | format with carriage return / line feed at the end of each line of | 
|  | text while WineLib files are in Unix format with only line feed at the | 
|  | end of each line of text. | 
|  |  | 
|  | The main problem with the difference between Unix and DOS format | 
|  | source files occurs with macro line continuation. A Unix compiler | 
|  | expects a backslash (\) followed by a newline (^J) to indict that a | 
|  | macro is continued on the next line. However, a file in DOS format will | 
|  | have the characters backslash (\), carriage return (^M), and newline | 
|  | (^J). The Unix compiler will interpret the backslash (\), carriage | 
|  | return (^M), newline (^) of a file in DOS format as a quoted carriage | 
|  | return and newline. The Unix compiler will think the line has ended | 
|  | and the macro is completely defined. Hence, before you compile your | 
|  | sources, you will need to convert you DOS format sources to Unix | 
|  | format. There are several tools such as dos2unix and tr that are | 
|  | available to convert the format. | 
|  |  | 
|  | FIXME: get more info on dos2unix, tr, and all other such tools and | 
|  | give example commands. Until I do [3] is a good source. | 
|  |  | 
|  | FIXME: is CR/LF conversion necessary for gcc 2.95 ? | 
|  |  | 
|  | V. Compiling A Simple Win32 Program | 
|  |  | 
|  | Wine and WineLib are written in C as is the MS Win32 API; thus, if | 
|  | have a program that calls only the Win32 API directly, you can compile | 
|  | the program using a C compiler and link it with some of the WineLib | 
|  | libraries. There are several simple examples of WineLib programs in | 
|  | the directory libtest/ in the Wine source tree. We shall examine one | 
|  | of these to show you how to compile a WineLib program. | 
|  |  | 
|  | The example we shall examine is hello2. If you examine hello2.c, you | 
|  | will see it is a windows program that pops up a message box that says | 
|  | "Hello, hello!". It can be compiled and run using a windows compiler | 
|  | just like any other windows program. However, it can not be compiled | 
|  | and run with a non-windows compiler. As mentioned previously, windows | 
|  | programs have an entry point called WinMain(), while non-windows | 
|  | compilers use an entry point of main(). Hence, we need some "glue" to | 
|  | glue the main() entry point to the WinMain() in the windows program. | 
|  |  | 
|  | In WineLib, the glue is provided by the spec file. Spec files are used | 
|  | in several places in Wine and WineLib to provide glue between windows | 
|  | code and code for non-windows compilers. WineLib provides a tool | 
|  | called winebuild in the tools/winebuild directory that converts a spec file | 
|  | into a C file that can be compiled and linked with the windows source | 
|  | files. If you examine hello2.spec, you will see the following: | 
|  |  | 
|  | name	hello2 | 
|  | mode	guiexe | 
|  | type	win32 | 
|  | init	WinMain | 
|  |  | 
|  | Information on the complete format of the spec file can be found in | 
|  | <wine>/tools/winebuild/README. Name is the name of the | 
|  | application. Mode is the type of "glue" that winebuild needs to | 
|  | create. Possible modes are 'dll' for a library, 'cuiexe' for a console | 
|  | application, and 'guiexe' for a regular graphical application. Type is | 
|  | the type of API, either win32 or win16. Win16 is supported only in | 
|  | Wine, not WineLib, so you should use win32. Init is the function to | 
|  | call for initialization: in this case, WinMain. | 
|  |  | 
|  | During compilation of the hello2 executable, the following command is | 
|  | executed. | 
|  |  | 
|  | ../tools/winebuild/winebuild -fPIC -o hello2.spec.c -spec hello2.spec | 
|  |  | 
|  | The program winebuild will generate the output file hello2.spec.c (option | 
|  | -o hello2.spec.c) from the spec file hello2.spec (option -spec | 
|  | hello2.spec). The option -pic specifies that winebuild should generate | 
|  | position independent code and is only necessary for building shared | 
|  | library files (.so files). It is not needed when building the main | 
|  | executable spec file, but since there is no assembly code generated | 
|  | for the main executable, it doesn't make any difference anyway. [5] | 
|  |  | 
|  | The winebuild program is used in several places in Wine as well as | 
|  | WineLib; however, only the -spec option will be used in WineLib. The | 
|  | output file hello2.spec.c contains main() and the glue code to | 
|  | initialize WineLib and call WinMain(). | 
|  |  | 
|  | Now the compilation of hello2 can proceed as any other compilation for | 
|  | a program. | 
|  |  | 
|  | gcc -c -I. -I. -I../include -I../include -g -O2 -Wall  -D_REENTRANT \ | 
|  | -I/usr/X11R6/include -o hello2.o hello2.c | 
|  |  | 
|  | FIXME: -D_REENTRANT why? | 
|  | FIXME: explain compiler options | 
|  |  | 
|  | to compile the window program itself and | 
|  |  | 
|  | gcc -c -I. -I. -I../include -I../include -g -O2 -Wall -D_REENTRANT \ | 
|  | -I/usr/X11R6/include -o hello2.spec.o hello2.spec.c | 
|  |  | 
|  | to compile the main() and the glue code. Finally, | 
|  |  | 
|  | gcc -o hello2 hello2.o hello2.spec.o -L../dlls  -L.. -lwine -lncurses | 
|  | -lm  -lutil -ldl | 
|  |  | 
|  | FIXME: explain linker options | 
|  |  | 
|  | will link the files into an executable. All of the steps are automated | 
|  | with the makefile, so "make hello2" will execute all of the steps for | 
|  | you. | 
|  |  | 
|  | Thus, you now have the basics of compiling a simple windows | 
|  | program. There are two more things to learn for compiling more complex | 
|  | windows programs: windows resources and DLL dependencies. Window | 
|  | resources are described in the next section. DLL dependencies are | 
|  | handled by linker magic with windows compilers. Thus, in WineLib, you | 
|  | will need to provide information about which DLLs your program | 
|  | depends. This information is given in the spec file. For example, if | 
|  | our hello2 program had a .wav file that it played, it would need the | 
|  | multi-media DLL winmm. Our spec file would then be | 
|  |  | 
|  | name	hello2 | 
|  | mode	guiexe | 
|  | type	win32 | 
|  | init	WinMain | 
|  | import  winmm | 
|  |  | 
|  | If you need to list multiple DLLs, then the import specification can | 
|  | appear multiple times. | 
|  |  | 
|  | FIXME: can multiple libraries appear on one import line? | 
|  |  | 
|  | VI. Compiling A Win32 Program With Resources | 
|  |  | 
|  | FIXME: to be continued. | 
|  | Describe wrc. | 
|  | Go through hello world example 3. | 
|  |  | 
|  | VII. DLLs | 
|  |  | 
|  | As mentioned in the introduction, Wine allows you to execute windows | 
|  | executables and windows libraries under non-Microsoft operating | 
|  | systems. WineLib allows you to take sources intended for the windows | 
|  | operating system and to compile them to run as native executables | 
|  | under a Unix/Linux operating system. With an executable and a single | 
|  | library, there are four combinations in which to run the programs and | 
|  | the library: | 
|  | 1. a Windows executable with a Windows DLL, | 
|  | 2. a Windows executable with WineLib DLL, | 
|  | 3. a WineLib executable with Windows DLL, and | 
|  | 4. a WineLib executable with WineLib DLL. | 
|  | In this section, we will discuss each of these and discuss the steps | 
|  | required to implement the executable/DLL combination. | 
|  |  | 
|  | A. Windows executable and Windows DLL | 
|  |  | 
|  | Running a windows executable with a windows DLL is not a WineLib | 
|  | program: it is a Wine program. If you type | 
|  | wine program.exe | 
|  | and the DLL is in the search path, then the windows program should run | 
|  | using the windows DLL. | 
|  |  | 
|  | FIXME: find out what is the search path. | 
|  |  | 
|  | B. Windows executable and WineLib DLL | 
|  |  | 
|  | Running a windows executable with a WineLib DLL is also accomplished | 
|  | using the Wine program. The source code for the DLL is compiled into a | 
|  | Unix style shared library. When the windows executable "loads" the | 
|  | DLL, Wine will use the shared library (.so file) instead. | 
|  |  | 
|  | At first you may wonder why you would want to run a windows executable | 
|  | with a WineLib DLL. Such a situation implies you do not have the | 
|  | source for the executable, but you do have the source for the | 
|  | DLL. This is backwards from what you might expect. However, I do have | 
|  | an example where this situation might arise. | 
|  |  | 
|  | Codewright is a popular editor in the windows world, and the | 
|  | capabilities of Codewright can be extended by using DLLs. Since | 
|  | Codewright is a commercial product, you do not have the source and | 
|  | must use the windows executable with Wine. If you have written a DLL | 
|  | to add functionality to Codewright, you have two choices: you can | 
|  | compile the DLL using a windows compiler and use both a windows | 
|  | executable and a windows DLL as in case A above, or you can use | 
|  | WineLib and compile the DLL as a shared library (.so file). I have no | 
|  | idea if Codewright actually runs under Wine, but this is an example of | 
|  | why you might decide to use a windows executable and a WineLib | 
|  | DLL. Many other editors and other programs use DLLs to extend their | 
|  | functionality. | 
|  |  | 
|  | In order for Wine to use the WineLib DLL, certain glue code is need to | 
|  | replace the linker magic that windows compilers use. As with a simple | 
|  | executable, the winebuild program uses a spec file to generate the glue | 
|  | code. For example, in the spec file for the DLL will look something like | 
|  | name	winedll | 
|  | type	win32 | 
|  | init	winedll_DllMain | 
|  | 1 cdecl _WINEbirthDay@4 ( str ) WINEbirthDay | 
|  | 2 cdecl _WINEfullName@4 ( str ) WINEfullName | 
|  | The name is the name of the DLL. Since WineLib only supports win32, | 
|  | the type should always be win32. The init function is the name of the | 
|  | initialization function for the DLL. The initialization function for a | 
|  | windows DLL is named DllMain(). You will need to rename the function | 
|  | in the DLL source so there will not be any name clashes with the | 
|  | DllMain() of other DLLs in you program. | 
|  |  | 
|  | The last two lines of the spec file above, provide the export | 
|  | information for the DLL. For example, the line | 
|  | 1 cdecl _WINEbirthDay@4 ( str ) WINEbirthDay | 
|  | says that the function at ordinal 1 uses the cdecl calling convention | 
|  | for the parameters. The DLL export name is _WINEbirthDay@4. The | 
|  | function takes a single parameter that is a string. Finally, the C | 
|  | function name to be called whenever this DLL function is called is | 
|  | WINEbirthday. You will need a function ordinal line for each function | 
|  | in the DLL. The export name and the ordinal can be obtained from the | 
|  | windows program dumpbin and the windows version of the DLL. See the | 
|  | file <wine>/tools/winebuild/README for more details on the spec file | 
|  | format. | 
|  |  | 
|  | During the the compile process, a command like | 
|  | winebuild -fPIC -o winedll.spec.c -spec winedll.spec | 
|  | will be executed to create the file winedll.spec.c from information in | 
|  | the file winedll.spec. The file winedll.spec.c and winedll.c are | 
|  | compiled into object files and used to create the shared library. | 
|  |  | 
|  | In order for the program to run, a copy of the shared library must be in | 
|  | your EXTRA_LD_LIBRARY_PATH. For example, if your wine.conf file has | 
|  | the following line, | 
|  | EXTRA_LD_LIBRARY_PATH=${HOME}/wine/lib | 
|  | then you must copy the shared library into the directory ~/wine/lib/ | 
|  | and the shared library will now be in the correct search path. | 
|  |  | 
|  | Now when you type | 
|  | wine program.exe | 
|  | the program will load the shared library (.so). | 
|  |  | 
|  | C. WineLib executable and Windows DLL | 
|  |  | 
|  | Running a WineLib executable with a Windows DLL is accomplished | 
|  | using WineLib. This situation will be common since you may have | 
|  | purchased DLLs to use with you project and the DLL vendor may not give | 
|  | you the source code for the DLL. | 
|  |  | 
|  | In order for WineLib to use the Windows DLL, certain glue code is | 
|  | needed to replace the linker magic that windows compilers use. Part of | 
|  | the glue code must be written by you. The basic idea of the glue code | 
|  | is that you write a new DLL that consists of function pointers. Each | 
|  | function in the DLL will consist of a call on a function pointer. For | 
|  | example, | 
|  | WINEDLL_ConstString WINEDLL_INTERFACE | 
|  | WINEfullName( WINEDLL_ConstString handle ) { | 
|  | return (* pWINEfullName) ( handle ); | 
|  | } | 
|  | The initialization function for the DLL will use the function | 
|  | LoadLibrary() to load the windows DLL and initialize the function | 
|  | pointers using the function GetProcAddress(). | 
|  |  | 
|  | Since Wine can use either windows DLLs or Unix shared libraries (.so), | 
|  | the LoadLibrary() function call may have unexpected results if there | 
|  | is a winedll.dll and a winedll.so file. Hence, the windows version of | 
|  | the DLL should be named something like hiddenWinedll.dll and the | 
|  | shared library should be named winedll.so. Now the shared library will | 
|  | use LoadLibrary() to load the "hidden" DLL. | 
|  |  | 
|  | The shared library will need a spec file. Fortunately, it is simpler | 
|  | than case B above. The spec file will look something like | 
|  | name	winedll | 
|  | type	win32 | 
|  | init	winedll_DllMain | 
|  | The name is the name of the DLL. Since WineLib only supports win32, | 
|  | the type should always be win32. The init function is the name of the | 
|  | initialization function for the shared library. This is the function | 
|  | that will load the "hidden" DLL and initialize the function | 
|  | pointers. There is no need for any function ordinals unless your | 
|  | program calls functions by the ordinal. | 
|  |  | 
|  | During the the compile process, a command like | 
|  | winebuild -fPIC -o winedll.spec.c -spec winedll.spec | 
|  | will be executed to create the file winedll.spec.c from information in | 
|  | the file winedll.spec. The file winedll.spec.c and winedll.c are | 
|  | compiled into object files and used to create the shared library. | 
|  |  | 
|  | Now that the shared library is compiled, you still need to compile | 
|  | your program. Part of the compile process for your program will | 
|  | consist of a spec file for you program. For example, | 
|  | name	program | 
|  | mode	guiexe | 
|  | type	win32 | 
|  | init	WinMain | 
|  | import winedll.dll | 
|  | This spec file is similar to the spec file of the simple WineLib | 
|  | example in part V above. The only difference is the import | 
|  | specification that tells WineLib that the main program uses | 
|  | winedll.dll. If this import line is not included, the "hidden" DLL | 
|  | will not be loaded and the function pointers will not be initialized. | 
|  |  | 
|  | During the the compile process, a command like | 
|  | winebuild -fPIC -o program.spec.c -spec program.spec | 
|  | will be executed to create the file program.spec.c from information in | 
|  | the file program.spec. The file program.spec.c and your source code are | 
|  | compiled into object files and used to create the executable. | 
|  |  | 
|  | D. WineLib executable and WineLib DLL. | 
|  |  | 
|  | Running a WineLib executable with a WineLib DLL is accomplished using | 
|  | WineLib. The source for the DLL will be combined with a spec file to | 
|  | generate the shared library. Likewise, the source for your program and | 
|  | a spec file will be combined to create the executable. In the source | 
|  | for the DLL, you should change the name of DllMain() to a name like | 
|  | winedll_DllMain() so that there will not be a name clash with other | 
|  | initialization functions for other DLLs. | 
|  |  | 
|  | The shared library's spec file is like case C above. The spec file | 
|  | will look something like | 
|  | name	winedll | 
|  | type	win32 | 
|  | init	winedll_DllMain | 
|  | The init function is the name of the initialization function for the | 
|  | shared library (what you renamed DllMain to). There is no need for any | 
|  | function ordinals unless your program calls functions by the ordinal. | 
|  |  | 
|  | During the the compile process, a command like | 
|  | winebuild -fPIC -o winedll.spec.c -spec winedll.spec | 
|  | will be executed to create the file winedll.spec.c from information in | 
|  | the file winedll.spec. The file winedll.spec.c and the source code for | 
|  | your DLL are compiled into object files and used to create the shared | 
|  | library. | 
|  |  | 
|  | Compiling your program is exactly like case C above. For example, the | 
|  | spec file for you program will look something like | 
|  | name	program | 
|  | mode	guiexe | 
|  | type	win32 | 
|  | init	WinMain | 
|  | import winedll.dll | 
|  |  | 
|  | During the the compile process, a command like | 
|  | winebuild -fPIC -o program.spec.c -spec program.spec | 
|  | will be executed to create the file program.spec.c from information in | 
|  | the file program.spec. The file program.spec.c and your source code are | 
|  | compiled into object files and used to create the executable. | 
|  |  | 
|  | VIII. How to use MFC | 
|  | A. Using a native MFC DLL | 
|  | B. Compiling MFC | 
|  |  | 
|  | FIXME: to be continued. | 
|  |  | 
|  | ===================================================================== | 
|  | References | 
|  |  | 
|  | Until this HOWTO is complete, I will document who gives me what | 
|  | information. | 
|  |  | 
|  | Reference [1] | 
|  | From: Patrik Stridvall <ps@leissner.se> | 
|  | To: "'wilbur.dale@lumin.nl'" <wilbur.dale@lumin.nl>, | 
|  | Date:   Mon, 5 Jun 2000 14:25:22 +0200 | 
|  |  | 
|  | First of all WineLib suppport for Win16 has been discontinued | 
|  | for quite some time, because: | 
|  |  | 
|  | 1. It is difficult for us to support and it is impossible | 
|  | to do so prefectly without special compiler support, | 
|  | because of memory layout issues. For example Win16 int | 
|  | is 16-bit and data is aligned 16-bit. | 
|  | 2. It is in almost all cases easier to port a | 
|  | Win16 application to Win32. | 
|  |  | 
|  | A minor detail, I personally would prefer that Wine and WineLib | 
|  | was always used in the uppercase W and uppercase L variant, | 
|  | instead of, as in your document, sometime one variant, sometimes | 
|  | another. | 
|  |  | 
|  | Reference [2] | 
|  |  | 
|  | The exact options for controlling error messages mentioned in the | 
|  | reference are apparently incorrect, but may have been correct for some | 
|  | earlier version of Wine. | 
|  |  | 
|  | From: michael cardenas <mbc@deneba.com> | 
|  | To: wilbur.dale@lumin.nl | 
|  | Date:   Mon, 5 Jun 2000 13:19:34 -0400 | 
|  |  | 
|  | a few things you should mention... | 
|  |  | 
|  | - you can compile resources as a dll under windows and then load the dll | 
|  | with wine. That's what we do for canvas. This is probably not ideal, but | 
|  | most of my problems porting were in the code. We very seldomly have to | 
|  | change the resources for the porting process. But wrc does work for most | 
|  | cases... | 
|  |  | 
|  | - the error messages can be turned off or turned up with options to | 
|  | configure like --enable-trace-msgs=wireoff or --enable-trace-msgs=wireon . | 
|  | Take a look at configure. | 
|  |  | 
|  | - you probably want to compile your WineLib with --disable-debugger, at | 
|  | least for the release version of your app. | 
|  |  | 
|  | Reference [3] | 
|  | http://fgouget.free.fr/wine/winelib-en.shtml | 
|  |  | 
|  | Reference [4] | 
|  | Date: Wed, 21 Jun 2000 10:34:10 +0200 | 
|  | From: Rob Carriere <rob.carriere@lumin.nl> | 
|  | To: Wilbur N Dale <wilbur.dale@lumin.nl> | 
|  | Subject: WineLib-HOWTO comments | 
|  |  | 
|  | Hello Wilbur, | 
|  |  | 
|  | Some picking of nits.  It reads right well. | 
|  |  | 
|  | Some of Windows xyz are registered trade marks, other are vanilla: | 
|  | Microsoft: Registered | 
|  | Windows NT: Registered | 
|  | Windows (95,98): plain | 
|  |  | 
|  | A Windows compiler does NOT generate a fake main.  Instead, the | 
|  | executable file format provides for 2 (NE) or 3 (PE) entry points. | 
|  | One of these is your program, the other(s) are normally filled with | 
|  | stubs that print an error message and exit.  It is possible to instruct | 
|  | the _linker_ to link 16-bit objects into one or both of the alternate | 
|  | entry points, and create a fat binary. | 
|  |  | 
|  | At the C/C++ level, your statement about WinMain() is correct.  Of | 
|  | course the actual entry point first inits run time lib etc, and then | 
|  | calls the C/C++ level entry, but that is also true for main() in the | 
|  | standard setup.  It may be important to regurgitate this info here, | 
|  | though, because some of the fun things that can happen with multiple | 
|  | run time libs and DLLs occur at this level. | 
|  |  | 
|  | Line 86: I only need to know how compile MFC if I use it... :-) | 
|  |  | 
|  |  | 
|  | Best regards, | 
|  | Rob                          mailto:rob.carriere@lumin.nl | 
|  |  | 
|  | Reference [5] | 
|  | To: wilbur.dale@lumin.nl | 
|  | Subject: Re: tool/build questions | 
|  | From: Alexandre Julliard <julliard@winehq.com> | 
|  | Date:   13 Jun 2000 20:06:23 -0700 | 
|  |  | 
|  | "Wilbur N. Dale" <wilbur.dale@lumin.nl> writes: | 
|  |  | 
|  | > 2. tools/build for WineLib users -- is there ever a need to not specify -pic? | 
|  |  | 
|  | -pic is only necessary for building .so files, so it's not needed when | 
|  | building the main executable spec file (but since there is no assembly | 
|  | code generated for the main exe it doesn't make any difference anyway). | 
|  |  | 
|  | -- | 
|  | Alexandre Julliard | 
|  | julliard@winehq.com | 
|  |  | 
|  | Reference [6] | 
|  | Wine Weekly News #51 (2000 Week 28) | 
|  |  | 
|  | Events, progress, and happenings in the Wine community for | 
|  | July 10, 2000. | 
|  |  | 
|  | Uwe Bonnes and Ove Kaven also reminded of some tools to generate under | 
|  | Linux some Windows executables: | 
|  | * Cygwin/Mingw: as native Linux apps | 
|  | * LCC-Win32: run with the help of Wine | 
|  | * Borland C++ 5.5: command line version available for free (after | 
|  | registering to Borland users' database) | 
|  |  | 
|  | ===================================================================== | 
|  |  | 
|  | The information included here is from various Wine-devel posting and | 
|  | private e-mails. I am including them so that any one starting on MFC | 
|  | will have some documentation. Glean what you can and good luck. | 
|  |  | 
|  | Before I write more detailed info on compiling MFC I have three | 
|  | questions. The info I have mentions three problems: | 
|  |  | 
|  | 1. Wine header files---what is the status of this? Do changes need | 
|  | to be made in the headers and if so, do I submit the changes back | 
|  | into Wine cvs? Do the changes need #ifdef for C vs. C++ | 
|  | compilation? | 
|  |  | 
|  | Francois Gouget <fgouget@psn.net> has been doing a lot of work in | 
|  | this area. It should be a lot easier to compile using C++ now and to | 
|  | compile MFC. | 
|  |  | 
|  | 2. DOS format files <CR/LF> and no case distinction in | 
|  | filenames. Do the extensions Corel made to gcc 2.95 handle this? | 
|  | If so, how? | 
|  |  | 
|  | 3. Microsoft extensions to the C++ syntax. Do the extensions Corel | 
|  | made to gcc 2.95 handle this? If so, how? | 
|  |  | 
|  | If you have info that needs to be added, send me email at | 
|  | <wilbur.dale@lumin.nl> and I will add it. | 
|  |  | 
|  | ===================================================================== | 
|  |  | 
|  | THANKS | 
|  |  | 
|  | Most of the information in this file came from postings on | 
|  | <Wine-devel@Winehq.com> and from private e-mails. The following people | 
|  | contributed information for this document and I thank them for their | 
|  | time and effort in answering my questions. I also want to thank them | 
|  | for encouraging me to attack the MFC problem. | 
|  |  | 
|  | CONTRIBUTERS: | 
|  |  | 
|  | Damyan Ognyanoff <Damyan@rocketmail.com> | 
|  | Gavriel State <gav@magmacom.com> | 
|  | Ian Schmidt <ischmidt@cfl.rr.com> | 
|  | Jeremy White <jwhite@codeweavers.com> | 
|  |  | 
|  |  | 
|  | From: Ian Schmidt <ischmidt@cfl.rr.com> | 
|  | Subject: Re: WineLib and MFC | 
|  |  | 
|  | "Wilbur N. Dale" wrote: | 
|  |  | 
|  | > What is the status of MFC under WineLib? | 
|  |  | 
|  | I don't know precisely. Corel has done more MFC work than anyone (all | 
|  | of their applications which they are porting are MFC-based), and | 
|  | reportedly they have MFC itself compiled. I was just trying to get a | 
|  | moderately simple MFC-using app to compile, with moderate success | 
|  | (there are still some problems with MFC's headers after my patch, but | 
|  | at least they don't appear to be Wine's fault :) I did not try to | 
|  | compile MFC itself. | 
|  |  | 
|  | > Which versions of MFC, if any? | 
|  |  | 
|  | I have no idea what version Corel uses. As noted in my patch, I was | 
|  | fiddling with the headers for MFC 6 (from Visual C++ 6.0 Service Pack | 
|  | 3). Most of the stuff my patch addressed was for newer IE 5-related | 
|  | features, so I'd guess MFC 5 (VC++ 5.0) is likely what they used. | 
|  |  | 
|  | > Is there any documentation on how to compile MFC for WineLib?  If so | 
|  | > where? | 
|  |  | 
|  | Not that I know of. | 
|  |  | 
|  | > I have started to compile programs using WineLib (hello.c last | 
|  | > Sunday) and expect to be ready to start compiling MFC in a couple of | 
|  | > weeks. If documentation is not available on compiling MFC, I am | 
|  | > willing to write it. | 
|  |  | 
|  | Documentation would be a Good Thing, as WineLib in general is grossly | 
|  | underdocumented right now. Here's a few tips I discovered to get you | 
|  | started: | 
|  |  | 
|  | - First off, run all the MFC headers (and source too if you try it) | 
|  | through a utility to strip out the DOS carriage returns. They cause | 
|  | havoc with GCC when it sees one after a line that ends with a \ (and | 
|  | MFC has many macros in it's headers that meet that description). If | 
|  | you don't have one, do a Google search on "fromdos" and you should | 
|  | locate some source (or it's fairly easy to make your own). | 
|  |  | 
|  | - Use GCC 2.95.2, and the -fpermissive flag to make it less picky. | 
|  | 2.95.2 has some VC++-compatibility features that Corel paid for, and I | 
|  | believe more are forthcoming in future GCCs. | 
|  |  | 
|  | - Use -I to add whereever you have the MFC headers at to your include | 
|  | path, as MFC apps typically use #include <> to access them rather than | 
|  | "". | 
|  |  | 
|  | - Be prepared to have to rename and/or symlink headers, unless you | 
|  | compile on a case-insensitive filesystem :) | 
|  |  | 
|  | - When you make install Wine it seems not to include all it's headers | 
|  | in /usr/local/include/Wine. To have any chance at getting MFC going | 
|  | you'll want to use -I to add the include/ directory from the Wine | 
|  | source tarball to the path so it can grab everything. | 
|  |  | 
|  | Sorry I can't help you more, but good luck! | 
|  |  | 
|  | -Ian Schmidt | 
|  | ischmidt@cfl.rr.com | 
|  |  | 
|  |  | 
|  | From: Jeremy White <jwhite@codeweavers.com> | 
|  | Subject: Re: RFC: Wine 1.0 | 
|  |  | 
|  | "Wilbur N. Dale" wrote: | 
|  | > > Further, we have successfully built MFC after making only | 
|  | > > a modest set of changes to it, even with older | 
|  | > > versions of g++. | 
|  | > | 
|  | > Lumin Software is about to use WineLib to port a window program to linux. A | 
|  | > couple of years ago we thought we had to make a modification to MFC for one | 
|  | > of our projects and we had problems getting MFC to compile under MS Visual C++. | 
|  | > After much wailing and gnashing of teeth, we gave up and did things another | 
|  | > way. After this bad experience, we were wondering --- approximately how many | 
|  | > man-hours did you spend compiling and changing MFC ? | 
|  |  | 
|  | Urk. I misspoke. None of the developers here that I thought | 
|  | had working versions of MFC with Wine have working versions any | 
|  | longer. So, it may be a bit trickier than I led you to believe. | 
|  |  | 
|  | We have it working pretty reliably with TWine, but not | 
|  | quite so cleanly (yet) with Wine. However, it really shouldn't | 
|  | be too difficult, and this is what I can remember of the process: | 
|  |  | 
|  | 1. If you use a very modern version of gcc (2.95.2 or higher), | 
|  | I believe you will need to add the -relaxed flag to | 
|  | have any hope of compiling. | 
|  |  | 
|  | 2. If you use an earlier version of gcc, you will need to | 
|  | adjust the many anonymous structs/unions that MFC supplies. | 
|  | We prefer this approach, because requiring very | 
|  | modern gcc implementations seems harsh to us. | 
|  |  | 
|  | 3. You will need to adjust for the many type differences | 
|  | between MFC intrinsic types and the types supplied by Wine. | 
|  | For example, I believe that MFC expects a HANDLE to | 
|  | be compatible with certain scalar types, (and it is | 
|  | under Windows/VC, but is not with Wine/gcc). | 
|  |  | 
|  | 4. The key procedure:  add many -DNO_XXX flags to the | 
|  | makefile. If you start with Microsofts make file | 
|  | for MFC, convert it into a Wine makefile, and then turn | 
|  | on many of the flags they list there (of the form -DNO_XXX), | 
|  | your life will get much easier. Once you get it working | 
|  | with a few -DNO_XXX flags, you can go back and add them | 
|  | back in. | 
|  |  | 
|  | 5. The best resource:  you need someone who knows C++ very, | 
|  | very well. You occassionaly run into very obscure C++ | 
|  | problems where MS has extended the C++ standard and | 
|  | gcc has not. It really helps to have a guru on hand | 
|  | when you hit those. | 
|  |  | 
|  |  | 
|  | I hope this helps. Sorry for the earlier deceptive post. | 
|  |  | 
|  | Jeremy | 
|  |  | 
|  | From: Gavriel State <gav@magmacom.com> | 
|  | Subject: Re: MFC questions | 
|  |  | 
|  | "Wilbur N. Dale" wrote: | 
|  |  | 
|  | > 1. Compile MFC. Several years ago we (Lumin Software) tried to | 
|  | > compile MFC.  The attempt failed and we found another way to do what | 
|  | > we wanted. MS documentation states that compiling MFC was | 
|  | > deliberately made difficult.  Considering my experience with stuff | 
|  | > they call "easy" I am not looking forward to compiling MFC. We are | 
|  | > currently using Visual Studio 5 for windows development. | 
|  |  | 
|  | At Corel, we had MFC compiled and running sample apps in WineLib in | 
|  | late 1998. It's mostly a question of the Wine headers, which weren't | 
|  | originally up to snuff. We did quite a bit of work on them, and most | 
|  | of those changes have been contributed back to WineHQ, so it should be | 
|  | pretty easy now. The other thing that was a big deal was getting the | 
|  | startup code working properly - since MFC needs to initialize static | 
|  | data *after* WineLib gets initialized. I believe that that issue has | 
|  | been addressed now on the WineHQ side with some of the work done on | 
|  | the .spec file tools recently. | 
|  |  | 
|  | -Gav | 
|  |  | 
|  | -- | 
|  | Gavriel State | 
|  | CEO | 
|  | TransGaming Technologies Inc. | 
|  | gav@transgaming.com | 
|  |  | 
|  | From: Jeremy White <jwhite@codeweavers.com> | 
|  | Subject: Re: MFC questions | 
|  |  | 
|  | "Wilbur N. Dale" wrote: | 
|  | [snip] | 
|  | > 1. Compile MFC. Several years ago we (Lumin Software) tried to | 
|  | > compile MFC.  The attempt failed and we found another way to do what | 
|  | > we wanted. MS documentation states that compiling MFC was | 
|  | > deliberately made difficult.  Considering my experience with stuff | 
|  | > they call "easy" I am not looking forward to compiling MFC. We are | 
|  | > currently using Visual Studio 5 for windows development. | 
|  |  | 
|  | Wilbur, I personally think that this is the 'right' approach, although | 
|  | approach #2 may prove faster. | 
|  |  | 
|  | Despite your previous experience, and despite my earlier incorrect | 
|  | statements, I think that this is simpler than you fear. It's one of | 
|  | those tasks that's darkest before the storm - you spend all of your | 
|  | energy getting all the include files to work. Once you have *one* | 
|  | object file, the rest go much more quickly (alright, getting it to | 
|  | link is also a hairball of a job, but it's tractable <g>). | 
|  |  | 
|  | If you're not in a hurry, getting MFC to compile, and having a | 
|  | documented procedure for compiling it is on our agenda for the | 
|  | relatively near future (see the Wine 1.0 task list). | 
|  |  | 
|  | Jer | 
|  |  | 
|  | p.s. Stick with Visi C++ 5. IMHO its MFC license is cleaner than that | 
|  | of VC 6. | 
|  |  | 
|  | From: Gavriel State <gav@magmacom.com> | 
|  | Subject: The MSVC++ 6.0 license | 
|  |  | 
|  | Jeremy White wrote: | 
|  | > p.s. Stick with Visi C++ 5. IMHO its MFC license is cleaner than that | 
|  | > of VC 6. | 
|  |  | 
|  | Actually, I just picked up a copy of MSVC 6.0 and it appears that they | 
|  | changed the license between the original release and the Service Pack | 
|  | 3 release - they removed the bit in section 1.1 about requiring that | 
|  | you be developing your software product only for use with a Microsoft | 
|  | OS.  In any case, even the original license explicitly says that the | 
|  | MFC redistribution rights are *in addition* to the usage rights in | 
|  | section 1.1. | 
|  |  | 
|  | The relevant portion of the original EULA: | 
|  |  | 
|  | 1.1	General License Grant. Microsoft grants to you as an individual, a | 
|  | personal, nonexclusive license to make and use copies of the SOFTWARE | 
|  | PRODUCT for the sole purposes of designing, developing, and testing your | 
|  | software product(s) that are designed to operate in conjunction with | 
|  | any Microsoft operating system product. [Other unrelated stuff deleted] | 
|  |  | 
|  | >From the SP3 EULA: | 
|  |  | 
|  | 3.	Section 1.1 of the EULA is deleted in its entirety and replaced | 
|  | with the following: | 
|  |  | 
|  | 1.1	General License Grant. Microsoft grants to you as an individual, a | 
|  | personal, nonexclusive license to make and use copies of the SOFTWARE | 
|  | PRODUCT for the purpose of designing, developing, and testing your | 
|  | software product(s). [Other unrelated stuff deleted] | 
|  |  | 
|  | Disclaimer - I am not a lawyer, but I've spent lots of time with them | 
|  | investigating software licenses. | 
|  |  | 
|  | -Gav | 
|  |  | 
|  | -- | 
|  | Gavriel State | 
|  | CEO | 
|  | TransGaming Technologies Inc. | 
|  | gav@transgaming.com | 
|  |  | 
|  | From: Damyan Ognyanoff <Damyan@rocketmail.com> | 
|  | Subject: Need a hint | 
|  |  | 
|  | Hi, | 
|  |  | 
|  | I manage to build mfc42 as .so library and a application using it (as | 
|  | a .so library too). I execute it using simple loader which is linked | 
|  | to Wine and I load my application in it's WinMain routine. The | 
|  | problem is how clearly to unload mfc and my application (to invoke | 
|  | mfc's destructors before loader is terminated) All is fine except that | 
|  | there is a "zombi" reference to code in shared library which is | 
|  | invoked in Wine code and generate GPF. debugger stops somewhere in | 
|  | aplication's InitInstance !!! - and the stack is broken so I can't | 
|  | catch where exactly the problem is. Any hints are welcome. I'm using | 
|  | Wine-2000517 shapshot downloaded form Wine.datapary.no | 
|  |  | 
|  | TNX. | 
|  |  | 
|  | Damyan | 
|  | p.s. | 
|  | If any of You is interested in details I can share my | 
|  | experience. | 
|  |  | 
|  | WND comment: | 
|  | Francois Gouget <fgouget@psn.net> has been doing a lot of work in | 
|  | the  headers of wine. It should be a lot easier to compile using | 
|  | C++ now and to compile MFC. Many of the actions needed in the | 
|  | following email are not needed any more. | 
|  |  | 
|  | From: Damyan Ognyanoff <Damyan@rocketmail.com> | 
|  | Subject: Re: Wine MFC info request | 
|  |  | 
|  | hi, | 
|  | my MFC is from VC6.0 with SP3 | 
|  | MFC Bulid: (form  afxbld_.h) | 
|  | #define _MFC_BUILD 8447 | 
|  | #define _MFC_USER_BUILD "8447" | 
|  | #define _MFC_RBLD 0 | 
|  | mfcdll.rc | 
|  | FILEVERSION       6,0,_MFC_BUILD,_MFC_RBLD | 
|  | PRODUCTVERSION    6,0,0,0 | 
|  |  | 
|  | Hints: | 
|  | 1. Wine include files | 
|  |  | 
|  | In some of them you will find error about '__attribute__' all kinds of | 
|  | similar errors can be fixed using proper typedefs first example : | 
|  |  | 
|  | typedef BOOL (CALLBACK *DLGPROC)(HWND,UINT,WPARAM,LPARAM); | 
|  |  | 
|  | must be converted to | 
|  |  | 
|  | typedef BOOL CALLBACK (*DLGPROC)(HWND,UINT,WPARAM,LPARAM); | 
|  |  | 
|  | and the second kind is something like | 
|  |  | 
|  | TYPE* WINAPI SomeFunction(HWND param1,UINT param2); | 
|  |  | 
|  | The problem here is a TYPE* or TYPE& (in some of mfc files) the | 
|  | workaround is to declare a type before: | 
|  |  | 
|  | typedef TYPE* TYPEPtr; | 
|  |  | 
|  | or | 
|  |  | 
|  | typedef TYPE& TYPERef; | 
|  |  | 
|  | and declaration will look like: | 
|  |  | 
|  | TYPEPtr WINAPI SomeFunction(HWND param1,UINT param2); | 
|  |  | 
|  | note: don't miss a 'struct' when you define struct type pointers. I | 
|  | miss it and get a lot of problems compiling MFC: | 
|  |  | 
|  | >> | 
|  | struct _TEB; | 
|  | typedef !!!struct!!! _TEB* P_TEB; | 
|  | extern inline P_TEB WINAPI NtCurrentTeb(void); | 
|  | << | 
|  |  | 
|  | Those conversions are semanticaly the same as above but g++ compile | 
|  | them and generate proper code to invoke __stdcall kind of functions | 
|  |  | 
|  | in some of Wine/obj_XXX.h files: Wine/obj_base.h - there are a lot of | 
|  | defines's that are used to declare a COM interfaces | 
|  |  | 
|  | #define ICOM_METHOD(ret,xfn) \ | 
|  | public: virtual ret (CALLBACK xfn)(void) = 0; | 
|  |  | 
|  | will be (for all of them that are related to C++ (watch #ifdef's | 
|  | carefully)): | 
|  |  | 
|  | #define ICOM_METHOD(ret,xfn) \ | 
|  | public: virtual ret CALLBACK (xfn)(void) = 0; | 
|  |  | 
|  | and the second tip is an error when compiler stops on line like: | 
|  |  | 
|  | ICOM_DEFINE(ISomeInterfase,IUnknown) | 
|  |  | 
|  | watch method declarations above to find something like: | 
|  |  | 
|  | ICOM_METHOD1(TYPE*,MethodName, DWORD,dwParam) | 
|  |  | 
|  | and replace TYPE* with proper TYPEPtr type. In many cases You will see | 
|  | void* which can be replaced simply by LPVOID. | 
|  |  | 
|  | qthere are several errors related to anonymous structs and unions but | 
|  | they can be avoided with proper - #ifdef __cplusplus | 
|  |  | 
|  | This is all about Wine headers I think. If you find something that I | 
|  | miss type a line of mail to me. | 
|  |  | 
|  | 2. MFC | 
|  | The rules are the same with some new issues: | 
|  |  | 
|  | virtual BOOL Method1(int param1, BOOL (CALLBACK *param2) | 
|  | (HWND,UINT,WPARAM,LPARAM)); | 
|  |  | 
|  | don't compile. I remove a function pointer declaration | 
|  | outside method: | 
|  |  | 
|  | typedef BOOL CALLBACK | 
|  | (*param2Type)(HWND,UINT,WPARAM,LPARAM); | 
|  |  | 
|  | virtual BOOL Method1(int param1, param2Type param2); | 
|  |  | 
|  | I didn't apply this technique to a operator new | 
|  | definitions: | 
|  |  | 
|  | void* AFXAPI operator new(size_t nSize); | 
|  |  | 
|  | so i remove AFXAPI from these declarations: | 
|  |  | 
|  | I got some missed #defines from commctrl.h and I added | 
|  | them form VC6.0 include. | 
|  |  | 
|  | these are my defines form Makefile which I used to | 
|  | compile MFC | 
|  |  | 
|  | -DTWINE_NO_CMONIKER \ -- this is related to exclude | 
|  | CMonikerFile | 
|  | -D__urlmon_h__ \ -- Wine didn't have URL interfaces | 
|  | -D_AFX_NO_OLEDB_SUPPORT \ | 
|  | -D_WIN32  \ | 
|  | -DNOWIN98  \ -- this is used to exclude all | 
|  | unimplemented classes from commctrl | 
|  | -D_AFX_PACKING \ | 
|  | -D_AFX_NO_DHTML_SUPPORT \ | 
|  | -D_AFX_NO_SOCKET_SUPPORT \ | 
|  | -D_AFX_NO_SYNC_SUPPORT \ | 
|  | -D_AFX_NO_OCX_SUPPORT  \ | 
|  | -D_AFX_PORTABLE \ | 
|  | -D_AFX_OLD_EXCEPTIONS \ | 
|  | -D_AFX_NO_SOCKET_SUPPORT \ | 
|  | -D_AFX_NO_DEBUG_CRT \ | 
|  | -D_AFX_NO_DAO_SUPPORT \ | 
|  | -D_AFX_NO_OCC_SUPPORT \ | 
|  | -D_AFX_NO_INET_SUPPORT \ | 
|  | -D_AFX_NO_RICHEDIT_SUPPORT  \ | 
|  | -D_X86_ \ | 
|  | -DLONGHANDLES | 
|  |  | 
|  | may be you will try to enable some of features of mfc I tested only | 
|  | -D_AFX_NO_OCC_SUPPORT but got missing interfaces from Wine | 
|  |  | 
|  | in file afxcom_.h | 
|  | - _CIP<_Interface, _IID>::~_CIP<_Interface, _IID>() | 
|  | + _CIP<_Interface, _IID>::~_CIP() | 
|  |  | 
|  | in file afxtempl.h | 
|  | -       BOOL Lookup(BASE_CLASS::BASE_ARG_KEY key, | 
|  | VALUE& rValue) const | 
|  | -               { return BASE_CLASS::Lookup(key, | 
|  | (BASE_CLASS::BASE_VALUE&)rValue); } | 
|  | +       BOOL Lookup(typename BASE_CLASS::BASE_ARG_KEY | 
|  | key, VALUE& rValue) const | 
|  | +               { return BASE_CLASS::Lookup(key, | 
|  | (typename BASE_CLASS::BASE_VALUE&)rValue); } | 
|  |  | 
|  | and all releated errors can be fixed in this way. | 
|  |  | 
|  | 3. spec file | 
|  | name        mfc42 | 
|  | type        win32 | 
|  | rsrc        mfc42 | 
|  |  | 
|  | 10 stdcall WinMain(long long ptr long) WinMain | 
|  |  | 
|  | 4. linking | 
|  | use -rdynamic wnen link libmfc.so to get ARGV and | 
|  | ARGC from loader | 
|  |  | 
|  | 5. I didn'n build a extension dll with Wine but I suspect that there | 
|  | will be some problems related to a chaining Runtime classes form MFC | 
|  | to a new dll | 
|  |  | 
|  | 6. build your app as a MODULE too. | 
|  |  | 
|  | 7. make a loader and in it's _WinMain: | 
|  | ... includes are here | 
|  | iint PASCAL (*winMain)(HINSTANCE,HINSTANCE,LPSTR,int) = | 
|  | 0; | 
|  | my app uses these to manage filenames | 
|  | VOID __cdecl (*_splitpath1)(LPCSTR path, LPSTR drive, | 
|  | LPSTR directory, LPSTR filename, LPSTR extension ) = | 
|  | NULL; | 
|  | VOID __cdecl _splitpath(LPCSTR path, LPSTR drive, | 
|  | LPSTR directory, LPSTR filename, LPSTR extension ) | 
|  | { | 
|  | if (_splitpath1) | 
|  | _splitpath1(path, drive, directory, filename, | 
|  | extension ); | 
|  | } | 
|  | VOID __cdecl (*_makepath1)(LPSTR path, LPCSTR drive, | 
|  | LPCSTR directory, LPCSTR filename, LPCSTR extension ) | 
|  | = NULL; | 
|  | VOID __cdecl _makepath(LPSTR path, LPCSTR drive, | 
|  | LPCSTR directory, LPCSTR filename, LPCSTR extension ) | 
|  | { | 
|  | if (_makepath1) | 
|  | _makepath1(path, drive, directory, filename, | 
|  | extension); | 
|  | } | 
|  | int PASCAL _WinMain(HINSTANCE h,HINSTANCE h1,LPSTR | 
|  | lpszCmdParam,int c) | 
|  | { | 
|  | HINSTANCE hInstance,hins,hlib,htst,hform,himag,hexe; | 
|  | int retv; | 
|  |  | 
|  | hins = LoadLibrary("CRTDLL.DLL"); | 
|  | _splitpath1 = GetProcAddress(hins, | 
|  | "_splitpath"); | 
|  | _makepath1 = GetProcAddress(hins, | 
|  | "_makepath"); | 
|  | hins = LoadLibrary("COMCTL32.DLL"); | 
|  | hins = LoadLibrary("COMDLG32.DLL"); | 
|  |  | 
|  |  | 
|  | hins = dlopen("libmfc42.so",2); | 
|  | hlib = LoadLibrary("mfc42"); | 
|  | himag = dlopen("libmxformatslib.so",2); | 
|  | hform = LoadLibrary("mxformatslib"); | 
|  | hexe = dlopen("libmxpaint.so",2); | 
|  | htst = LoadLibrary("mxpaint"); | 
|  |  | 
|  | winMain = GetProcAddress(hlib, "WinMain"); | 
|  | if (winMain) | 
|  | { | 
|  | retv = winMain (htst,    // note the > htst | 
|  | < HERE | 
|  | 0, | 
|  | lpszCmdParam, | 
|  | SW_NORMAL); | 
|  | } | 
|  | FreeLibrary(htst); | 
|  | FreeLibrary(hform); | 
|  | FreeLibrary(hlib); | 
|  | dlclose(hexe); | 
|  | dlclose(himag); | 
|  | dlclose(hins); | 
|  | return retv; | 
|  | } | 
|  | the spec for loader is: | 
|  | name    c10 | 
|  | mode    guiexe | 
|  | type    win32 | 
|  | init    _WinMain | 
|  |  | 
|  | please find attached a Makefile which i use to build | 
|  | MFC | 
|  |  | 
|  | Regards | 
|  | Damyan. | 
|  |  | 
|  | LocalWords:  WineLib HOWTO Jul vs DLLs DLL MFC NT FIXME CrypKey Kenonic API TM | 
|  | LocalWords:  Codewright NE PE WinMain GPL LGPL EULA nonexclusive winver nt dos | 
|  | LocalWords:  redistributables unix tr CR LF gcc libtest winebuild pic fPIC dll | 
|  | LocalWords:  guiexe init cuiexe lwine lncurses lm lutil ldl wav winmm wrc lcc | 
|  | LocalWords:  dllExamples WindowsExeWindowsDLL WindowsExeWineDLL WineExeWineDLL | 
|  | LocalWords:  WineExeWindowsDLL Borland URL's cd distclean DllMain winemain exe | 
|  | LocalWords:  winedll cdecl WINEbirthDay str WINEfullName WINEbirthday libtool | 
|  | LocalWords:  proost conf LD libwinedll Gouget docs dumpbin ConstString | 
|  | LocalWords:  pWINEfullName LoadLibrary GetProcAddress hiddenWinedll |