Release 950817
[wine] / misc / main.c
1 /*
2  * Main function.
3  *
4  * Copyright 1994 Alexandre Julliard
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <ctype.h>
11 #include <locale.h>
12 #ifdef MALLOC_DEBUGGING
13 #include <malloc.h>
14 #endif
15 #include <X11/Xlib.h>
16 #include <X11/Xresource.h>
17 #include <X11/Xutil.h>
18 #include <X11/cursorfont.h>
19 #include "wine.h"
20 #include "msdos.h"
21 #include "windows.h"
22 #include "miscemu.h"
23 #include "winsock.h"
24 #include "options.h"
25 #include "desktop.h"
26 #include "dlls.h"
27 #define DEBUG_DEFINE_VARIABLES
28 #include "stddebug.h"
29 #include "debug.h"
30
31 const char people[] = "Wine is available thanks to the work of "\
32 "Bob Amstadt, Dag Asheim, Martin Ayotte, Ross Biro, Erik Bos, Fons Botman, "\
33 "John Brezak, Andrew Bulhak, John Burton, Paul Falstad, Olaf Flebbe, "\
34 "Peter Galbavy, Cameron Heide, Jeffrey Hsu, Miguel de Icaza, "\
35 "Alexandre Julliard, Jon Konrath, Scott A. Laird, Martin von Loewis, "\
36 "Kenneth MacDonald, Peter MacDonald, William Magro, David Metcalfe, "\
37 "Michael Patra, John Richardson, Johannes Ruscheinski, Thomas Sandford, "\
38 "Constantine Sapuntzakis, Bernd Schmidt, Yngvi Sigurjonsson, Rick Sladkey, "\
39 "William Smith, Erik Svendsen, Goran Thyni, Jimmy Tirtawangsa, Jon Tombs, "\
40 "Linus Torvalds, Michael Veksler, Carl Williams, Karl Guenter Wuensch, "\
41 "Eric Youngdale, and James Youngman.";
42
43 #define WINE_CLASS    "Wine"    /* Class name for resources */
44
45 typedef struct tagENVENTRY {
46   LPSTR                 Name;
47   LPSTR                 Value;
48   WORD                  wSize;
49   struct tagENVENTRY    *Prev;
50   struct tagENVENTRY    *Next;
51 } ENVENTRY, *LPENVENTRY;
52
53 LPENVENTRY      lpEnvList = NULL;
54
55 Display *display;
56 Screen *screen;
57 Window rootWindow;
58 int screenWidth = 0, screenHeight = 0;  /* Desktop window dimensions */
59 int screenDepth = 0;  /* Screen depth to use */
60 int desktopX = 0, desktopY = 0;  /* Desktop window position (if any) */
61
62 struct options Options =
63 {  /* default options */
64     NULL,           /* desktopGeometry */
65     NULL,           /* programName */
66     FALSE,          /* usePrivateMap */
67     FALSE,          /* synchronous */
68     FALSE,          /* backing store */
69     SW_SHOWNORMAL,  /* cmdShow */
70     FALSE,
71     FALSE,          /* AllowReadOnly */
72     FALSE,          /* Enhanced mode */
73     FALSE           /* IPC enabled */
74 };
75
76
77 static XrmOptionDescRec optionsTable[] =
78 {
79     { "-backingstore",  ".backingstore",    XrmoptionNoArg,  (caddr_t)"on" },
80     { "-desktop",       ".desktop",         XrmoptionSepArg, (caddr_t)NULL },
81     { "-depth",         ".depth",           XrmoptionSepArg, (caddr_t)NULL },
82     { "-display",       ".display",         XrmoptionSepArg, (caddr_t)NULL },
83     { "-iconic",        ".iconic",          XrmoptionNoArg,  (caddr_t)"on" },
84     { "-ipc",           ".ipc",             XrmoptionNoArg,  (caddr_t)"off"},
85     { "-name",          ".name",            XrmoptionSepArg, (caddr_t)NULL },
86     { "-privatemap",    ".privatemap",      XrmoptionNoArg,  (caddr_t)"on" },
87     { "-synchronous",   ".synchronous",     XrmoptionNoArg,  (caddr_t)"on" },
88     { "-debug",         ".debug",           XrmoptionNoArg,  (caddr_t)"on" },
89     { "-debugmsg",      ".debugmsg",        XrmoptionSepArg, (caddr_t)NULL },
90     { "-dll",           ".dll",             XrmoptionSepArg, (caddr_t)NULL },
91     { "-allowreadonly", ".allowreadonly",   XrmoptionNoArg,  (caddr_t)"on" },
92     { "-enhanced",      ".enhanced",        XrmoptionNoArg,  (caddr_t)"off"}
93 };
94
95 #define NB_OPTIONS  (sizeof(optionsTable) / sizeof(optionsTable[0]))
96
97 #define USAGE \
98   "Usage:  %s [options] program_name [arguments]\n" \
99   "\n" \
100   "Options:\n" \
101   "    -depth n        Change the depth to use for multiple-depth screens\n" \
102   "    -desktop geom   Use a desktop window of the given geometry\n" \
103   "    -display name   Use the specified display\n" \
104   "    -iconic         Start as an icon\n" \
105   "    -ipc            Enable IPC facilities\n" \
106   "    -debug          Enter debugger before starting application\n" \
107   "    -name name      Set the application name\n" \
108   "    -privatemap     Use a private color map\n" \
109   "    -synchronous    Turn on synchronous display mode\n" \
110   "    -backingstore   Turn on backing store\n" \
111   "    -spy file       Obsolete. Use -debugmsg +spy for Spy messages\n" \
112   "    -debugmsg name  Turn debugging-messages on or off\n" \
113   "    -dll name       Enable or disable built-in DLLs\n" \
114   "    -allowreadonly  Read only files may be opened in write mode\n" \
115   "    -enhanced       Start wine in enhanced mode (like 'win /3') \n"
116
117
118
119 /***********************************************************************
120  *           MAIN_Usage
121  */
122 static void MAIN_Usage( char *name )
123 {
124     fprintf( stderr, USAGE, name );
125     exit(1);
126 }
127
128
129 /***********************************************************************
130  *           MAIN_GetProgramName
131  *
132  * Get the program name. The name is specified by (in order of precedence):
133  * - the option '-name'.
134  * - the environment variable 'WINE_NAME'.
135  * - the last component of argv[0].
136  */
137 static char *MAIN_GetProgramName( int argc, char *argv[] )
138 {
139     int i;
140     char *p;
141
142     for (i = 1; i < argc-1; i++)
143         if (!strcmp( argv[i], "-name" )) return argv[i+1];
144     if ((p = getenv( "WINE_NAME" )) != NULL) return p;
145     if ((p = strrchr( argv[0], '/' )) != NULL) return p+1;
146     return argv[0];
147 }
148
149
150 /***********************************************************************
151  *           MAIN_GetResource
152  *
153  * Fetch the value of resource 'name' using the correct instance name.
154  * 'name' must begin with '.' or '*'
155  */
156 static int MAIN_GetResource( XrmDatabase db, char *name, XrmValue *value )
157 {
158     char *buff_instance, *buff_class;
159     char *dummy;
160     int retval;
161
162     buff_instance = (char *)malloc(strlen(Options.programName)+strlen(name)+1);
163     buff_class    = (char *)malloc( strlen(WINE_CLASS) + strlen(name) + 1 );
164
165     strcpy( buff_instance, Options.programName );
166     strcat( buff_instance, name );
167     strcpy( buff_class, WINE_CLASS );
168     strcat( buff_class, name );
169     retval = XrmGetResource( db, buff_instance, buff_class, &dummy, value );
170     free( buff_instance );
171     free( buff_class );
172     return retval;
173 }
174
175
176 /***********************************************************************
177  *                    ParseDebugOptions
178  *
179  *  Turns specific debug messages on or off, according to "options".
180  *  Returns TRUE if parsing was successfull 
181  */
182 #ifdef DEBUG_RUNTIME
183
184 BOOL ParseDebugOptions(char *options)
185 {
186   int l;
187   if (strlen(options)<3)
188     return FALSE;
189   do
190   {
191     if ((*options!='+')&&(*options!='-'))
192       return FALSE;
193     if (strchr(options,','))
194       l=strchr(options,',')-options;
195     else
196       l=strlen(options);
197     if (!strncasecmp(options+1,"all",l-1))
198       {
199         int i;
200         for (i=0;i<sizeof(debug_msg_enabled)/sizeof(short);i++)
201           debug_msg_enabled[i]=(*options=='+');
202       }
203     else
204       {
205         int i;
206         for (i=0;i<sizeof(debug_msg_enabled)/sizeof(short);i++)
207           if (debug_msg_name && (!strncasecmp(options+1,debug_msg_name[i],l-1)))
208             {
209               debug_msg_enabled[i]=(*options=='+');
210               break;
211             }
212         if (i==sizeof(debug_msg_enabled)/sizeof(short))
213           return FALSE;
214       }
215     options+=l;
216   }
217   while((*options==',')&&(*(++options)));
218   if (*options)
219     return FALSE;
220   else
221     return TRUE;
222 }
223
224 #endif
225
226 #ifndef WINELIB
227 /***********************************************************************
228  *           MAIN_ParseDLLOptions
229  *
230  * Set runtime DLL usage flags
231  */
232 static BOOL MAIN_ParseDLLOptions(char *options)
233 {
234   int l;
235   int i;
236   if (strlen(options)<3)
237     return FALSE;
238   do
239   {
240     if ((*options!='+')&&(*options!='-'))
241       return FALSE;
242     if (strchr(options,','))
243       l=strchr(options,',')-options;
244     else l=strlen(options);
245     for (i=0;i<N_BUILTINS;i++)
246          if (!strncasecmp(options+1,dll_builtin_table[i].name,l-1))
247            {
248              dll_builtin_table[i].used = (*options=='+');
249              break;
250            }
251     if (i==N_BUILTINS)
252          return FALSE;
253     options+=l;
254   }
255   while((*options==',')&&(*(++options)));
256   if (*options)
257     return FALSE;
258   else
259     return TRUE;
260 }
261 #endif
262
263
264
265 /***********************************************************************
266  *           MAIN_ParseOptions
267  *
268  * Parse command line options and open display.
269  */
270 static void MAIN_ParseOptions( int *argc, char *argv[] )
271 {
272     char *display_name;
273     XrmValue value;
274     XrmDatabase db = XrmGetFileDatabase("/usr/lib/X11/app-defaults/Wine");
275
276       /* Parse command line */
277     Options.programName = MAIN_GetProgramName( *argc, argv );
278     XrmParseCommand( &db, optionsTable, NB_OPTIONS,
279                      Options.programName, argc, argv );
280
281 #ifdef WINELIB
282     /* Need to assemble command line and pass it to WinMain */
283 #else
284     if (*argc < 2 || strcasecmp(argv[1], "-h") == 0) 
285         MAIN_Usage( argv[0] );
286 #endif
287
288       /* Open display */
289
290     if (MAIN_GetResource( db, ".display", &value )) display_name = value.addr;
291     else display_name = NULL;
292
293     if (!(display = XOpenDisplay( display_name )))
294     {
295         fprintf( stderr, "%s: Can't open display: %s\n",
296                  argv[0], display_name ? display_name : "" );
297         exit(1);
298     }
299
300       /* Get all options */
301     if (MAIN_GetResource( db, ".iconic", &value ))
302         Options.cmdShow = SW_SHOWMINIMIZED;
303     if (MAIN_GetResource( db, ".privatemap", &value ))
304         Options.usePrivateMap = TRUE;
305     if (MAIN_GetResource( db, ".synchronous", &value ))
306         Options.synchronous = TRUE;
307     if (MAIN_GetResource( db, ".backingstore", &value ))
308         Options.backingstore = TRUE;    
309     if (MAIN_GetResource( db, ".debug", &value ))
310         Options.debug = TRUE;
311     if (MAIN_GetResource( db, ".allowreadonly", &value ))
312         Options.allowReadOnly = TRUE;
313     if (MAIN_GetResource( db, ".enhanced", &value ))
314         Options.enhanced = TRUE;
315     if (MAIN_GetResource( db, ".ipc", &value ))
316         Options.ipc = TRUE;
317     if (MAIN_GetResource( db, ".depth", &value))
318         screenDepth = atoi( value.addr );
319     if (MAIN_GetResource( db, ".desktop", &value))
320         Options.desktopGeometry = value.addr;
321 #ifdef DEBUG_RUNTIME
322     if (MAIN_GetResource( db, ".debugoptions", &value))
323         ParseDebugOptions((char*)value.addr);
324 #endif
325     if (MAIN_GetResource( db, ".debugmsg", &value))
326       {
327 #ifndef DEBUG_RUNTIME
328         fprintf(stderr,"%s: Option \"-debugmsg\" not implemented.\n" \
329           "    Recompile with DEBUG_RUNTIME in include/stddebug.h defined.\n",
330           argv[0]);
331         exit(1);
332 #else
333         if (ParseDebugOptions((char*)value.addr)==FALSE)
334           {
335             int i;
336             fprintf(stderr,"%s: Syntax: -debugmsg +xxx,...  or -debugmsg -xxx,...\n",argv[0]);
337             fprintf(stderr,"Example: -debugmsg +all,-heap    turn on all messages except heap messages\n");
338             fprintf(stderr,"Available message types:\n");
339             fprintf(stderr,"%-9s ","all");
340             for(i=0;i<sizeof(debug_msg_enabled)/sizeof(short);i++)
341               if(debug_msg_name[i])
342                 fprintf(stderr,"%-9s%c",debug_msg_name[i],
343                         (((i+2)%8==0)?'\n':' '));
344             fprintf(stderr,"\n\n");
345             exit(1);
346           }
347 #endif
348       }
349
350       if(MAIN_GetResource( db, ".dll", &value))
351 #ifndef WINELIB
352        if(MAIN_ParseDLLOptions((char*)value.addr)==FALSE)
353        {
354          int i;
355          fprintf(stderr,"%s: Syntax: -dll +xxx,... or -dll -xxx,...\n",argv[0]);
356          fprintf(stderr,"Example: -dll -ole2    Do not use emulated OLE2.DLL\n");
357          fprintf(stderr,"Available DLLs\n");
358          for(i=0;i<N_BUILTINS;i++)
359                fprintf(stderr,"%-9s%c",dll_builtin_table[i].name,
360                        (((i+2)%8==0)?'\n':' '));
361          fprintf(stderr,"\n\n");
362          exit(1);
363        }
364 #else
365                 fprintf(stderr,"-dll not supported in libwine\n");
366 #endif
367 }
368
369
370 /***********************************************************************
371  *           MAIN_CreateDesktop
372  */
373 static void MAIN_CreateDesktop( int argc, char *argv[] )
374 {
375     int flags;
376     unsigned int width = 640, height = 480;  /* Default size = 640x480 */
377     char *name = "Wine desktop";
378     XSizeHints *size_hints;
379     XWMHints   *wm_hints;
380     XClassHint *class_hints;
381     XSetWindowAttributes win_attr;
382     XTextProperty window_name;
383
384     flags = XParseGeometry( Options.desktopGeometry,
385                             &desktopX, &desktopY, &width, &height );
386     screenWidth  = width;
387     screenHeight = height;
388
389       /* Create window */
390
391     win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
392                          PointerMotionMask | ButtonPressMask |
393                          ButtonReleaseMask | EnterWindowMask | 
394                          StructureNotifyMask;
395     win_attr.cursor = XCreateFontCursor( display, XC_top_left_arrow );
396
397     rootWindow = XCreateWindow( display, DefaultRootWindow(display),
398                                 desktopX, desktopY, width, height, 0,
399                                 CopyFromParent, InputOutput, CopyFromParent,
400                                 CWEventMask | CWCursor, &win_attr );
401
402       /* Set window manager properties */
403
404     size_hints  = XAllocSizeHints();
405     wm_hints    = XAllocWMHints();
406     class_hints = XAllocClassHint();
407     if (!size_hints || !wm_hints || !class_hints)
408     {
409         fprintf( stderr, "Not enough memory for window manager hints.\n" );
410         exit(1);
411     }
412     size_hints->min_width = size_hints->max_width = width;
413     size_hints->min_height = size_hints->max_height = height;
414     size_hints->flags = PMinSize | PMaxSize;
415     if (flags & (XValue | YValue)) size_hints->flags |= USPosition;
416     if (flags & (WidthValue | HeightValue)) size_hints->flags |= USSize;
417     else size_hints->flags |= PSize;
418
419     wm_hints->flags = InputHint | StateHint;
420     wm_hints->input = True;
421     wm_hints->initial_state = NormalState;
422     class_hints->res_name = argv[0];
423     class_hints->res_class = "Wine";
424
425     XStringListToTextProperty( &name, 1, &window_name );
426     XSetWMProperties( display, rootWindow, &window_name, &window_name,
427                       argv, argc, size_hints, wm_hints, class_hints );
428     XFree( size_hints );
429     XFree( wm_hints );
430     XFree( class_hints );
431
432       /* Map window */
433
434     XMapWindow( display, rootWindow );
435 }
436
437
438 XKeyboardState keyboard_state;
439
440 /***********************************************************************
441  *           MAIN_SaveSetup
442  */
443 static void MAIN_SaveSetup(void)
444 {
445     XGetKeyboardControl(display, &keyboard_state);
446 }
447
448 /***********************************************************************
449  *           MAIN_RestoreSetup
450  */
451 static void MAIN_RestoreSetup(void)
452 {
453     XKeyboardControl keyboard_value;
454
455     keyboard_value.key_click_percent    = keyboard_state.key_click_percent;
456     keyboard_value.bell_percent         = keyboard_state.bell_percent;
457     keyboard_value.bell_pitch           = keyboard_state.bell_pitch;
458     keyboard_value.bell_duration        = keyboard_state.bell_duration;
459     keyboard_value.auto_repeat_mode     = keyboard_state.global_auto_repeat;
460
461     XChangeKeyboardControl(display, KBKeyClickPercent | KBBellPercent | 
462         KBBellPitch | KBBellDuration | KBAutoRepeatMode, &keyboard_value);
463 }
464
465
466 #ifdef MALLOC_DEBUGGING
467 static void malloc_error()
468 {
469        fprintf(stderr,"malloc is not feeling well. Good bye\n");
470        exit(1);
471 }
472 #endif  /* MALLOC_DEBUGGING */
473
474
475 static void called_at_exit(void)
476 {
477     extern void sync_profiles(void);
478
479     sync_profiles();
480     MAIN_RestoreSetup();
481     WSACleanup();
482 }
483
484 /***********************************************************************
485  *           main
486  */
487 int main( int argc, char *argv[] )
488 {    
489     int ret_val;
490     int depth_count, i;
491     int *depth_list;
492
493     extern int _WinMain(int argc, char **argv);
494
495     setbuf(stdout,NULL);
496     setbuf(stderr,NULL);
497
498     setlocale(LC_CTYPE,"");
499
500     XrmInitialize();
501     
502     MAIN_ParseOptions( &argc, argv );
503
504 #ifdef MALLOC_DEBUGGING
505     if(debugging_malloc)
506     {
507        char *trace=getenv("MALLOC_TRACE");
508        if(!trace)
509        {       
510         dprintf_malloc(stddeb,"MALLOC_TRACE not set. No trace generated\n");
511        }else
512        {
513                dprintf_malloc(stddeb,"malloc trace goes to %s\n",trace);
514                mtrace();
515        }
516       mcheck(malloc_error);
517     }
518 #endif
519
520     screen       = DefaultScreenOfDisplay( display );
521     screenWidth  = WidthOfScreen( screen );
522     screenHeight = HeightOfScreen( screen );
523     if (screenDepth)  /* -depth option specified */
524     {
525         depth_list = XListDepths(display,DefaultScreen(display),&depth_count);
526         for (i = 0; i < depth_count; i++)
527             if (depth_list[i] == screenDepth) break;
528         XFree( depth_list );
529         if (i >= depth_count)
530         {
531             fprintf( stderr, "%s: Depth %d not supported on this screen.\n",
532                               Options.programName, screenDepth );
533             exit(1);
534         }
535     }
536     else screenDepth  = DefaultDepthOfScreen( screen );
537     if (Options.synchronous) XSynchronize( display, True );
538     if (Options.desktopGeometry) MAIN_CreateDesktop( argc, argv );
539     else rootWindow = DefaultRootWindow( display );
540
541     MAIN_SaveSetup();
542 #ifndef sparc
543     atexit(called_at_exit);
544 #else
545     on_exit (called_at_exit, 0);
546 #endif
547
548     ret_val = _WinMain( argc, argv );
549
550     return ret_val;
551 }
552
553 /***********************************************************************
554  *           MessageBeep    (USER.104)
555  */
556 void MessageBeep(WORD i)
557 {
558         XBell(display, 100);
559 }
560
561 /***********************************************************************
562  *      GetVersion (KERNEL.3)
563  */
564 LONG GetVersion(void)
565 {
566     return MAKELONG( WINVERSION, WINDOSVER );
567 }
568
569 /***********************************************************************
570  *      GetWinFlags (KERNEL.132)
571  */
572 LONG GetWinFlags(void)
573 {
574   if (Options.enhanced)
575     return (WF_ENHANCED | WF_CPU386 | WF_PMODE | WF_80x87 | WF_PAGING);
576   else
577     return (WF_STANDARD | WF_CPU386 | WF_PMODE | WF_80x87);
578 }
579
580 /***********************************************************************
581  *      SetEnvironment (GDI.132)
582  */
583 int SetEnvironment(LPSTR lpPortName, LPSTR lpEnviron, WORD nCount)
584 {
585         LPENVENTRY      lpNewEnv;
586         LPENVENTRY      lpEnv = lpEnvList;
587         printf("SetEnvironnement('%s', '%s', %d) !\n", 
588                                 lpPortName, lpEnviron, nCount);
589         if (lpPortName == NULL) return -1;
590         while (lpEnv != NULL) {
591                 if (lpEnv->Name != NULL && strcmp(lpEnv->Name, lpPortName) == 0) {
592                         if (nCount == 0 || lpEnviron == NULL) {
593                                 if (lpEnv->Prev != NULL) lpEnv->Prev->Next = lpEnv->Next;
594                                 if (lpEnv->Next != NULL) lpEnv->Next->Prev = lpEnv->Prev;
595                                 free(lpEnv->Value);
596                                 free(lpEnv->Name);
597                                 free(lpEnv);
598                                 printf("SetEnvironnement() // entry deleted !\n");
599                                 return -1;
600                                 }
601                         free(lpEnv->Value);
602                         lpEnv->Value = malloc(nCount);
603                         if (lpEnv->Value == NULL) {
604                                 printf("SetEnvironment() // Error allocating entry value !\n");
605                                 return 0;
606                         }
607                         memcpy(lpEnv->Value, lpEnviron, nCount);
608                         lpEnv->wSize = nCount;
609                         printf("SetEnvironnement() // entry modified !\n");
610                         return nCount;
611                         }
612                 if (lpEnv->Next == NULL) break;
613                 lpEnv = lpEnv->Next;
614                 }
615         if (nCount == 0 || lpEnviron == NULL) return -1;
616         printf("SetEnvironnement() // new entry !\n");
617         lpNewEnv = malloc(sizeof(ENVENTRY));
618         if (lpNewEnv == NULL) {
619                 printf("SetEnvironment() // Error allocating new entry !\n");
620                 return 0;
621                 }
622         if (lpEnvList == NULL) {
623                 lpEnvList = lpNewEnv;
624                 lpNewEnv->Prev = NULL;
625                 }
626         else {
627                 lpEnv->Next = lpNewEnv;
628                 lpNewEnv->Prev = lpEnv;
629                 }
630         lpNewEnv->Next = NULL;
631         lpNewEnv->Name = malloc(strlen(lpPortName) + 1);
632         if (lpNewEnv->Name == NULL) {
633                 printf("SetEnvironment() // Error allocating entry name !\n");
634                 return 0;
635                 }
636         strcpy(lpNewEnv->Name, lpPortName);
637         lpNewEnv->Value = malloc(nCount);
638         if (lpNewEnv->Value == NULL) {
639                 printf("SetEnvironment() // Error allocating entry value !\n");
640                 return 0;
641                 }
642         memcpy(lpNewEnv->Value, lpEnviron, nCount);
643         lpNewEnv->wSize = nCount;
644         return nCount;
645 }
646
647 /***********************************************************************
648  *      GetEnvironment (GDI.134)
649  */
650 int GetEnvironment(LPSTR lpPortName, LPSTR lpEnviron, WORD nMaxSiz)
651 {
652         WORD            nCount;
653         LPENVENTRY      lpEnv = lpEnvList;
654         printf("GetEnvironnement('%s', '%s', %d) !\n",
655                                         lpPortName, lpEnviron, nMaxSiz);
656         while (lpEnv != NULL) {
657                 if (lpEnv->Name != NULL && strcmp(lpEnv->Name, lpPortName) == 0) {
658                         nCount = min(nMaxSiz, lpEnv->wSize);
659                         memcpy(lpEnviron, lpEnv->Value, nCount);
660                         printf("GetEnvironnement() // found '%s' !\n", lpEnviron);
661                         return nCount;
662                         }
663                 lpEnv = lpEnv->Next;
664                 }
665         printf("GetEnvironnement() // not found !\n");
666         return 0;
667 }
668
669 /***********************************************************************
670  *      GetTimerResolution (USER.14)
671  */
672 LONG GetTimerResolution(void)
673 {
674         return (1000);
675 }
676
677 /***********************************************************************
678  *      SystemParametersInfo (USER.483)
679  */
680 BOOL SystemParametersInfo (UINT uAction, UINT uParam, void FAR *lpvParam, UINT fuWinIni)
681 {
682         int timeout, temp;
683         char buffer[256];
684         XKeyboardState          keyboard_state;
685         XKeyboardControl        keyboard_value;
686
687
688         fprintf(stderr, "SystemParametersInfo: action %d, param %x, flag %x\n", 
689                         uAction, uParam, fuWinIni);
690
691         switch (uAction) {
692                 case SPI_GETBEEP:
693                         XGetKeyboardControl(display, &keyboard_state);
694                         if (keyboard_state.bell_percent == 0)
695                                 *(BOOL *) lpvParam = FALSE;
696                         else
697                                 *(BOOL *) lpvParam = TRUE;
698                         break;
699                 
700                 case SPI_GETBORDER:
701                         *(INT *) lpvParam = 1;
702                         break;
703
704                 case SPI_GETFASTTASKSWITCH:
705                         *(BOOL *) lpvParam = FALSE;
706                         break;
707
708                 case SPI_GETGRIDGRANULARITY:
709                         *(INT *) lpvParam = 1;
710                         break;
711
712                 case SPI_GETICONTITLEWRAP:
713                         *(BOOL *) lpvParam = FALSE;
714                         break;
715
716                 case SPI_GETKEYBOARDDELAY:
717                         *(INT *) lpvParam = 1;
718                         break;
719
720                 case SPI_GETKEYBOARDSPEED:
721                         *(WORD *) lpvParam = 30;
722                         break;
723
724                 case SPI_GETMENUDROPALIGNMENT:
725                         *(BOOL *) lpvParam = FALSE;
726                         break;
727
728                 case SPI_GETSCREENSAVEACTIVE:
729                         *(BOOL *) lpvParam = FALSE;
730                         break;
731
732                 case SPI_GETSCREENSAVETIMEOUT:
733                         XGetScreenSaver(display, &timeout, &temp,&temp,&temp);
734                         *(INT *) lpvParam = timeout * 1000;
735                         break;
736
737                 case SPI_ICONHORIZONTALSPACING:
738                         if (lpvParam == NULL)
739                                 fprintf(stderr, "SystemParametersInfo: Horizontal icon spacing set to %d\n.", uParam);
740                         else
741                                 *(INT *) lpvParam = 50;
742                         break;
743
744                 case SPI_ICONVERTICALSPACING:
745                         if (lpvParam == NULL)
746                                 fprintf(stderr, "SystemParametersInfo: Vertical icon spacing set to %d\n.", uParam);
747                         else
748                                 *(INT *) lpvParam = 50;
749                         break;
750
751                 case SPI_SETBEEP:
752                         if (uParam == TRUE)
753                                 keyboard_value.bell_percent = -1;
754                         else
755                                 keyboard_value.bell_percent = 0;                        
756                         XChangeKeyboardControl(display, KBBellPercent, 
757                                                         &keyboard_value);
758                         break;
759
760                 case SPI_SETSCREENSAVEACTIVE:
761                         if (uParam == TRUE)
762                                 XActivateScreenSaver(display);
763                         else
764                                 XResetScreenSaver(display);
765                         break;
766
767                 case SPI_SETSCREENSAVETIMEOUT:
768                         XSetScreenSaver(display, uParam, 60, DefaultBlanking, 
769                                                 DefaultExposures);
770                         break;
771
772                 case SPI_SETDESKWALLPAPER:
773                         return (SetDeskWallPaper((LPSTR) lpvParam));
774                         break;
775
776                 case SPI_SETDESKPATTERN:
777                         if ((INT) uParam == -1) {
778                                 GetProfileString("Desktop", "Pattern", 
779                                                 "170 85 170 85 170 85 170 85", 
780                                                 buffer, sizeof(buffer) );
781                                 return (DESKTOP_SetPattern((LPSTR) buffer));
782                         } else
783                                 return (DESKTOP_SetPattern((LPSTR) lpvParam));
784                         break;
785
786                 case SPI_GETICONTITLELOGFONT: 
787                 {
788                   LPLOGFONT lpLogFont = (LPLOGFONT)lpvParam;
789                   lpLogFont->lfHeight = 10;
790                   lpLogFont->lfWidth = 0;
791                   lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
792                   lpLogFont->lfWeight = FW_NORMAL;
793                   lpLogFont->lfItalic = lpLogFont->lfStrikeOut = lpLogFont->lfUnderline = FALSE;
794                   lpLogFont->lfCharSet = ANSI_CHARSET;
795                   lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
796                   lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
797                   lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
798                   break;
799                 }
800                 case SPI_LANGDRIVER:
801                 case SPI_SETBORDER:
802                 case SPI_SETDOUBLECLKHEIGHT:
803                 case SPI_SETDOUBLECLICKTIME:
804                 case SPI_SETDOUBLECLKWIDTH:
805                 case SPI_SETFASTTASKSWITCH:
806                 case SPI_SETKEYBOARDDELAY:
807                 case SPI_SETKEYBOARDSPEED:
808                         fprintf(stderr, "SystemParametersInfo: option %d ignored.\n", uParam);
809                         break;
810
811                 default:
812                         fprintf(stderr, "SystemParametersInfo: unknown option %d.\n", uParam);
813                         break;
814         }
815         return 1;
816 }
817
818 /***********************************************************************
819 *       HMEMCPY (KERNEL.348)
820 */
821 void hmemcpy(void FAR *hpvDest, const void FAR *hpvSource, long cbCopy)
822 {
823         memcpy(hpvDest, hpvSource, cbCopy);
824 }
825
826 /***********************************************************************
827 *       COPY (GDI.250)
828 */
829 void Copy(LPVOID lpSource, LPVOID lpDest, WORD nBytes)
830 {
831         memcpy(lpDest, lpSource, nBytes);
832 }
833
834 /***********************************************************************
835 *       SWAPMOUSEBUTTON (USER.186)
836 */
837 BOOL SwapMouseButton(BOOL fSwap)
838 {
839         return 0;       /* don't swap */
840 }
841
842 /***********************************************************************
843 *       FileCDR (KERNEL.130)
844 */
845 void FileCDR(FARPROC x)
846 {
847         printf("FileCDR(%8x)\n", (int) x);
848 }