| 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 |