Release 960611
[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 <unistd.h>
11 #include <ctype.h>
12 #include <locale.h>
13 #ifdef MALLOC_DEBUGGING
14 #include <malloc.h>
15 #endif
16 #include <X11/Xlib.h>
17 #include <X11/Xresource.h>
18 #include <X11/Xutil.h>
19 #include <X11/cursorfont.h>
20 #include "wine.h"
21 #include "message.h"
22 #include "module.h"
23 #include "msdos.h"
24 #include "windows.h"
25 #include "winsock.h"
26 #include "options.h"
27 #include "desktop.h"
28 #include "shell.h"
29 #include "winbase.h"
30 #include "string32.h"
31 #define DEBUG_DEFINE_VARIABLES
32 #include "stddebug.h"
33 #include "debug.h"
34 #include "xmalloc.h"
35
36 const char people[] = "Wine is available thanks to the work of "
37 "Bob Amstadt, Dag Asheim, Martin Ayotte, Ross Biro, Uwe Bonnes, Erik Bos, "
38 "Fons Botman, John Brezak, Andrew Bulhak, John Burton, "
39 "Niels de Carpentier, Roman Dolejsi, Frans van Dorsselaer, Paul Falstad, "
40 "Olaf Flebbe, Peter Galbavy, Ramon Garcia, Hans de Graaff, "
41 "Charles M. Hannum, John Harvey, Cameron Heide, Jochen Hoenicke, "
42 "Onno Hovers, Jeffrey Hsu, Miguel de Icaza, Jukka Iivonen, "
43 "Alexandre Julliard, Jochen Karrer, Andreas Kirschbaum, Albrecht Kleine, "
44 "Jon Konrath, Alex Korobka, Greg Kreider, Anand Kumria, Scott A. Laird, "
45 "Martin von Loewis, Kenneth MacDonald, Peter MacDonald, William Magro, "
46 "Juergen Marquardt, Marcus Meissner, Graham Menhennitt, David Metcalfe, "
47 "Steffen Moeller, Philippe De Muyter, Itai Nahshon, Michael Patra, "
48 "Jim Peterson, Robert Pouliot, Keith Reynolds, John Richardson, "
49 "Johannes Ruscheinski, Thomas Sandford, Constantine Sapuntzakis, "
50 "Daniel Schepler, Ulrich Schmid, Bernd Schmidt, Yngvi Sigurjonsson, "
51 "Rick Sladkey, William Smith, Erik Svendsen, Tristan Tarrant, "
52 "Andrew Taylor, Duncan C Thomson, Goran Thyni, Jimmy Tirtawangsa, "
53 "Jon Tombs, Linus Torvalds, Gregory Trubetskoy, Michael Veksler, "
54 "Sven Verdoolaege, Eric Warnke, Manfred Weichel, Morten Welinder, "
55 "Jan Willamowius, Carl Williams, Karl Guenter Wuensch, Eric Youngdale, "
56 "and James Youngman. ";
57
58 const char * langNames[] =
59 {
60     "En",  /* LANG_En */
61     "Es",  /* LANG_Es */
62     "De",  /* LANG_De */
63     "No",  /* LANG_No */
64     "Fr",  /* LANG_Fr */
65     "Fi",  /* LANG_Fi */
66     "Da",  /* LANG_Da */
67     "Cz",  /* LANG_Cz */
68     "Eo",  /* LANG_Eo */
69     "It",  /* LANG_It */
70     "Ko",  /* LANG_Ko */
71     NULL
72 };
73
74 #define WINE_CLASS    "Wine"    /* Class name for resources */
75
76 typedef struct tagENVENTRY {
77   LPSTR                 Name;
78   LPSTR                 Value;
79   WORD                  wSize;
80   struct tagENVENTRY    *Prev;
81   struct tagENVENTRY    *Next;
82 } ENVENTRY, *LPENVENTRY;
83
84 LPENVENTRY      lpEnvList = NULL;
85
86 Display *display;
87 Screen *screen;
88 Window rootWindow;
89 int screenWidth = 0, screenHeight = 0;  /* Desktop window dimensions */
90 int screenDepth = 0;  /* Screen depth to use */
91 int desktopX = 0, desktopY = 0;  /* Desktop window position (if any) */
92 int getVersion16 = 0;
93 int getVersion32 = 0;
94 OSVERSIONINFO32A getVersionEx;
95
96 struct options Options =
97 {  /* default options */
98     NULL,           /* desktopGeometry */
99     NULL,           /* programName */
100     FALSE,          /* usePrivateMap */
101     FALSE,          /* useFixedMap */
102     FALSE,          /* synchronous */
103     FALSE,          /* backing store */
104     SW_SHOWNORMAL,  /* cmdShow */
105     FALSE,
106     FALSE,          /* AllowReadOnly */
107     MODE_ENHANCED,  /* Enhanced mode */
108     FALSE,          /* IPC enabled */
109 #ifdef DEFAULT_LANG
110     DEFAULT_LANG,   /* Default language */
111 #else
112     LANG_En,
113 #endif
114     FALSE           /* Managed windows */
115 };
116
117
118 static XrmOptionDescRec optionsTable[] =
119 {
120     { "-backingstore",  ".backingstore",    XrmoptionNoArg,  (caddr_t)"on" },
121     { "-desktop",       ".desktop",         XrmoptionSepArg, (caddr_t)NULL },
122     { "-depth",         ".depth",           XrmoptionSepArg, (caddr_t)NULL },
123     { "-display",       ".display",         XrmoptionSepArg, (caddr_t)NULL },
124     { "-iconic",        ".iconic",          XrmoptionNoArg,  (caddr_t)"on" },
125     { "-ipc",           ".ipc",             XrmoptionNoArg,  (caddr_t)"off"},
126     { "-language",      ".language",        XrmoptionSepArg, (caddr_t)"En" },
127     { "-name",          ".name",            XrmoptionSepArg, (caddr_t)NULL },
128     { "-privatemap",    ".privatemap",      XrmoptionNoArg,  (caddr_t)"on" },
129     { "-fixedmap",      ".fixedmap",        XrmoptionNoArg,  (caddr_t)"on" },
130     { "-synchronous",   ".synchronous",     XrmoptionNoArg,  (caddr_t)"on" },
131     { "-debug",         ".debug",           XrmoptionNoArg,  (caddr_t)"on" },
132     { "-debugmsg",      ".debugmsg",        XrmoptionSepArg, (caddr_t)NULL },
133     { "-dll",           ".dll",             XrmoptionSepArg, (caddr_t)NULL },
134     { "-allowreadonly", ".allowreadonly",   XrmoptionNoArg,  (caddr_t)"on" },
135     { "-mode",          ".mode",            XrmoptionSepArg, (caddr_t)NULL },
136     { "-managed",       ".managed",         XrmoptionNoArg,  (caddr_t)"off"},
137     { "-winver",        ".winver",          XrmoptionSepArg, (caddr_t)NULL }
138 };
139
140 #define NB_OPTIONS  (sizeof(optionsTable) / sizeof(optionsTable[0]))
141
142 #define USAGE \
143   "Usage:  %s [options] program_name [arguments]\n" \
144   "\n" \
145   "Options:\n" \
146   "    -allowreadonly  Read only files may be opened in write mode\n" \
147   "    -backingstore   Turn on backing store\n" \
148   "    -debug          Enter debugger before starting application\n" \
149   "    -debugmsg name  Turn debugging-messages on or off\n" \
150   "    -depth n        Change the depth to use for multiple-depth screens\n" \
151   "    -desktop geom   Use a desktop window of the given geometry\n" \
152   "    -display name   Use the specified display\n" \
153   "    -dll name       Enable or disable built-in DLLs\n" \
154   "    -fixedmap       Use a \"standard\" color map\n" \
155   "    -iconic         Start as an icon\n" \
156   "    -ipc            Enable IPC facilities\n" \
157   "    -language xx    Set the language (one of En,Es,De,No,Fr,Fi,Da,Cz,Eo,It,Ko)\n" \
158   "    -managed        Allow the window manager to manage created windows\n" \
159   "    -mode mode      Start Wine in a particular mode (standard or enhanced)\n" \
160   "    -name name      Set the application name\n" \
161   "    -privatemap     Use a private color map\n" \
162   "    -synchronous    Turn on synchronous display mode\n" \
163   "    -winver         Version to imitate (one of win31,win95,nt351)\n"
164
165
166
167 /***********************************************************************
168  *           MAIN_Usage
169  */
170 #ifndef WINELIB32
171 static void MAIN_Usage( char *name )
172 {
173     fprintf( stderr, USAGE, name );
174     exit(1);
175 }
176 #endif
177
178
179 /***********************************************************************
180  *           MAIN_GetProgramName
181  *
182  * Get the program name. The name is specified by (in order of precedence):
183  * - the option '-name'.
184  * - the environment variable 'WINE_NAME'.
185  * - the last component of argv[0].
186  */
187 static char *MAIN_GetProgramName( int argc, char *argv[] )
188 {
189     int i;
190     char *p;
191
192     for (i = 1; i < argc-1; i++)
193         if (!strcmp( argv[i], "-name" )) return argv[i+1];
194     if ((p = getenv( "WINE_NAME" )) != NULL) return p;
195     if ((p = strrchr( argv[0], '/' )) != NULL) return p+1;
196     return argv[0];
197 }
198
199
200 /***********************************************************************
201  *           MAIN_GetResource
202  *
203  * Fetch the value of resource 'name' using the correct instance name.
204  * 'name' must begin with '.' or '*'
205  */
206 static int MAIN_GetResource( XrmDatabase db, char *name, XrmValue *value )
207 {
208     char *buff_instance, *buff_class;
209     char *dummy;
210     int retval;
211
212     buff_instance = (char *)xmalloc(strlen(Options.programName)+strlen(name)+1);
213     buff_class    = (char *)xmalloc( strlen(WINE_CLASS) + strlen(name) + 1 );
214
215     strcpy( buff_instance, Options.programName );
216     strcat( buff_instance, name );
217     strcpy( buff_class, WINE_CLASS );
218     strcat( buff_class, name );
219     retval = XrmGetResource( db, buff_instance, buff_class, &dummy, value );
220     free( buff_instance );
221     free( buff_class );
222     return retval;
223 }
224
225
226 /***********************************************************************
227  *                    ParseDebugOptions
228  *
229  *  Turns specific debug messages on or off, according to "options".
230  *  Returns TRUE if parsing was successfull 
231  */
232 #ifdef DEBUG_RUNTIME
233
234 BOOL ParseDebugOptions(char *options)
235 {
236   int l;
237   if (strlen(options)<3)
238     return FALSE;
239   do
240   {
241     if ((*options!='+')&&(*options!='-'))
242       return FALSE;
243     if (strchr(options,','))
244       l=strchr(options,',')-options;
245     else
246       l=strlen(options);
247     if (!lstrncmpi32A(options+1,"all",l-1))
248       {
249         int i;
250         for (i=0;i<sizeof(debug_msg_enabled)/sizeof(short);i++)
251           debug_msg_enabled[i]=(*options=='+');
252       }
253     else
254       {
255         int i;
256         for (i=0;i<sizeof(debug_msg_enabled)/sizeof(short);i++)
257           if (debug_msg_name && (!lstrncmpi32A(options+1,debug_msg_name[i],l-1)))
258             {
259               debug_msg_enabled[i]=(*options=='+');
260               break;
261             }
262         if (i==sizeof(debug_msg_enabled)/sizeof(short))
263           return FALSE;
264       }
265     options+=l;
266   }
267   while((*options==',')&&(*(++options)));
268   if (*options)
269     return FALSE;
270   else
271     return TRUE;
272 }
273
274 #endif
275
276
277 /***********************************************************************
278  *           MAIN_ParseLanguageOption
279  *
280  * Parse -language option.
281  */
282 static void MAIN_ParseLanguageOption( char *arg )
283 {
284     const char **p = langNames;
285
286     Options.language = LANG_En;  /* First language */
287     for (p = langNames; *p; p++)
288     {
289         if (!lstrcmpi32A( *p, arg )) return;
290         Options.language++;
291     }
292     fprintf( stderr, "Invalid language specified '%s'. Supported languages are: ", arg );
293     for (p = langNames; *p; p++) fprintf( stderr, "%s ", *p );
294     fprintf( stderr, "\n" );
295     exit(1);
296 }
297
298
299 /***********************************************************************
300  *           MAIN_ParseModeOption
301  *
302  * Parse -mode option.
303  */
304 static void MAIN_ParseModeOption( char *arg )
305 {
306     if (!lstrcmpi32A("enhanced", arg)) Options.mode = MODE_ENHANCED;
307     else if (!lstrcmpi32A("standard", arg)) Options.mode = MODE_STANDARD;
308     else
309     {
310         fprintf(stderr, "Invalid mode '%s' specified.\n", arg);
311         fprintf(stderr, "Valid modes are: 'standard', 'enhanced' (default).\n");
312         exit(1);
313     }
314 }
315
316 /**********************************************************************
317  *           MAIN_ParseVersion
318  */
319 static void MAIN_ParseVersion( char *arg )
320 {
321     /* If you add any other options, 
322        verify the values you return on the real thing */
323     if(strcmp(arg,"win31")==0) 
324     {
325         getVersion16 = 0x06160A03;
326         /* FIXME: My Win32s installation failed to execute the
327            MSVC 4 test program. So check these values */
328         getVersion32 = 0x80000A03;
329         getVersionEx.dwMajorVersion=3;
330         getVersionEx.dwMinorVersion=10;
331         getVersionEx.dwBuildNumber=0;
332         getVersionEx.dwPlatformId=VER_PLATFORM_WIN32s;
333         strcpy(getVersionEx.szCSDVersion,"Win32s 1.3");
334     }
335     else if(strcmp(arg, "win95")==0)
336     {
337         getVersion16 = 0x07005F03;
338         getVersion32 = 0xC0000004;
339         getVersionEx.dwMajorVersion=4;
340         getVersionEx.dwMinorVersion=0;
341         getVersionEx.dwBuildNumber=0x40003B6;
342         getVersionEx.dwPlatformId=VER_PLATFORM_WIN32_WINDOWS;
343         strcpy(getVersionEx.szCSDVersion,"");
344     }
345     else if(strcmp(arg, "nt351")==0)
346     {
347         getVersion16 = 0x05000A03;
348         getVersion32 = 0x04213303;
349         getVersionEx.dwMajorVersion=3;
350         getVersionEx.dwMinorVersion=51;
351         getVersionEx.dwBuildNumber=0x421;
352         getVersionEx.dwPlatformId=VER_PLATFORM_WIN32_NT;
353         strcpy(getVersionEx.szCSDVersion,"Service Pack 2");
354     }
355     else fprintf(stderr, "Unknown winver system code - ignored\n");
356 }
357
358 /***********************************************************************
359  *           MAIN_ParseOptions
360  *
361  * Parse command line options and open display.
362  */
363 static void MAIN_ParseOptions( int *argc, char *argv[] )
364 {
365     char *display_name;
366     XrmValue value;
367     XrmDatabase db = XrmGetFileDatabase("/usr/lib/X11/app-defaults/Wine");
368
369       /* Parse command line */
370     Options.programName = MAIN_GetProgramName( *argc, argv );
371     XrmParseCommand( &db, optionsTable, NB_OPTIONS,
372                      Options.programName, argc, argv );
373
374 #ifdef WINELIB
375     /* Need to assemble command line and pass it to WinMain */
376 #else
377     if (*argc < 2 || lstrcmpi32A(argv[1], "-h") == 0) 
378         MAIN_Usage( argv[0] );
379 #endif
380
381       /* Open display */
382
383     if (MAIN_GetResource( db, ".display", &value )) display_name = value.addr;
384     else display_name = NULL;
385
386     if (!(display = XOpenDisplay( display_name )))
387     {
388         fprintf( stderr, "%s: Can't open display: %s\n",
389                  argv[0], display_name ? display_name : "(none specified)" );
390         exit(1);
391     }
392
393       /* Get all options */
394     if (MAIN_GetResource( db, ".iconic", &value ))
395         Options.cmdShow = SW_SHOWMINIMIZED;
396     if (MAIN_GetResource( db, ".privatemap", &value ))
397         Options.usePrivateMap = TRUE;
398     if (MAIN_GetResource( db, ".fixedmap", &value ))
399         Options.useFixedMap = TRUE;
400     if (MAIN_GetResource( db, ".synchronous", &value ))
401         Options.synchronous = TRUE;
402     if (MAIN_GetResource( db, ".backingstore", &value ))
403         Options.backingstore = TRUE;    
404     if (MAIN_GetResource( db, ".debug", &value ))
405         Options.debug = TRUE;
406     if (MAIN_GetResource( db, ".allowreadonly", &value ))
407         Options.allowReadOnly = TRUE;
408     if (MAIN_GetResource( db, ".ipc", &value ))
409         Options.ipc = TRUE;
410     if (MAIN_GetResource( db, ".depth", &value))
411         screenDepth = atoi( value.addr );
412     if (MAIN_GetResource( db, ".desktop", &value))
413         Options.desktopGeometry = value.addr;
414     if (MAIN_GetResource( db, ".language", &value))
415         MAIN_ParseLanguageOption( (char *)value.addr );
416     if (MAIN_GetResource( db, ".managed", &value))
417         Options.managed = TRUE;
418     if (MAIN_GetResource( db, ".mode", &value))
419         MAIN_ParseModeOption( (char *)value.addr );
420
421 #ifdef DEBUG_RUNTIME
422     if (MAIN_GetResource( db, ".debugoptions", &value))
423         ParseDebugOptions((char*)value.addr);
424 #endif
425     if (MAIN_GetResource( db, ".debugmsg", &value))
426       {
427 #ifndef DEBUG_RUNTIME
428         fprintf(stderr,"%s: Option \"-debugmsg\" not implemented.\n" \
429           "    Recompile with DEBUG_RUNTIME in include/stddebug.h defined.\n",
430           argv[0]);
431         exit(1);
432 #else
433         if (ParseDebugOptions((char*)value.addr)==FALSE)
434           {
435             int i;
436             fprintf(stderr,"%s: Syntax: -debugmsg +xxx,...  or -debugmsg -xxx,...\n",argv[0]);
437             fprintf(stderr,"Example: -debugmsg +all,-heap    turn on all messages except heap messages\n");
438             fprintf(stderr,"Available message types:\n");
439             fprintf(stderr,"%-9s ","all");
440             for(i=0;i<sizeof(debug_msg_enabled)/sizeof(short);i++)
441               if(debug_msg_name[i])
442                 fprintf(stderr,"%-9s%c",debug_msg_name[i],
443                         (((i+2)%8==0)?'\n':' '));
444             fprintf(stderr,"\n\n");
445             exit(1);
446           }
447 #endif
448       }
449
450       if(MAIN_GetResource( db, ".dll", &value))
451       {
452 #ifndef WINELIB
453           if (!BUILTIN_ParseDLLOptions( (char*)value.addr ))
454           {
455               fprintf(stderr,"%s: Syntax: -dll +xxx,... or -dll -xxx,...\n",argv[0]);
456               fprintf(stderr,"Example: -dll -ole2    Do not use emulated OLE2.DLL\n");
457               fprintf(stderr,"Available DLLs:\n");
458               BUILTIN_PrintDLLs();
459               exit(1);
460           }
461 #else
462           fprintf(stderr,"-dll not supported in libwine\n");
463 #endif
464       }
465
466       if(MAIN_GetResource( db, ".winver", &value))
467           MAIN_ParseVersion( (char*)value.addr );
468 }
469
470
471 /***********************************************************************
472  *           MAIN_CreateDesktop
473  */
474 static void MAIN_CreateDesktop( int argc, char *argv[] )
475 {
476     int flags;
477     unsigned int width = 640, height = 480;  /* Default size = 640x480 */
478     char *name = "Wine desktop";
479     XSizeHints *size_hints;
480     XWMHints   *wm_hints;
481     XClassHint *class_hints;
482     XSetWindowAttributes win_attr;
483     XTextProperty window_name;
484     Atom XA_WM_DELETE_WINDOW;
485
486     flags = XParseGeometry( Options.desktopGeometry,
487                             &desktopX, &desktopY, &width, &height );
488     screenWidth  = width;
489     screenHeight = height;
490
491       /* Create window */
492
493     win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
494                          PointerMotionMask | ButtonPressMask |
495                          ButtonReleaseMask | EnterWindowMask | 
496                          StructureNotifyMask;
497     win_attr.cursor = XCreateFontCursor( display, XC_top_left_arrow );
498
499     rootWindow = XCreateWindow( display, DefaultRootWindow(display),
500                                 desktopX, desktopY, width, height, 0,
501                                 CopyFromParent, InputOutput, CopyFromParent,
502                                 CWEventMask | CWCursor, &win_attr );
503
504       /* Set window manager properties */
505
506     size_hints  = XAllocSizeHints();
507     wm_hints    = XAllocWMHints();
508     class_hints = XAllocClassHint();
509     if (!size_hints || !wm_hints || !class_hints)
510     {
511         fprintf( stderr, "Not enough memory for window manager hints.\n" );
512         exit(1);
513     }
514     size_hints->min_width = size_hints->max_width = width;
515     size_hints->min_height = size_hints->max_height = height;
516     size_hints->flags = PMinSize | PMaxSize;
517     if (flags & (XValue | YValue)) size_hints->flags |= USPosition;
518     if (flags & (WidthValue | HeightValue)) size_hints->flags |= USSize;
519     else size_hints->flags |= PSize;
520
521     wm_hints->flags = InputHint | StateHint;
522     wm_hints->input = True;
523     wm_hints->initial_state = NormalState;
524     class_hints->res_name = argv[0];
525     class_hints->res_class = "Wine";
526
527     XStringListToTextProperty( &name, 1, &window_name );
528     XSetWMProperties( display, rootWindow, &window_name, &window_name,
529                       argv, argc, size_hints, wm_hints, class_hints );
530     XA_WM_DELETE_WINDOW = XInternAtom( display, "WM_DELETE_WINDOW", False );
531     XSetWMProtocols( display, rootWindow, &XA_WM_DELETE_WINDOW, 1 );
532     XFree( size_hints );
533     XFree( wm_hints );
534     XFree( class_hints );
535
536       /* Map window */
537
538     XMapWindow( display, rootWindow );
539 }
540
541
542 XKeyboardState keyboard_state;
543
544 /***********************************************************************
545  *           MAIN_SaveSetup
546  */
547 static void MAIN_SaveSetup(void)
548 {
549     XGetKeyboardControl(display, &keyboard_state);
550 }
551
552 /***********************************************************************
553  *           MAIN_RestoreSetup
554  */
555 static void MAIN_RestoreSetup(void)
556 {
557     XKeyboardControl keyboard_value;
558
559     keyboard_value.key_click_percent    = keyboard_state.key_click_percent;
560     keyboard_value.bell_percent         = keyboard_state.bell_percent;
561     keyboard_value.bell_pitch           = keyboard_state.bell_pitch;
562     keyboard_value.bell_duration        = keyboard_state.bell_duration;
563     keyboard_value.auto_repeat_mode     = keyboard_state.global_auto_repeat;
564
565     XChangeKeyboardControl(display, KBKeyClickPercent | KBBellPercent | 
566         KBBellPitch | KBBellDuration | KBAutoRepeatMode, &keyboard_value);
567 }
568
569
570 static void called_at_exit(void)
571 {
572     MAIN_RestoreSetup();
573     WSACleanup();
574 }
575
576 /***********************************************************************
577  *           main
578  */
579 #if defined(WINELIB) && defined(WINELIBDLL)
580 int _wine_main (int argc, char *argv[])
581 #else
582 int main( int argc, char *argv[] )
583 #endif
584 {    
585     int ret_val;
586     int depth_count, i;
587     int *depth_list;
588     struct timeval tv;
589
590     extern int _WinMain(int argc, char **argv);
591
592 #ifdef MALLOC_DEBUGGING
593     char *trace;
594
595     mcheck(NULL);
596     if (!(trace = getenv("MALLOC_TRACE")))
597     {       
598         fprintf( stderr, "MALLOC_TRACE not set. No trace generated\n" );
599     }
600     else
601     {
602         fprintf( stderr, "malloc trace goes to %s\n", trace );
603         mtrace();
604     }
605 #endif
606
607     setbuf(stdout,NULL);
608     setbuf(stderr,NULL);
609
610     setlocale(LC_CTYPE,"");
611     gettimeofday( &tv, NULL);
612     MSG_WineStartTicks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
613
614     XrmInitialize();
615     
616     MAIN_ParseOptions( &argc, argv );
617
618     screen       = DefaultScreenOfDisplay( display );
619     screenWidth  = WidthOfScreen( screen );
620     screenHeight = HeightOfScreen( screen );
621     if (screenDepth)  /* -depth option specified */
622     {
623         depth_list = XListDepths(display,DefaultScreen(display),&depth_count);
624         for (i = 0; i < depth_count; i++)
625             if (depth_list[i] == screenDepth) break;
626         XFree( depth_list );
627         if (i >= depth_count)
628         {
629             fprintf( stderr, "%s: Depth %d not supported on this screen.\n",
630                               Options.programName, screenDepth );
631             exit(1);
632         }
633     }
634     else screenDepth  = DefaultDepthOfScreen( screen );
635     if (Options.synchronous) XSynchronize( display, True );
636     if (Options.desktopGeometry) MAIN_CreateDesktop( argc, argv );
637     else rootWindow = DefaultRootWindow( display );
638
639     MAIN_SaveSetup();
640     atexit(called_at_exit);
641
642     ret_val = _WinMain( argc, argv );
643
644     return ret_val;
645 }
646
647
648 /***********************************************************************
649  *           MessageBeep    (USER.104)
650  */
651 void MessageBeep(WORD i)
652 {
653         XBell(display, 100);
654 }
655
656
657 /***********************************************************************
658  *      GetVersion (KERNEL.3)
659  */
660 LONG GetVersion(void)
661 {
662     if (getVersion16) return getVersion16;
663     return MAKELONG( WINVERSION, WINDOSVER );
664 }
665
666
667 /***********************************************************************
668  *      GetVersion32
669  */
670 LONG GetVersion32(void)
671 {
672     if (getVersion32) return getVersion32;
673     return MAKELONG( 4, DOSVERSION);
674 }
675
676
677 /***********************************************************************
678  *      GetVersionExA
679  */
680 BOOL32 GetVersionEx32A(OSVERSIONINFO32A *v)
681 {
682     if(v->dwOSVersionInfoSize!=sizeof(OSVERSIONINFO32A))
683     {
684         fprintf(stddeb,"wrong OSVERSIONINFO size from app");
685         return FALSE;
686     }
687     if(!getVersion32)
688     {
689         /* Return something like NT 3.5 */
690         v->dwMajorVersion = 3;
691         v->dwMinorVersion = 5;
692         v->dwBuildNumber = 42;
693         v->dwPlatformId = VER_PLATFORM_WIN32_NT;
694         strcpy(v->szCSDVersion, "Wine is not an emulator");
695         return TRUE;
696     }
697     v->dwMajorVersion = getVersionEx.dwMajorVersion;
698     v->dwMinorVersion = getVersionEx.dwMinorVersion;
699     v->dwBuildNumber = getVersionEx.dwBuildNumber;
700     v->dwPlatformId = getVersionEx.dwPlatformId;
701     strcpy(v->szCSDVersion, getVersionEx.szCSDVersion);
702     return TRUE;
703 }
704
705
706 /***********************************************************************
707  *     GetVersionExW
708  */
709 BOOL32 GetVersionEx32W(OSVERSIONINFO32W *v)
710 {
711         OSVERSIONINFO32A v1;
712         if(v->dwOSVersionInfoSize!=sizeof(OSVERSIONINFO32W))
713         {
714                 fprintf(stddeb,"wrong OSVERSIONINFO size from app");
715                 return FALSE;
716         }
717         v1.dwOSVersionInfoSize=sizeof(v1);
718         GetVersionEx32A(&v1);
719         v->dwMajorVersion = v1.dwMajorVersion;
720         v->dwMinorVersion = v1.dwMinorVersion;
721         v->dwBuildNumber = v1.dwBuildNumber;
722         v->dwPlatformId = v1.dwPlatformId;
723         STRING32_AnsiToUni(v->szCSDVersion, v1.szCSDVersion);
724         return TRUE;
725 }
726
727 /***********************************************************************
728  *      GetWinFlags (KERNEL.132)
729  */
730 LONG GetWinFlags(void)
731 {
732   static const long cpuflags[5] =
733     { WF_CPU086, WF_CPU186, WF_CPU286, WF_CPU386, WF_CPU486 };
734
735   long result = 0;
736
737   /* There doesn't seem to be any Pentium flag.  */
738 #ifndef WINELIB
739   long cpuflag = cpuflags[MIN (runtime_cpu (), 4)];
740 #else
741   long cpuflag = cpuflags[4];
742 #endif
743
744   switch(Options.mode) {
745   case MODE_STANDARD:
746     result = (WF_STANDARD | cpuflag | WF_PMODE | WF_80x87);
747     break;
748
749   case MODE_ENHANCED:
750     result = (WF_ENHANCED | cpuflag | WF_PMODE | WF_80x87 | WF_PAGING);
751     break;
752
753   default:
754     fprintf(stderr, "Unknown mode set? This shouldn't happen. Check GetWinFlags()!\n");
755     break;
756   }
757
758   return result;
759 }
760
761 /***********************************************************************
762  *      SetEnvironment (GDI.132)
763  */
764 int SetEnvironment(LPSTR lpPortName, LPSTR lpEnviron, WORD nCount)
765 {
766     LPENVENTRY  lpNewEnv;
767     LPENVENTRY  lpEnv = lpEnvList;
768     dprintf_env(stddeb, "SetEnvironment('%s', '%s', %d) !\n", 
769                 lpPortName, lpEnviron, nCount);
770     if (lpPortName == NULL) return -1;
771     while (lpEnv != NULL) {
772         if (lpEnv->Name != NULL && strcmp(lpEnv->Name, lpPortName) == 0) {
773             if (nCount == 0 || lpEnviron == NULL) {
774                 if (lpEnv->Prev != NULL) lpEnv->Prev->Next = lpEnv->Next;
775                 if (lpEnv->Next != NULL) lpEnv->Next->Prev = lpEnv->Prev;
776                 free(lpEnv->Value);
777                 free(lpEnv->Name);
778                 free(lpEnv);
779                 dprintf_env(stddeb, "SetEnvironment() // entry deleted !\n");
780                 return -1;
781             }
782             free(lpEnv->Value);
783             lpEnv->Value = malloc(nCount);
784             if (lpEnv->Value == NULL) {
785                 dprintf_env(stddeb, "SetEnvironment() // Error allocating entry value !\n");
786                 return 0;
787             }
788             memcpy(lpEnv->Value, lpEnviron, nCount);
789             lpEnv->wSize = nCount;
790             dprintf_env(stddeb, "SetEnvironment() // entry modified !\n");
791             return nCount;
792         }
793         if (lpEnv->Next == NULL) break;
794         lpEnv = lpEnv->Next;
795     }
796     if (nCount == 0 || lpEnviron == NULL) return -1;
797     dprintf_env(stddeb, "SetEnvironment() // new entry !\n");
798     lpNewEnv = malloc(sizeof(ENVENTRY));
799     if (lpNewEnv == NULL) {
800         dprintf_env(stddeb, "SetEnvironment() // Error allocating new entry !\n");
801         return 0;
802     }
803     if (lpEnvList == NULL) {
804         lpEnvList = lpNewEnv;
805         lpNewEnv->Prev = NULL;
806     }
807     else 
808     {
809         lpEnv->Next = lpNewEnv;
810         lpNewEnv->Prev = lpEnv;
811     }
812     lpNewEnv->Next = NULL;
813     lpNewEnv->Name = malloc(strlen(lpPortName) + 1);
814     if (lpNewEnv->Name == NULL) {
815         dprintf_env(stddeb, "SetEnvironment() // Error allocating entry name !\n");
816         return 0;
817     }
818     strcpy(lpNewEnv->Name, lpPortName);
819     lpNewEnv->Value = malloc(nCount);
820     if (lpNewEnv->Value == NULL) {
821         dprintf_env(stddeb, "SetEnvironment() // Error allocating entry value !\n");
822         return 0;
823     }
824     memcpy(lpNewEnv->Value, lpEnviron, nCount);
825     lpNewEnv->wSize = nCount;
826     return nCount;
827 }
828
829 /***********************************************************************
830  *      SetEnvironmentVariableA (KERNEL32.484)
831  */
832 BOOL SetEnvironmentVariableA(LPSTR lpName, LPSTR lpValue)
833 {
834     int rc;
835
836     rc = SetEnvironment(lpName, lpValue, strlen(lpValue) + 1);
837     return (rc > 0) ? 1 : 0;
838 }
839
840 /***********************************************************************
841  *      GetEnvironment (GDI.134)
842  */
843 int GetEnvironment(LPSTR lpPortName, LPSTR lpEnviron, WORD nMaxSiz)
844 {
845     WORD       nCount;
846     LPENVENTRY lpEnv = lpEnvList;
847     dprintf_env(stddeb, "GetEnvironment('%s', '%s', %d) !\n",
848                 lpPortName, lpEnviron, nMaxSiz);
849     while (lpEnv != NULL) {
850         if (lpEnv->Name != NULL && strcmp(lpEnv->Name, lpPortName) == 0) {
851             nCount = MIN(nMaxSiz, lpEnv->wSize);
852             memcpy(lpEnviron, lpEnv->Value, nCount);
853             dprintf_env(stddeb, "GetEnvironment() // found '%s' !\n", lpEnviron);
854             return nCount;
855         }
856         lpEnv = lpEnv->Next;
857     }
858     dprintf_env(stddeb, "GetEnvironment() // not found !\n");
859     return 0;
860 }
861
862 /***********************************************************************
863  *      GetEnvironmentVariableA (KERNEL32.213)
864  */
865 DWORD GetEnvironmentVariableA(LPSTR lpName, LPSTR lpValue, DWORD size)
866 {
867     return GetEnvironment(lpName, lpValue, size);
868 }
869
870 /***********************************************************************
871  *      GetEnvironmentStrings (KERNEL32.210)
872  */
873 LPVOID GetEnvironmentStrings(void)
874 {
875     int count;
876     LPENVENTRY lpEnv;
877     char *envtable, *envptr;
878
879     /* Count the total number of bytes we'll need for the string
880      * table.  Include the trailing nuls and the final double nul.
881      */
882     count = 1;
883     lpEnv = lpEnvList;
884     while(lpEnv != NULL)
885     {
886         if(lpEnv->Name != NULL)
887         {
888             count += strlen(lpEnv->Name) + 1;
889             count += strlen(lpEnv->Value) + 1;
890         }
891         lpEnv = lpEnv->Next;
892     }
893
894     envtable = malloc(count);
895     if(envtable)
896     {
897         lpEnv = lpEnvList;
898         envptr = envtable;
899
900         while(lpEnv != NULL)
901         {
902             if(lpEnv->Name != NULL)
903             {
904                 count = sprintf(envptr, "%s=%s", lpEnv->Name, lpEnv->Value);
905                 envptr += count + 1;
906             }
907             lpEnv = lpEnv->Next;
908         }
909         *envptr = '\0';
910     }
911
912     return envtable;
913 }
914
915
916 LPVOID GetEnvironmentStringsW(void)
917 {
918     int count,len;
919     LPENVENTRY lpEnv;
920     char *envtable, *envptr;
921         WCHAR *wenvtable;
922
923     /* Count the total number of bytes we'll need for the string
924      * table.  Include the trailing nuls and the final double nul.
925      */
926     count = 1;
927     lpEnv = lpEnvList;
928     while(lpEnv != NULL)
929     {
930         if(lpEnv->Name != NULL)
931         {
932             count += strlen(lpEnv->Name) + 1;
933             count += strlen(lpEnv->Value) + 1;
934         }
935         lpEnv = lpEnv->Next;
936     }
937
938         len=count;
939     envtable = malloc(count);
940     if(envtable)
941     {
942         lpEnv = lpEnvList;
943         envptr = envtable;
944
945         while(lpEnv != NULL)
946         {
947             if(lpEnv->Name != NULL)
948             {
949                 count = sprintf(envptr, "%s=%s", lpEnv->Name, lpEnv->Value);
950                 envptr += count + 1;
951             }
952             lpEnv = lpEnv->Next;
953         }
954         *envptr = '\0';
955     }
956
957         wenvtable = malloc(2*len);
958         for(count=0;count<len;count++)
959                 wenvtable[count]=(WCHAR)envtable[count];
960         free(envtable);
961
962     return envtable;
963 }
964
965 void FreeEnvironmentStringsA(void *e)
966 {
967         free(e);
968 }
969
970 void FreeEnvironmentStringsW(void* e)
971 {
972         free(e);
973 }
974
975 /***********************************************************************
976  *      GetTimerResolution (USER.14)
977  */
978 LONG GetTimerResolution(void)
979 {
980         return (1000);
981 }
982
983 /***********************************************************************
984  *      SystemParametersInfo (USER.483)
985  */
986 BOOL SystemParametersInfo (UINT uAction, UINT uParam, LPVOID lpvParam, UINT fuWinIni)
987 {
988         int timeout, temp;
989         char buffer[256];
990         XKeyboardState          keyboard_state;
991         XKeyboardControl        keyboard_value;
992
993
994         fprintf(stderr, "SystemParametersInfo: action %d, param %x, flag %x\n", 
995                         uAction, uParam, fuWinIni);
996
997         switch (uAction) {
998                 case SPI_GETBEEP:
999                         XGetKeyboardControl(display, &keyboard_state);
1000                         if (keyboard_state.bell_percent == 0)
1001                                 *(BOOL *) lpvParam = FALSE;
1002                         else
1003                                 *(BOOL *) lpvParam = TRUE;
1004                         break;
1005                 
1006                 case SPI_GETBORDER:
1007                         *(INT *)lpvParam = GetSystemMetrics( SM_CXFRAME );
1008                         break;
1009
1010                 case SPI_GETFASTTASKSWITCH:
1011                         *(BOOL *) lpvParam = FALSE;
1012                         /* FIXME GetProfileInt( "windows", "CoolSwitch", 1 ) */
1013                         break;
1014
1015                 case SPI_GETGRIDGRANULARITY:
1016                         *(INT *) lpvParam = 1;
1017                 /* FIXME GetProfileInt( "desktop", "GridGranularity", 1 ) */
1018                         break;
1019
1020                 case SPI_GETICONTITLEWRAP:
1021                         *(BOOL *) lpvParam = FALSE;
1022                         /* FIXME GetProfileInt( "desktop", "?", True ) */
1023                         break;
1024
1025                 case SPI_GETKEYBOARDDELAY:
1026                         *(INT *) lpvParam = 1;
1027                         /* FIXME */
1028                         break;
1029
1030                 case SPI_GETKEYBOARDSPEED:
1031                         *(WORD *) lpvParam = 30;
1032                         /* FIXME */
1033                         break;
1034
1035                 case SPI_GETMENUDROPALIGNMENT:
1036                         *(BOOL *) lpvParam = GetSystemMetrics( SM_MENUDROPALIGNMENT ); /* XXX check this */
1037                         break;
1038
1039                 case SPI_GETSCREENSAVEACTIVE:
1040                         /* FIXME GetProfileInt( "windows", "ScreenSaveActive", 1 ); */
1041                         *(BOOL *) lpvParam = FALSE;
1042                         break;
1043
1044                 case SPI_GETSCREENSAVETIMEOUT:
1045                         /* FIXME GetProfileInt( "windows", "ScreenSaveTimeout", 300 ); */
1046                         XGetScreenSaver(display, &timeout, &temp,&temp,&temp);
1047                         *(INT *) lpvParam = timeout * 1000;
1048                         break;
1049
1050                 case SPI_ICONHORIZONTALSPACING:
1051                         if (lpvParam == NULL)
1052                                 fprintf(stderr, "SystemParametersInfo: Horizontal icon spacing set to %d\n.", uParam);
1053                         else
1054                                 *(INT *) lpvParam = GetSystemMetrics( SM_CXICONSPACING );
1055                         break;
1056
1057                 case SPI_ICONVERTICALSPACING:
1058                         if (lpvParam == NULL)
1059                                 fprintf(stderr, "SystemParametersInfo: Vertical icon spacing set to %d\n.", uParam);
1060                         else
1061                                 *(INT *) lpvParam = GetSystemMetrics( SM_CYICONSPACING );
1062                         break;
1063
1064                 case SPI_SETBEEP:
1065                         if (uParam == TRUE)
1066                                 keyboard_value.bell_percent = -1;
1067                         else
1068                                 keyboard_value.bell_percent = 0;                        
1069                         XChangeKeyboardControl(display, KBBellPercent, 
1070                                                         &keyboard_value);
1071                         break;
1072
1073                 case SPI_SETSCREENSAVEACTIVE:
1074                         if (uParam == TRUE)
1075                                 XActivateScreenSaver(display);
1076                         else
1077                                 XResetScreenSaver(display);
1078                         break;
1079
1080                 case SPI_SETSCREENSAVETIMEOUT:
1081                         XSetScreenSaver(display, uParam, 60, DefaultBlanking, 
1082                                                 DefaultExposures);
1083                         break;
1084
1085                 case SPI_SETDESKWALLPAPER:
1086                         return (SetDeskWallPaper((LPSTR) lpvParam));
1087                         break;
1088
1089                 case SPI_SETDESKPATTERN:
1090                         if ((INT) uParam == -1) {
1091                                 GetProfileString("Desktop", "Pattern", 
1092                                                 "170 85 170 85 170 85 170 85", 
1093                                                 buffer, sizeof(buffer) );
1094                                 return (DESKTOP_SetPattern((LPSTR) buffer));
1095                         } else
1096                                 return (DESKTOP_SetPattern((LPSTR) lpvParam));
1097                         break;
1098
1099                 case SPI_GETICONTITLELOGFONT: 
1100                 {
1101                     /* FIXME GetProfileString( "?", "?", "?" ) */
1102                   LPLOGFONT16 lpLogFont = (LPLOGFONT16)lpvParam;
1103                   lpLogFont->lfHeight = 10;
1104                   lpLogFont->lfWidth = 0;
1105                   lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
1106                   lpLogFont->lfWeight = FW_NORMAL;
1107                   lpLogFont->lfItalic = lpLogFont->lfStrikeOut = lpLogFont->lfUnderline = FALSE;
1108                   lpLogFont->lfCharSet = ANSI_CHARSET;
1109                   lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1110                   lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1111                   lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
1112                   break;
1113                 }
1114                 case SPI_LANGDRIVER:
1115                 case SPI_SETBORDER:
1116                 case SPI_SETDOUBLECLKHEIGHT:
1117                 case SPI_SETDOUBLECLICKTIME:
1118                 case SPI_SETDOUBLECLKWIDTH:
1119                 case SPI_SETFASTTASKSWITCH:
1120                 case SPI_SETKEYBOARDDELAY:
1121                 case SPI_SETKEYBOARDSPEED:
1122                         fprintf(stderr, "SystemParametersInfo: option %d ignored.\n", uParam);
1123                         break;
1124
1125                 default:
1126                         fprintf(stderr, "SystemParametersInfo: unknown option %d.\n", uParam);
1127                         break;
1128         }
1129         return 1;
1130 }
1131
1132 /***********************************************************************
1133 *       COPY (GDI.250)
1134 */
1135 void Copy(LPVOID lpSource, LPVOID lpDest, WORD nBytes)
1136 {
1137         memcpy(lpDest, lpSource, nBytes);
1138 }
1139
1140 /***********************************************************************
1141 *       SWAPMOUSEBUTTON (USER.186)
1142 */
1143 BOOL SwapMouseButton(BOOL fSwap)
1144 {
1145         return 0;       /* don't swap */
1146 }
1147
1148 /***********************************************************************
1149 *       FileCDR (KERNEL.130)
1150 */
1151 void FileCDR(FARPROC x)
1152 {
1153         printf("FileCDR(%8x)\n", (int) x);
1154 }
1155
1156 /***********************************************************************
1157 *       GetWinDebugInfo (KERNEL.355)
1158 */
1159 BOOL GetWinDebugInfo(WINDEBUGINFO *lpwdi, UINT flags)
1160 {
1161         printf("GetWinDebugInfo(%8lx,%d) stub returning 0\n", (unsigned long)lpwdi, flags);
1162         /* 0 means not in debugging mode/version */
1163         /* Can this type of debugging be used in wine ? */
1164         /* Constants: WDI_OPTIONS WDI_FILTER WDI_ALLOCBREAK */
1165         return 0;
1166 }
1167
1168 /***********************************************************************
1169 *       GetWinDebugInfo (KERNEL.355)
1170 */
1171 BOOL SetWinDebugInfo(WINDEBUGINFO *lpwdi)
1172 {
1173         printf("SetWinDebugInfo(%8lx) stub returning 0\n", (unsigned long)lpwdi);
1174         /* 0 means not in debugging mode/version */
1175         /* Can this type of debugging be used in wine ? */
1176         /* Constants: WDI_OPTIONS WDI_FILTER WDI_ALLOCBREAK */
1177         return 0;
1178 }