Fixed some places where whitespace was not handled correctly.
[wine] / documentation / implementation.sgml
1   <chapter id="implementation">
2     <title>Low-level Implementation</title>
3     <para>Details of Wine's Low-level Implementation...</para>
4
5     <sect1 id="builtin-dlls">
6       <title>Builtin DLLs</title>
7
8       <para>
9         Written by &name-juergen-schmied; <email>&email-juergen-schmied;</email>
10       </para>
11       <para>
12         (Extracted from <filename>wine/documentation/internal-dll</filename>)
13       </para>
14
15       <para>
16         This document describes some points you should know before
17         implementing the internal counterparts to external DLL's.
18         Only 32 bit DLL's are considered.
19       </para>
20
21       <sect2>
22         <title>1. The LibMain function</title>
23
24         <para>
25           This is the way to do some initializing when a process or
26           thread is attached to the dll. The function name is taken
27           from a <filename>*.spec</filename> file line:
28         </para>
29         <programlisting>
30 init    YourFunctionName
31         </programlisting>
32         <para>
33           Then, you have to implement the function:
34         </para>
35         <programlisting>
36 BOOL32 WINAPI YourLibMain(HINSTANCE32 hinstDLL,
37                          DWORD fdwReason, LPVOID lpvReserved)
38 { if (fdwReason==DLL_PROCESS_ATTACH)
39   { ...
40   } 
41   ....
42 }
43         </programlisting>
44       </sect2>
45
46       <sect2>
47         <title>2. Using functions from other built-in DLL's</title>
48
49         <para>
50           The problem here is, that you can't know if you have to call
51           the function from the internal or the external DLL. If you
52           just call the function you will get the internal
53           implementation. If the external DLL is loaded the executed
54           program will use the external DLL and you the internal one.
55           When you -as an example- fill an iconlist placed in the
56           internal DLL the application won't get the icons from the
57           external DLL.
58         </para>
59         <para>
60           To work around this, you should always use a pointer to call
61           such functions:
62         </para>
63         <programlisting>
64 /* definition of the pointer type*/
65 void (CALLBACK* pDLLInitComctl)();
66
67 /* getting the function address  this should be done in the
68  LibMain function when called with DLL_PROCESS_ATTACH*/
69  
70 BOOL32 WINAPI Shell32LibMain(HINSTANCE32 hinstDLL, DWORD fdwReason,
71                                                          LPVOID lpvReserved)
72 { HINSTANCE32 hComctl32;
73   if (fdwReason==DLL_PROCESS_ATTACH)
74   { /* load the external / internal DLL*/
75     hComctl32 = LoadLibrary32A("COMCTL32.DLL"); 
76     if (hComctl32)
77     { /* get the function pointer */
78       pDLLInitComctl=GetProcAddress32(hComctl32,"InitCommonControlsEx");
79
80           /* check it */
81       if (pDLLInitComctl)
82       { /* use it */
83         pDLLInitComctl();
84       }
85       
86       /* free the DLL / decrease the ref count */
87       FreeLibrary32(hComctl32);
88     }
89     else
90     { /* do some panic*/
91       ERR(shell,"P A N I C error getting functionpointers\n");
92       exit (1);
93     }
94   }
95  ....
96         </programlisting>
97       </sect2>
98
99       <sect2>
100         <title>3. Getting resources from a <filename>*.rc</filename> file linked to the DLL</title>
101
102         <para>
103           &lt; If you know how, write some lines&gt;
104         </para>
105       </sect2>
106     </sect1>
107
108     <sect1 id="accel-impl">
109       <title>Accelerators</title>
110
111       <para>
112         Findings researched by Uwe Bonnes, Ulrich Weigand and Marcus Meissner.
113       </para>
114       <para>
115         (Extracted from <filename>wine/documentation/accelerators</filename>)
116       </para>
117
118       <para>
119         Some notes concerning accelerators.
120       </para>
121       <para>
122         There are <emphasis>three</emphasis> differently sized
123         accelerator structures exposed to the user. The general layout
124         is:
125       </para>
126       <programlisting>
127 BYTE   fVirt;
128 WORD   key;
129 WORD   cmd;
130       </programlisting>
131       <para>
132         We now have three different appearances:
133       </para>
134
135       <orderedlist>
136         <listitem>
137           <para>
138             Accelerators in NE resources. These have a size of 5 byte
139             and do not have any padding. This is also the internal
140             layout of the global handle <type>HACCEL</type> (16 and
141             32) in Windows 95 and WINE. Exposed to the user as Win16
142             global handles <type>HACCEL16</type> and
143             <type>HACCEL32</type> by the Win16/Win32 API.
144           </para>
145         </listitem>
146         <listitem>
147           <para>
148             Accelerators in PE resources. These have a size of 8 byte.
149             Layout is:
150           </para>
151           <programlisting>
152 BYTE   fVirt;
153 BYTE   pad0;
154 WORD   key;
155 WORD   cmd;
156 WORD   pad1;
157           </programlisting>
158           <para>
159             They are exposed to the user only by direct accessing PE
160             resources.
161           </para>
162         </listitem>
163         <listitem>
164           <para>
165             Accelerators in the Win32 API. These have a size of 6
166             bytes. Layout is:
167           </para>
168           <programlisting>
169 BYTE   fVirt;
170 BYTE   pad0;
171 WORD   key;
172 WORD   cmd;
173           </programlisting>
174           <para>
175             These are exposed to the user by the
176             <function>CopyAcceleratorTable</function> and
177             <function>CreateAcceleratorTable</function> functions in
178             the Win32 API.
179           </para>
180         </listitem>
181       </orderedlist>
182
183       <para>
184         Why two types of accelerators in the Win32 API? We can only
185         guess, but my best bet is that the Win32 resource compiler
186         can/does not handle struct packing. Win32 <type>ACCEL</type>
187         is defined using <function>#pragma(2)</function> for the
188         compiler but without any packing for RC, so it will assume
189         <function>#pragma(4)</function>.
190       </para>
191
192     </sect1>
193
194     <sect1 id="file-handles">
195       <title>File Handles</title>
196
197       <para>
198         Written by (???)
199       </para>
200       <para>
201         (Extracted from <filename>wine/documentation/filehandles</filename>)
202       </para>
203
204       <para>
205         DOS treats the first 5 file handles as special cases.  They
206         map directly to <filename>stdin</filename>,
207         <filename>stdout</filename>, <filename>stderr</filename>,
208         <filename>stdaux</filename> and <filename>stdprn</filename>.
209         Windows 16 inherits this behavior, and in fact, win16 handles
210         are interchangable with DOS handles. Some nasty windows
211         programs even do this!
212       </para>
213       <para>
214         Windows32 issues file handles starting from
215         <literal>1</literal>, on the grounds that most GUI processes
216         don't need a <filename>stdin</filename>,
217         <filename>stdout</filename>, etc.
218       </para>
219       <para>
220         The Wine handle code is implemented in the Win32 style, and
221         the Win16 functions use two macros to convert to and from the
222         two types.
223       </para>
224
225       <para>
226         The macros are defined in <filename>file.h</filename> as follows:
227       </para>
228       <programlisting>
229 #define HFILE16_TO_HFILE32(handle) \
230 (((handle)==0) ? GetStdHandle(STD_INPUT_HANDLE) : \
231  ((handle)==1) ? GetStdHandle(STD_OUTPUT_HANDLE) : \
232  ((handle)==2) ? GetStdHandle(STD_ERROR_HANDLE) : \
233  ((handle)>0x400) ? handle : \
234  (handle)-5)
235
236 #define HFILE32_TO_HFILE16(handle) ({ HFILE32 hnd=handle; \
237       ((hnd==HFILE_ERROR32) ? HFILE_ERROR16 : \
238       ((handle>0x400) ? handle : \
239        (HFILE16)hnd+5); })
240       </programlisting>
241
242       <warning>
243         <para>
244           Be careful not to use the macro
245           <function>HFILE16_TO_HFILE32</function> on functions with
246           side-effects, as it will cause them to be evaluated several
247           times.  This could be considered a bug, but the use of this
248           macro is limited enough not to need a rewrite.
249         </para>
250       </warning>
251       <note>
252         <para>
253           The <literal>0x400</literal> special case above deals with
254           LZW filehandles (see <filename>misc/lzexpand.c</filename>).
255         </para>
256       </note>
257     </sect1>
258
259     <sect1 id="hardware-trace">
260       <title>Doing A Hardware Trace In Wine</title>
261
262       <para>
263         Written by &name-jonathan-buzzard; <email>&email-jonathan-buzzard;</email>
264       </para>
265       <para>
266         (Extracted from <filename>wine/documentation/ioport-trace-hints</filename>)
267       </para>
268
269       <para>
270         The primary reason to do this is to reverse engineer a
271         hardware device for which you don't have documentation, but
272         can get to work under Wine.
273       </para>
274       <para>
275         This lot is aimed at parallel port devices, and in particular
276         parallel port scanners which are now so cheap they are
277         virtually being given away. The problem is that few
278         manufactures will release any programming information which
279         prevents drivers being written for Sane, and the traditional
280         technique of using DOSemu to produce the traces does not work
281         as the scanners invariably only have drivers for Windows.
282       </para>
283       <para>
284         Please note that I have not been able to get my scanner
285         working properly (a UMAX Astra 600P), but a couple of people
286         have reported success with at least the Artec AS6e scanner. I
287         am not in the process of developing any driver nor do I intend
288         to, so don't bug me about it. My time is now spent writing
289         programs to set things like battery save options under Linux
290         on Toshiba laptops, and as such I don't have any spare time
291         for writing a driver for a parallel port scanner etc.
292       </para>
293       <para>
294         Presuming that you have compiled and installed wine the first
295         thing to do is is to enable direct hardware access to your
296         parallel port. To do this edit <filename>wine.conf</filename>
297         (usually in <filename>/usr/local/etc</filename>) and in the
298         ports section add the following two lines
299       </para>
300       <programlisting>
301 read=0x378,0x379,0x37a,0x37c,0x77a
302 write=0x378,x379,0x37a,0x37c,0x77a
303       </programlisting>
304       <para>
305         This adds the necessary access required for SPP/PS2/EPP/ECP
306         parallel port on LPT1. You will need to adjust these number
307         accordingly if your parallel port is on LPT2 or LPT0.
308       </para>
309       <para>
310         When starting wine use the following command line, where
311         <literal>XXXX</literal> is the program you need to run in
312         order to access your scanner, and <literal>YYYY</literal> is
313         the file your trace will be stored in:
314       </para>
315       <programlisting>
316 wine -debugmsg +io XXXX 2&gt; &gt;(sed 's/^[^:]*:io:[^ ]* //' &gt; YYYY)
317       </programlisting>
318       <para>
319         You will need large amounts of hard disk space (read hundreds
320         of megabytes if you do a full page scan), and for reasonable
321         performance a really fast processor and lots of RAM.
322       </para>
323       <para>
324         You might well find the log compression program that <email>David
325         Campbell campbell@torque.net</email> wrote helpful in
326         reducing the size of the log files. This can be obtained by
327         the following command:
328       </para>
329       <programlisting>
330 sh ioport-trace-hints
331       </programlisting>
332       <para>
333         This should extract <filename>shrink.c</filename> (which is
334         located at the end of this file. Compile the log compression
335         program by:
336       </para>
337       <programlisting>
338 cc shrink.c -o shrink
339       </programlisting>
340       <para>
341         Use the <command>shrink</command> program to reduce the
342         physical size of the raw log as follows:
343       </para>
344       <programlisting>
345 cat log | shrink &gt; log2
346       </programlisting>
347       <para>
348         The trace has the basic form of
349       </para>
350       <programlisting>
351 XXXX &gt; YY @ ZZZZ:ZZZZ
352       </programlisting>
353       <para>
354         where <literal>XXXX</literal> is the port in hexidecimal being
355         accessed, <literal>YY</literal> is the data written (or read)
356         from the port, and <literal>ZZZZ:ZZZZ</literal> is the address
357         in memory of the instruction that accessed the port. The
358         direction of the arrow indicates whether the data was written
359         or read from the port.
360       </para>
361       <programlisting>
362 &gt; data was written to the port
363 &lt; data was read from the port
364       </programlisting>
365       <para>
366         My basic tip for interperating these logs is to pay close
367         attention to the addresses of the IO instructions. Their
368         grouping and sometimes proximity should reveal the presence of
369         subroutines in the driver. By studying the different versions
370         you should be able to work them out. For example consider the
371         following section of trace from my UMAX Astra 600P
372       </para>
373       <programlisting>
374 0x378 &gt; 55 @ 0297:01ec
375 0x37a &gt; 05 @ 0297:01f5
376 0x379 &lt; 8f @ 0297:01fa
377 0x37a &gt; 04 @ 0297:0211
378 0x378 &gt; aa @ 0297:01ec
379 0x37a &gt; 05 @ 0297:01f5
380 0x379 &lt; 8f @ 0297:01fa
381 0x37a &gt; 04 @ 0297:0211
382 0x378 &gt; 00 @ 0297:01ec
383 0x37a &gt; 05 @ 0297:01f5
384 0x379 &lt; 8f @ 0297:01fa
385 0x37a &gt; 04 @ 0297:0211
386 0x378 &gt; 00 @ 0297:01ec
387 0x37a &gt; 05 @ 0297:01f5
388 0x379 &lt; 8f @ 0297:01fa
389 0x37a &gt; 04 @ 0297:0211
390 0x378 &gt; 00 @ 0297:01ec
391 0x37a &gt; 05 @ 0297:01f5
392 0x379 &lt; 8f @ 0297:01fa
393 0x37a &gt; 04 @ 0297:0211
394 0x378 &gt; 00 @ 0297:01ec
395 0x37a &gt; 05 @ 0297:01f5
396 0x379 &lt; 8f @ 0297:01fa
397 0x37a &gt; 04 @ 0297:0211
398       </programlisting>
399       <para>
400         As you can see their is a repeating structure starting at
401         address <literal>0297:01ec</literal> that consists of four io
402         accesses on the parallel port. Looking at it the first io
403         access writes a changing byte to the data port the second
404         always writes the byte <literal>0x05</literal> to the control
405         port, then a value which always seems to
406         <literal>0x8f</literal> is read from the status port at which
407         point a byte <literal>0x04</literal> is written to the control
408         port. By studying this and other sections of the trace we can
409         write a C routine that emulates this, shown below with some
410         macros to make reading/writing on the parallel port easier to
411         read.
412       </para>
413       <programlisting>
414 #define r_dtr(x)        inb(x)
415 #define r_str(x)        inb(x+1)
416 #define r_ctr(x)        inb(x+2)
417 #define w_dtr(x,y)      outb(y, x)
418 #define w_str(x,y)      outb(y, x+1)
419 #define w_ctr(x,y)      outb(y, x+2)
420
421 /*
422  * Seems to be sending a command byte to the scanner
423  *
424  */
425 int udpp_put(int udpp_base, unsigned char command)
426 {
427         int loop,value;
428
429         w_dtr(udpp_base, command);
430         w_ctr(udpp_base, 0x05);
431
432         for (loop=0;loop&lt;10;loop++)
433                 if (((value=r_str(udpp_base)) & 0x80)!=0x00) {
434                         w_ctr(udpp_base, 0x04);
435                         return value & 0xf8;
436                         }
437
438         return (value & 0xf8) | 0x01;
439 }
440       </programlisting>
441       <para>
442         For the UMAX Astra 600P only seven such routines exist (well
443         14 really, seven for SPP and seven for EPP). Whether you
444         choose to disassemble the driver at this point to verify the
445         routines is your own choice. If you do, the address from the
446         trace should help in locating them in the disassembly.
447       </para>
448       <para>
449         You will probably then find it useful to write a script/perl/C
450         program to analyse the logfile and decode them futher as this
451         can reveal higher level grouping of the low level routines.
452         For example from the logs from my UMAX Astra 600P when decoded
453         futher reveal (this is a small snippet)
454       </para>
455       <programlisting>
456 start:
457 put: 55 8f
458 put: aa 8f
459 put: 00 8f
460 put: 00 8f
461 put: 00 8f
462 put: c2 8f
463 wait: ff
464 get: af,87
465 wait: ff
466 get: af,87
467 end: cc
468 start:
469 put: 55 8f
470 put: aa 8f
471 put: 00 8f
472 put: 03 8f
473 put: 05 8f
474 put: 84 8f
475 wait: ff
476       </programlisting>
477       <para>
478         From this it is easy to see that <varname>put</varname>
479         routine is often grouped together in five successive calls
480         sending information to the scanner. Once these are understood
481         it should be possible to process the logs further to show the
482         higher level routines in an easy to see format. Once the
483         highest level format that you can derive from this process is
484         understood, you then need to produce a series of scans varying
485         only one parameter between them, so you can discover how to
486         set the various parameters for the scanner.
487       </para>
488
489       <para>
490         The following is the <filename>shrink.c</filename> program.
491       </para>
492
493       <programlisting>
494 cat &gt; shrink.c &lt;&lt;EOF
495 #include &lt;stdio.h&gt;
496 #include &lt;string.h&gt;
497
498 void 
499 main (void)
500 {
501   char buff[256], lastline[256];
502   int count;
503
504   count = 0;
505   lastline[0] = 0;
506
507   while (!feof (stdin))
508     {
509       fgets (buff, sizeof (buff), stdin);
510       if (strcmp (buff, lastline) == 0)
511         {
512           count++;
513         }
514       else
515         {
516           if (count &gt; 1)
517             fprintf (stdout, "# Last line repeated %i times #\n", count);
518           fprintf (stdout, "%s", buff);
519           strcpy (lastline, buff);
520             count = 1;
521         }
522     }
523 }
524 EOF
525       </programlisting>
526     </sect1>
527
528   </chapter>
529
530 <!-- Keep this comment at the end of the file
531 Local variables:
532 mode: sgml
533 sgml-parent-document:("wine-doc.sgml" "set" "book" "part" "chapter" "")
534 End:
535 -->