this patch adds winedump documentation (Alexandre, you can delete tools/winedump/README if you want) A+
Name: doc_winedump ChangeLog: added winedump doc to winelib book License: X11 GenDate: 2002/09/20 20:10:35 UTC ModifiedFiles: documentation/authors.ent documentation/tools.sgml AddedFiles: =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/documentation/authors.ent,v retrieving revision 1.2 diff -u -u -r1.2 authors.ent --- documentation/authors.ent 24 Jul 2002 03:00:02 -0000 1.2 +++ documentation/authors.ent 20 Sep 2002 20:07:27 -0000 @@ -99,6 +99,9 @@ <!entity name-jeremy-white "Jeremy White"> <!entity email-jeremy-white "jwhite@codeweavers.com"> +<!entity name-jon-griffiths "Jon Griffiths"> +<!entity email-jon-griffiths "jon_p_griffiths@yahoo.com"> + <!-- *** Coders mentioned in docs, but not doc writers *** --> <!entity name-francis-beaudet "Francis Beaudet"> Index: documentation/tools.sgml =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/documentation/tools.sgml,v retrieving revision 1.2 diff -u -u -r1.2 tools.sgml --- documentation/tools.sgml 13 Dec 2000 21:52:37 -0000 1.2 +++ documentation/tools.sgml 20 Sep 2002 20:08:21 -0000 @@ -45,7 +45,7 @@ filename. <command>bin2res -d bin rsrc.rc</command> generates binary files from all marked resources. If the binary file is newer it gets not overwritten. To force - overwriting use the <parameter>-f</parameter> switch. + overwriting use the <option>-f</option> switch. </para> </sect2> @@ -65,7 +65,7 @@ the resources into the <filename>.rc</filename> file if the binary resources are newer than the.rc file. To force the resources into the <filename>.rc</filename> file use the - <parameter>-f</parameter> switch. If there is already a + <option>-f</option> switch. If there is already a resource with the same filename in the <filename>.rc</filename> file it gets overwritten. </para> @@ -83,6 +83,1100 @@ means changed. </para> </sect2> + </sect1> + + <sect1 id="winedump"> + <title>winedump</title> + + <para>Generated from tools/winedump/README, written by +&name-jon-griffiths; &email-jon-griffiths;.</para> + + <sect2 id="overview"> + <title>Overview</title> + +<para> +<command>winedump</command> is a tool used to manipulate native +modules. It comes with different usages: + <itemizedlist> + <listitem> +<para> +generating default source files (<filename>.spec</filename>, +<filename>.c</filename>...) for using a native DLL in Wine +</para> + </listitem> + <listitem> + <para> + demangling MSVC C++ symbol names + </para> + </listitem> + <listitem> + <para>dumping the 'PE' files contents</para> + </listitem> + </itemizedlist> + </para> + + <sect3 id="usage"> + <title>Usage</title> + + <para> + <command>winedump</command> is a command line + tool. Running it with no arguments or passing it '-h' on + the command line lists the available options. + +<screen> +Usage: winedump [-h | sym <sym> | spec <dll> | dump + <dll>] [mode options] +</screen> + + Winedump can be used in several different modes. The first + argument to the program determines the mode winedump will + run in. +<screen> + -h Help mode. Basic usage help is printed. + sym Symbol mode. Used to demangle C++ symbols + spec For generating .spec files and stub DLL's + dump To dump the contents of a PE file. +</screen> + +[mode options] depend on the mode given as the first argument. + +<screen> +Help mode: + No options are used. The program prints help and then exits + +Sym mode: + <sym> Demangles C++ symbol <sym> and then exits. + +Spec mode: + <dll> Use dll for input file and generate implementation code + -I dir Look for prototypes in 'dir' (implies -c) + -c Generate skeleton code (requires -I) + -t TRACE arguments (implies -c) + -f dll Forward calls to 'dll' (implies -t) + -D Generate documentation + -o name Set the output dll name (default: dll) + -C Assume __cdecl calls (default: __stdcall) + -s num Start prototype search after symbol 'num' + -e num End prototype search after symbol 'num' + -S symfile Search only prototype names found in 'symfile' + -q Don't show progress (quiet). + -v Show lots of detail while working (verbose). + +Dump mode + <dll> Dumps the content of the dll named <dll> + -C Turns on symbol demangling + -f Dumps file header information + -j sect_name Dumps only the content of section sect_name (import, export, debug) + -x Dumps everything +</screen> + </para> + + <sect4 id="opts"> + <title>Basic options</title> + + <para> +<screen> +OPTION: -o name Set the output dll name (default: dll) +</screen> + + By default, if <command>winedump</command> is run on DLL + '<filename>foo</filename>', it creates files called + '<filename>foo.spec</filename>', + '<filename>foo_main.c</filename>' etc, and prefixes any + functions generated with '<function>FOO_</function>'. If + '<option>-o bar</option>' is given, these will + become <filename>'bar.spec</filename>', + '<filename>bar_main.c</filename>' and + '<function>BAR_</function>' respectively. + </para> + <para> + This option is mostly useful when generating a + forwarding DLL. See below for more information. + </para> + + <para> +<screen> +OPTION: -q Don't show progress (quiet). + -v Show lots of detail while working (verbose). +</screen> + + There are 3 levels of output while + <command>winedump</command> is running. The default + level, when neither <option>-q</option> or + <option>-v</option> are given, prints the number + of exported functions found in the DLL, followed by the + name of each function as it is processed, and a status + indication of whether it was processed OK. With + <option>-v</option> given, a lot of information is + dumped while <command>winedump</command> works: this is + intended to help debug any problems. Giving + <option>-q</option> means nothing will be printed + unless a fatal error occurs, and could be used when + calling winedump from a script. + </para> + + <para> +<screen> +OPTION: -C Assume __cdecl calls (default: __stdcall) +</screen> + + This option determines the default calling convention + used by the functions in the DLL. If + <command>winedump</command> cannot determine the + convention, <type>__stdcall</type> is used by default, + unless this option has been given. + </para> + + <para> + Unless <option>-q</option> is given, a warning + will be printed for every function that + <command>winedump</command> determines the calling + convention for and which does not match the assumed + calling convention. + </para> + </sect4> + </sect3> + </sect2> + + <sect2 id="spec"> + <title>Using native DLLs in Wine</title> + + <sect3 id="background"> + <title>Background</title> + + <para> + Most of the functions available in Windows, and in Windows + applications, are made available to applications from + DLL's. Wine implements the Win32 API by providing + replacement's for the essential Windows DLLs in the form + of Unix shared library (<filename>.so</filename>) files, + and provides a tool, <command>winebuild</command>, to + allow Winelib applications to link to functions exported + from shared libraries/DLLs. + </para> + + <para> + The first thing to note is that there are many DLLs that + aren't yet implemented in Wine. Mostly this doesn't + present a problem because the native Win32 versions of + lots of DLLs can be used without problems, at least on x86 + platforms. However, one of Wine's goals is the eventual + replacement of every essential O/S DLL so that the whole + API is implemented. This not only means that a copy of the + real O/S is not needed, but also that non-x86 platforms + can run most Win32 programs after recompiling. + </para> + + <para> + The second thing to note is that applications commonly use + their own or 3rd party DLLs to provide functionality. In + order to call these functions with a Winelib program, some + 'glue' is needed. This 'glue' comes in the form of a + <filename>.spec</filename> file. The + <filename>.spec</filename> file, along with some dummy + code, is used to create a Wine <filename>.so</filename> + corresponding to the Windows DLL. The + <command>winebuild</command> program can then resolve + calls made to DLL functions to call your dummy DLL. You + then tell Wine to only use the native Win32 version of the + DLL, and at runtime your calls will be made to the Win32 + DLL. If you want to reimplement the dll, you simply add + the code for the DLL calls to your stub + <filename>.so</filename>, and then tell Wine to use the + <filename>.so</filename> version instead. + <footnote> + <para> + See the Wine and Wine.conf man pages for details on + how to tell Wine whether to use native (Win32) or + internal DLLs. + </para> + </footnote> + </para> + + <para> + These two factors mean that if you are: + <itemizedlist> + <listitem> + <para> + A: Reimplementing a Win32 DLL for use within Wine, + or + </para> + </listitem> + <listitem> + <para> + B: Compiling a Win32 application with Winelib that + uses x86 DLLs + </para> + </listitem> + </itemizedlist> + </para> + + <para> + Then you will need to create a <filename>.spec</filename> + file (amongst other things). If you won't be doing either of + the above, then you won't need <command>winedump</command>. + </para> + + <para> + Creating a <filename>.spec</filename> file is a labour + intensive task during which it is easy to make a + mistake. The idea of <command>winedump</command> is to + automate this task and create the majority of the support + code needed for your DLL. In addition you can have + <command>winedump</command> create code to help you + reimplement a DLL, by providing tracing of calls to the + DLL, and (in some cases) automatically determining the + parameters, calling conventions, and return values of the + DLLs functions. + </para> + + <para> + You can think of <command>winedump</command> as somewhat + similar to the <command>IMPLIB</command> tool when only its + basic functionality is used. + </para> + + </sect3> + + <sect3 id="stubdll"> + <title>Generating stub DLLS</title> + + <para> + If all you want to do is generate a stub DLL to allow you + to link your Winelib application to an x86 DLL, the above + options are all you need. + </para> + + <para> + As an example, lets assume the application you are porting + uses functions from a 3rd party dll called + '<filename>zipextra.dll</filename>', and the functions in + the DLL use the <type>__stdcall</type> calling + convention. Copy <filename>zipextra.dll</filename> to an + empty directory, change to it, and run + <command>winedump</command> as follows: + +<screen> +winedump spec zipextra +</screen> + (Note: this assumes <command>winedump</command> is in your + path) +</para> + +<para> + The output will look something like the following: +<screen> +22 named symbols in DLL, 22 in total ... +Export 1 - '_OpenZipFile' ... [Ignoring] +Export 2 - '_UnZipFile' ... [Ignoring] +... +</screen> + + "[Ignoring]" Just tells you that + <command>winedump</command> isn't trying to determine the + parameters or return types of the functions, its just + creating stubs. + </para> + + <para> + The following files are created: + <itemizedlist> + <listitem> + <para><filename>zipextra.spec</filename></para> + <para> + This is the <filename>.spec</filename> file. Each + exported function is listed as a stub: +<screen> +@ stub _OpenZipFile +@ stub _UnZipFile +... +</screen> + </para> + + <para> + This means that <command>winebuild</command> will + generate dummy code for this function. That doesn't + concern us, because all we want is for + <command>winebuild</command> to allow the symbols to + be resolved. At run-time, the functions in the + native DLL will be called; this just allows us to link. + </para> + </listitem> + <listitem> + <para> + <filename>zipextra_dll.h zipextra_main.c</filename> + </para> + <para> + These are source code files containing the minimum + set of code to build a stub DLL. The C file contains + one function, <function>ZIPEXTRA_Init</function>, + which does nothing (but must be present). + </para> + </listitem> + <listitem> + <para> + <filename>Makefile.in</filename> + </para> + + <para> + This is a template for + '<command>configure</command>' to produce a + <filename>makefile</filename>. It is designed for a + DLL that will be inserted into the Wine source + tree. If your DLL will not be part of Wine, or you + don't wish to build it this way, you should look at + the Wine tool '<command>winemaker</command>' to + generate a DLL project. + </para> + + <para> + FIXME: <command>winemaker</command> could run this + tool automatically when generating projects that use + extra DLL's (*.lib in the "ADD LINK32" line in .dsp)... + </para> + </listitem> + <listitem> + <para> + <filename>zipextra_install</filename> + </para> + <para> + A shell script for adding zipextra to the Wine + source tree (see below). + </para> + </listitem> + </itemizedlist> + </para> + </sect3> + + <sect3 id="stubwine"> + <title>Inserting a stub DLL into the Wine tree</title> + + <para> + To build your stub DLL as part of Wine, do the following: +<screen> + chmod a+x ./zipextra_install + ./zipextra_install <wine-path> + cd <wine-path> + autoconf + ./configure + make depend && make + make install +</screen> + + Your application can now link with the DLL. + </para> + + <para> + If you recieve the following error when running autoconf: +<screen> +autoconf: configure.in: No such file or directory +</screen> + + Then you need to install a newer version of autoconf. At + the time of writing version 2.53 or later is required to + re-generate configure. + </para> + + <para> + If you have problems with this step, you can post to the + wine-devel mailing list for help. The build process can + change regularly and winebuild may lag behind in support. + </para> + + <note> + <title>Note</title> + <para> + **DO NOT** submit patches to Wine for 3rd party + DLLs! Building DLLs into your copy of the tree is just + a simple way for you to link. When you release your + application you won't be distributing the Unix + <filename>.so</filename> anyway, just the Win32 + DLL. As you update your version of Wine you can simply + re-run the procedure above (Since no patches are + involved, it should be pretty resiliant to changes). + </para> + </note> + </sect3> + + <sect3 id="advanced"> + <title>Advanced Options</title> + + <para> + This section discusses features of + <command>winedump</command> that are useful to Wine + Hackers or developers looking to reimplement a Win32 DLL + for Unix. Using these features means you will need to be + able to resolve compilation problems and have a general + understanding of Wine programming. + </para> + + <para> +<screen> +OPTION: -I dir Look for prototypes in 'dir' (implies -c) +</screen> + + For all advanced functionality, you must give + <command>winedump</command> a directory or file that + contains prototypes for the DLL. In the case of Windows + DLLs, this could be either the standard include directory + from your compiler, or an SDK include directory. If you + have a text document with prototypes (such as + documentation) that can be used also, however you may need + to delete some non-code lines to ensure that prototypes + are parsed correctly. + </para> + + <para> + The 'dir' argument can also be a file specification + (e.g. "include/*"). If it contains wildcards you must + quote it to prevent the shell from expanding it. + </para> + + <para> + If you have no prototypes, specify + <filename>/dev/null</filename> for + 'dir'. <command>winedump</command> may still be able to + generate some working stub code for you. + </para> + + <para> + Once you have created your DLL, if you generated code (see + below), you can backup the DLL header file created and use + it for rebuilding the DLL (you should remove the + <function>DLLNAME_</function> prefix from the prototypes + to make this work). This allows you to add names to the + function arguments, for example, so that the comments and + prototype in the regenerated DLL will be clearer. + </para> + + <para> + <command>winedump</command> searches for prototypes using + '<command>grep</command>', and then retrieves each + prototype by calling + '<command>function_grep.pl</command>', a Perl script. When + you pass the <option>-v</option> option on the + command line, the calls to both of these programs are + logged. This allows you to see where each function + definition has come from. Should + <command>winedump</command> take an excessively long time + to locate a prototype, you can check that it is searching + the right files; you may want to limit the number of files + searched if locating the prototype takes too long. + </para> + + <para> + You can compile <command>function_grep.pl</command> for a + slight increase in performance; see 'man perlcc' for details. + </para> + + <para> +<screen> +OPTION: -s num Start prototype search after symbol 'num' + -e num End prototype search after symbol 'num' +</screen> + + By passing the <option>-s</option> or + <option>-e</option> options you can have + <command>winedump</command> try to generate code for only + some functions in your DLL. This may be used to generate a + single function, for example, if you wanted to add + functionality to an existing DLL. + </para> + + <para> + They is also useful for debugging problems, in conjunction + with <option>-v</option>. + </para> + + <para> +<screen> +OPTION: -D Generate documentation +</screen> + + By default, <command>winedump</command> generates a + standard comment at the header of each function it + generates. Passing this option makes + <command>winedump</command> output a full header template + for standard Wine documentation, listing the parameters + and return value of the function. + </para> + + <para> +<screen> +OPTION: -S symfile Search only prototype names found in '<filename>symfile</filename>' +</screen> + + If you want to only generate code for a subset of exported + functions from your source DLL, you can use this option to + provide a text file containing the names of the symbols to + extract, one per line. Only the symbols present in this + file will be used in your output DLL. + </para> + + <para> +<screen> +OPTION: -c Generate skeleton code (requires -I) +</screen> + + This option tells <command>winedump</command> that you + want to create function stubs for each function in the + DLL. This is the most basic level of code generation. As + <command>winedump</command> reads each exported symbol + from the source DLL, it first tries to demangle the + name. If the name is a C++ symbol, the arguments, class + and return value are all encoded into the symbol + name. <command>winedump</command> converts this + information into a C function prototype. If this fails, + the file(s) specified in the <option>-I</option> + argument are scanned for a function prototype. If one is + found it is used for the next step of the process, code + generation. + </para> + + <note> + <title>Note</title> + <para> + Note: C++ name demangling is currently under + development. Since the algorithm used is not + documented, it must be decoded. Many simple prototypes + are already working however. + </para> + </note> + + <para> + If <command>winedump</command> does not find a prototype, + it emits code like the following: + <itemizedlist> + <listitem> + <para> + In the <filename>.spec</filename> file: +<programlisting> +@stub _OpenZipFile +</programlisting> + </para> + </listitem> + <listitem> + <para> + in the header file: +<programlisting> +/* __cdecl ZIPEXTRA__OpenZipFile() */ +</programlisting> + </para> + </listitem> + <listitem> + <para> + in the C source file: +<programlisting> +/********************************************************************* + * _OpenZipFile (ZIPEXTRA.@) + * + */ +#if 0 +__stdcall ZIPEXTRA__OpenZipFile() +{ + /* '@Stubbed'ed in .spec */ +} +#endif +</programlisting> + + If a prototype is found, or correctly demangled, the + following is emitted: +<programlisting> +.spec: +@ stdcall _OpenZipFile ZIPEXTRA__OpenZipFile + +.h: +BOOL __stdcall ZIPEXTRA__OpenZipFile(LPCSTR pszFileName); + +.c: +BOOL __stdcall ZIPEXTRA__OpenZipFile(LPCSTR pszFileName) +{ + TRACE("stub\n"); + return 0; +} +</programlisting> + </para> + </listitem> + </itemizedlist> + </para> + + <para> + Note that if the prototype does not contain argument + names, <command>winedump</command> will add them following + the convention arg0, arg1 ... argN. If the function is + demangled C++, the first argument will be called '_this' + if an implicit this pointer is passed (i.e. the function + is a non-static class member function). + </para> + + <para> +<screen> +OPTION: -t TRACE arguments (implies -c) +</screen> + + This option produces the same code as + <option>-c</option>, except that arguments are + printed out when the function is called, so the FIXME in + the above example becomes: +<programlisting> + FIXME("(%s) stub", pszFileName); +</programlisting> + </para> + + <para> + Structs that are passed by value are printed as "struct", + and functions that take variable argument lists print "...". + </para> + + <para> +<screen> +OPTION: -f dll Forward calls to 'dll' (implies -t) +</screen> + + This is the most complicated level of code generation. The + same code is generated as <option>-t</option>, + however support is added for forwarding calls to another + DLL. The DLL to forward to is given as 'dll'. Lets suppose + we built the examples above using "<option>-f + real_zipextra</option>". The code generated will look + like the following: + <itemizedlist> + <listitem> + <para>.spec</para> + <para> + As for <option>-c</option>, except if a + function prototype was not found:</para> + <programlisting> +@ forward _OpenZipFile real_zipextra._OpenZipFile +</programlisting> + <para> + In this case the function is forwarded to the + destination DLL rather than stubbed. + </para> + </listitem> + <listitem> + <para>.h</para> + <para>As for <option>-c</option>.</para> + </listitem> + <listitem> + <para>.c</para> + <para> + A variable "hDLL" is added to hold a pointer to the + DLL to forward to, and the initialisation code in + <function>ZIPEXTRA_Init</function> is changed to + load and free the forward DLL automatically: + </para> + +<programlisting> +HMODULE hDLL = 0; /* DLL to call through to */ + +BOOL WINAPI ZIPEXTRA_Init(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + TRACE("(0x%08x, %ld, %p)\n", hinstDLL, fdwReason, lpvReserved); + + if (fdwReason == DLL_PROCESS_ATTACH) + { + hDLL = LoadLibraryA( "real_zipextra" ); + TRACE ("Forwarding DLL (real_zipextra) loaded\n" ); + } + else if (fdwReason == DLL_PROCESS_DETACH) + { + FreeLibrary( hDLL ); + TRACE ("Forwarding DLL (real_zipextra) freed\n" ); + } + + return TRUE; +} +</programlisting> + + <para> + The stub function is changed to call the forwarding + DLL and return that value. + </para> + +<programlisting> +BOOL __stdcall ZIPEXTRA__OpenZipFile(LPCSTR pszFileName) +{ + BOOL (__stdcall *pFunc)(LPCSTR) = (void*)GetProcAddress(hDLL,"_OpenZipFile"); + BOOL retVal; + TRACE("((LPCSTR)%s) stub\n", pszFileName); + retVal = pFunc(pszFileName); + TRACE("returned (%ld)\n",(LONG)retVal)); + return retVal; +} +</programlisting> + + <para> + This allows you to investigate the workings of a DLL + without interfering in its operation in any way + (unless you want to). + </para> + </listitem> + </itemizedlist> + </para> + + <para> + In the example I have been using, we probably should have + used the <option>-o</option> option to change the + ouput name of our DLL to something else, and used the + <option>-f</option> option to forward to the real + <filename>zipextra</filename> DLL: + </para> + + <para> +<screen> +winedump spec zipextra -f zipextra -o myzipextra -I "~/zipextra/include/*h" +</screen> + + Then in the .spec file for our Winelib application, we add + the line: +<programlisting> +import myzipextra +</programlisting> + </para> + + <para> + When we build our application, + <command>winebuild</command> resolves the calls to our + Unix <filename>.so</filename>. As our application runs we + can see the values of all parameters passed to the DLL, + and any values returned, without having to write code to + dump them ourselves (see below for a better way to wrap a DLL for forwarding). + </para> + + <para> + This isn't a very realistic example of the usefulness of + this feature, however, since we could print out the + results anyway, because it is our application making the + calls to the DLL. Where DLL forwarding is most useful is + where an application or DLL we didn't write calls + functions in the DLL. In this case we can capture the + sequence of calls made, and the values passed around. This + is an aid in reimplementing the DLL, since we can add code + for a function, print the results, and then call the real + DLL and compare. Only when our code is the same do we need + to remove the function pointer and the call to the real + DLL. A similar feature in wine is +relay debugging. Using + a fowarding DLL allows more granular reporting of + arguments, because you can write code to dump out the + contents of types/structures rather than just their + address in memory. A future version of + <command>winedump</command> may generate this code + automatically for common Win32 types. + </para> + + <para> + See below for more information on setting up a forwarding DLL. + </para> + + </sect3> + + <sect3 id="comp"> + <title>Problems compiling a DLL containing generated code</title> + + <para> + Unless you are very lucky, you will need to do a small + amount of work to get a DLL generated with + <option>-c</option>, <option>-t</option> or + <option>-f</option> to compile. The reason for this + is that most DLLs will use custom types such as structs + whose definition is not known to the code in the DLL. + </para> + + <para> + Heres an example prototype from crtdll: +<programlisting> +double __cdecl _cabs(struct _complex arg0) +</programlisting> + </para> + + <para> + The definition for the <type>_complex</type> struct needs + to be given. Since it is passed by value, its size also + needs to be correct in order to forward the call correctly + to a native DLL. In this case the structure is 8 bytes in + size, which means that the gcc compile flag + <option>-freg-struct-return</option> must be given + when compiling the function in order to be compatable with + the native DLL. (In general this is not an issue, but you + need to be aware of such issues if you encounter problems + with your forwarding DLL). + </para> + + <para> + For third party (non C++) DLL's, the header(s) supplied + with the DLL can normally be added as an include to the + generated DLL header. For other DLLs I suggest creating a + seperate header in the DLL directory and adding any needed + types to that. This allows you to rebuild the DLL at whim, + for example if a new version of + <command>winedump</command> brings increased + functionality, then you only have to overwrite the + generated files and re-include the header to take + advantage of it. + </para> + + <para> + Usually there isn't much work to do to get the DLL to + compile if you have headers. As an example, building a + forwarded crtdll, which contains 520 functions, required + 20 types to be defined before it compiled. Of these, about + half were structures, so about 35 lines of code were + needed. The only change to the generated code was one line + in the header to include the type definitions. + </para> + + <para> + To save some typing in case you don't have headers for + your DLL type, <command>winedump</command> will dump dummy + declarations for unknown classes and types it encounters, + if you use the <option>-v</option> option. These can + be piped directly into a fix-up header file for use in + compiling your DLL. For example, if + <command>winedump</command> encounters the (C++ ) symbol: +<programlisting> + ??0foobar@@QAE@ABV0@@Z (Which is a constructor for a foobar object) +</programlisting> + + It will emit the following with <option>-v</option> set: +<programlisting> +struct foobar { int _FIXME; }; +</programlisting> + + (Classes are mapped to C structs when generating code). + </para> + + <para> + The output should be piped through + '<command>sort</command>' and '<command>uniq</command>' to + remove multiple declarations, e.g: +<screen> +winedump foo -c -I "inc/*.h" -v | grep FIXME | sort | uniq > fixup.h +</screen> + </para> + + <para> + By adding '<programlisting>#include + "fixup.h"</programlisting>' to + <filename>foobar_dll.h</filename> your compile errors will + be greatly reduced. + </para> + + <para> + If <command>winedump</command> encounters a type it doesnt + know that is passed by value (as in the + <function>_cabs</function> example above), it also prints + a FIXME message like: +<programlisting> +/* FIXME: By value type: Assumed 'int' */ typedef int ldiv_t; +</programlisting> + </para> + + <para> + If the type is not an <type>int</type>, you will need to + change the code and possibly the + <filename>.spec</filename> entry in order to forward + correctly. Otherwise, include the typedef in your fixup + header to avoid compile errors. + </para> + </sect3> + + <sect3 id="forward"> + <title>Using a forwarding DLL</title> + + <para> + To create and use a forwarding DLL to trace DLL calls, you + need to first create a DLL using the + <option>-f</option> option as outlined above, and + get it to compile. In order to forward calls the following + procedure can be used (for this example we are going to + build a forwarding <filename>msvcrt.dll</filename> for the + purpose of reimplementing it). + </para> + + <para> + First we create the forwarding DLL. We will rename the real + <filename>msvcrt.dll</filename> on our system to + <filename>ms_msvcrt.dll</filename>, and our msvcrt + implementation will call it: +<screen> +winedump spec msvcrt -C -f ms_msvcrt -I "inc/*.h" +</screen> + </para> + + <para> + We then install this DLL into the Wine tree and add the + types we need to make it compile. Once the DLL compiles, + we create a dummy <filename>ms_msvcrt</filename> DLL so + <command>winebuild</command> will resolve our forward + calls to it (for the cases where + <command>winedump</command> couldn't generate code and has + placed an '<type>@forward</type>' line in the + <filename>.spec</filename> file): +<screen> +winedump spec msvcrt -C -o ms_msvcrt +</screen> + </para> + + <para> + Install this DLL into the wine tree (since its a stub DLL, + no changes are needed to the code). + </para> + + <para> + Now uncomment the line that <command>winedump</command> + inserted into <filename>msvcrt.spec</filename>: +<programlisting> +#inport ms_msvcrt.dll +</programlisting> + And recompile Wine. + </para> + + <para> + Finally, we must tell Wine to only use the builtin + <filename>msvcrt.dll</filename> and to only use the native + (Win32) <filename>ms_msvcrt.dll</filename>. Add the + following two lines to <filename>~/.wine/config</filename> + under the [DllOverrides] section: +<screen> +;Use our implmentation of msvcrt +"msvcrt" = "builtin, so" +;Use only the Win32 ms_msvcrt +"ms_msvcrt" = "native" +</screen> + </para> + + <para> + At this point, when any call is made to + <filename>msvcrt.dll</filename>, Our + <filename>libmsvcrt.so</filename> recieves the call. It + then forwards our calls + <filename>ms_msvcrt.dll</filename>, which is the native + dll. We recieve a return value and pass it back to our + caller, having TRACEd the arguments on the way. + </para> + + <para> + At this point you are ready to start reimplementing the + calls. + </para> + </sect3> + + <sect3 id="final"> + <title>Final comments</title> + + <para> + If you have any suggestions for improving this tool, + please let me know. If anyone can help answer the + <function>FIXME</function> questions in + <filename>msmangle.c</filename> or can fill me in on any + aspect of the C++ mangling scheme, I would appreciate + it. In particular I want to know what _E and _G + represent. + </para> + + <para> + If you encounter a C++ symbol that doesn't demangle + **AND** you have the prototype for it, please send me the + symbol as reported by <command>winedump</command> and the + prototype. The more examples I have the easier it is to + decypher the scheme, and generating them myself is very slow. + </para> + + <para> + Finally, although it is easy to generate a DLL, I _very + strongly_ suggest that you dont submit a generated DLL for + inclusion into Wine unless you have actually implemented a + fairly reasonable portion of it. Even then, you should + only send the portions of the DLL you have + implemented. Thousands of lines of stub code don't help the project at all. + </para> + + </sect3> + + </sect2> + + <sect2 id="demangl"> + <title>Demangling</title> + + <para> + If you need to demangle a single C++ symbol, you can use the + demangling mode of <command>winedump</command>. This is + useful for testing the demangler or implementing C++ + functions in partially implemented wine DLLS. As an example: +<screen> +winedump sym "??3@YAXPAX@Z" +</screen> + + Gives: <function>void __cdecl _global_operator_delete_1(void + * arg0)</function> + + Which is enough information to begin implementing the function. + </para> + </sect2> + + <sect2 id="dump"> + <title>Dumping a PE file</title> + + <para> + Another use for this tool is to diplay information about a + 32bit DLL or PE format image file. When used in this way + winedump functions similarly to tools such as + <command>pedump</command> provided by many Win32 compiler + vendors. + </para> + + <para> +<screen> +Usage: +winedump dump <dllname.dll> [switches] + +dump mode switches: + -h Display this help message + -C Turns on symbol demangling + -f Dump file header information + -j dir_name Dump only the contents of directory dir_name (import, export, debug) + -x Dump everything +</screen> + + </para> + + <sect3 id="dump_opt"> + <title>Dump mode options</title> + + <para> +<screen> +OPTION: -x Dump everything +</screen> + + This command prints all available information about the + file. You may wish to pipe the output through more/less or + into a file, since a lot of output will be produced. + </para> + + <para> + If you are only interested in a subset of the available + information, you can use one of the following switches: +<screen> +OPTION: -f Dump file header information-x Dump everything +</screen> + + This option dumps only the standard PE header structures, + along with the COFF sections available in the file. + </para> + + <para> +<screen> +OPTION: -j dir_name Dump directory dir_name (import, export, debug) +</screen> + + To dump only a given directory, specify them using this + option. Currently only the import, export and debug + directories are implemented. + </para> + </sect3> + </sect2> + </sect1> </chapter>