1 /*
2 ===========================================================================
3 Copyright (C) 1997-2006 Id Software, Inc.
4
5 This file is part of Quake 2 Tools source code.
6
7 Quake 2 Tools source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Quake 2 Tools source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Quake 2 Tools source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
21 */
22
23 //*************************************************************
24 // File name: mru.c
25 //
26 // Description:
27 //
28 // Routines for MRU support
29 //
30 // Development Team:
31 //
32 // Gilles Vollant (100144.2636@compuserve.com)
33 //
34 //*************************************************************
35
36 #include <windows.h>
37 #include <windowsx.h>
38 #include <string.h>
39
40 #include "mru.h"
41 // CreateMruMenu : MRUMENU constructor
42 // wNbLruShowInit : nb of item showed in menu
43 // wNbLruMenuInit : nb of item stored in memory
44 // wMaxSizeLruItemInit : size max. of filename
45
46
47 //*************************************************************
48 //
49 // CreateMruMenu()
50 //
51 // Purpose:
52 //
53 // Allocate and Initialize an MRU and return a pointer on it
54 //
55 //
56 // Parameters:
57 //
58 // WORD wNbLruShowInit - Maximum number of item displayed on menu
59 // WORD wNbLruMenuInit - Maximum number of item stored in memory
60 // WORD wMaxSizeLruItemInit - Maximum size of an item (ie size of pathname)
61 // WORD wIdMruInit - ID of the first item in the menu (default:IDMRU)
62 //
63 //
64 // Return: (LPMRUMENU)
65 //
66 // Pointer on a MRUMENU structure, used by other function
67 //
68 //
69 // Comments:
70 // wNbLruShowInit <= wNbLruMenuInit
71 //
72 //
73 // History: Date Author Comment
74 // 09/24/94 G. Vollant Created
75 //
76 //*************************************************************
77
CreateMruMenu(WORD wNbLruShowInit,WORD wNbLruMenuInit,WORD wMaxSizeLruItemInit,WORD wIdMruInit)78 LPMRUMENU CreateMruMenu (WORD wNbLruShowInit,
79 WORD wNbLruMenuInit,WORD wMaxSizeLruItemInit,WORD wIdMruInit)
80 {
81 LPMRUMENU lpMruMenu;
82 lpMruMenu = (LPMRUMENU)GlobalAllocPtr(GHND,sizeof(MRUMENU));
83
84 lpMruMenu->wNbItemFill = 0;
85 lpMruMenu->wNbLruMenu = wNbLruMenuInit;
86 lpMruMenu->wNbLruShow = wNbLruShowInit;
87 lpMruMenu->wIdMru = wIdMruInit;
88 lpMruMenu->wMaxSizeLruItem = wMaxSizeLruItemInit;
89 lpMruMenu->lpMRU = (LPSTR)GlobalAllocPtr(GHND,
90 lpMruMenu->wNbLruMenu*(UINT)lpMruMenu->wMaxSizeLruItem);
91 if (lpMruMenu->lpMRU == NULL)
92 {
93 GlobalFreePtr(lpMruMenu);
94 lpMruMenu = NULL;
95 }
96 return lpMruMenu;
97 }
98
99 //*************************************************************
100 //
101 // CreateMruMenuDefault()
102 //
103 // Purpose:
104 //
105 // Allocate and Initialize an MRU and return a pointer on it
106 // Use default parameter
107 //
108 //
109 // Parameters:
110 //
111 //
112 // Return: (LPMRUMENU)
113 //
114 // Pointer on a MRUMENU structure, used by other function
115 //
116 //
117 // Comments:
118 //
119 //
120 // History: Date Author Comment
121 // 09/24/94 G. Vollant Created
122 //
123 //*************************************************************
124
CreateMruMenuDefault()125 LPMRUMENU CreateMruMenuDefault()
126 {
127 return CreateMruMenu (NBMRUMENUSHOW,NBMRUMENU,MAXSIZEMRUITEM,IDMRU);
128 }
129
130
131 //*************************************************************
132 //
133 // DeleteMruMenu()
134 //
135 // Purpose:
136 // Destructor :
137 // Clean and free a MRUMENU structure
138 //
139 // Parameters:
140 //
141 // LPMRUMENU lpMruMenu - pointer on MRUMENU, allocated
142 // by CreateMruMenu() or CreateMruMenuDefault()
143 //
144 //
145 // Return: void
146 //
147 //
148 // Comments:
149 //
150 //
151 // History: Date Author Comment
152 // 09/24/94 G. Vollant Created
153 //
154 //*************************************************************
DeleteMruMenu(LPMRUMENU lpMruMenu)155 void DeleteMruMenu(LPMRUMENU lpMruMenu)
156 {
157 GlobalFreePtr(lpMruMenu->lpMRU);
158 GlobalFreePtr(lpMruMenu);
159 }
160
161 //*************************************************************
162 //
163 // SetNbLruShow()
164 //
165 // Purpose:
166 // Change the maximum number of item displayed on menu
167 //
168 // Parameters:
169 // LPMRUMENU lpMruMenu - pointer on MRUMENU
170 // WORD wNbLruShowInit - Maximum number of item displayed on menu
171 //
172 //
173 // Return: void
174 //
175 //
176 // Comments:
177 //
178 //
179 // History: Date Author Comment
180 // 09/24/94 G. Vollant Created
181 //
182 //*************************************************************
SetNbLruShow(LPMRUMENU lpMruMenu,WORD wNbLruShowInit)183 void SetNbLruShow (LPMRUMENU lpMruMenu,WORD wNbLruShowInit)
184 {
185 lpMruMenu->wNbLruShow = min(wNbLruShowInit,lpMruMenu->wNbLruMenu);
186 }
187
188 //*************************************************************
189 //
190 // SetMenuItem()
191 //
192 // Purpose:
193 // Set the filename of an item
194 //
195 // Parameters:
196 // LPMRUMENU lpMruMenu - pointer on MRUMENU
197 // WORD wItem - Number of Item to set, zero based
198 // LPSTR lpItem - String, contain the filename of the item
199 //
200 //
201 // Return: (BOOL)
202 // TRUE - Function run successfully
203 // FALSE - Function don't run successfully
204 //
205 //
206 // Comments:
207 // used when load .INI or reg database
208 //
209 // History: Date Author Comment
210 // 09/24/94 G. Vollant Created
211 //
212 //*************************************************************
SetMenuItem(LPMRUMENU lpMruMenu,WORD wItem,LPSTR lpItem)213 BOOL SetMenuItem (LPMRUMENU lpMruMenu,WORD wItem,LPSTR lpItem)
214 {
215 if (wItem >= NBMRUMENU)
216 return FALSE;
217 _fstrncpy((lpMruMenu->lpMRU) +
218 ((lpMruMenu->wMaxSizeLruItem) * (UINT)wItem),
219 lpItem,lpMruMenu->wMaxSizeLruItem-1);
220 lpMruMenu->wNbItemFill = max(lpMruMenu->wNbItemFill,wItem+1);
221 return TRUE;
222 }
223
224 //*************************************************************
225 //
226 // GetMenuItem()
227 //
228 // Purpose:
229 // Get the filename of an item
230 //
231 // Parameters:
232 // LPMRUMENU lpMruMenu - pointer on MRUMENU
233 // WORD wItem - Number of Item to set, zero based
234 // BOOL fIDMBased - TRUE : wItem is based on ID menu item
235 // FALSE : wItem is zero-based
236 // LPSTR lpItem - String where the filename of the item will be
237 // stored by GetMenuItem()
238 // UINT uiSize - Size of the lpItem buffer
239 //
240 //
241 // Return: (BOOL)
242 // TRUE - Function run successfully
243 // FALSE - Function don't run successfully
244 //
245 //
246 // Comments:
247 // Used for saving in .INI or reg database, or when user select
248 // an MRU in File menu
249 //
250 // History: Date Author Comment
251 // 09/24/94 G. Vollant Created
252 //
253 //*************************************************************
GetMenuItem(LPMRUMENU lpMruMenu,WORD wItem,BOOL fIDMBased,LPSTR lpItem,UINT uiSize)254 BOOL GetMenuItem (LPMRUMENU lpMruMenu,WORD wItem,
255 BOOL fIDMBased,LPSTR lpItem,UINT uiSize)
256 {
257 if (fIDMBased)
258 wItem -= (lpMruMenu->wIdMru + 1);
259 if (wItem >= lpMruMenu->wNbItemFill)
260 return FALSE;
261 _fstrncpy(lpItem,(lpMruMenu->lpMRU) +
262 ((lpMruMenu->wMaxSizeLruItem) * (UINT)(wItem)),uiSize);
263 *(lpItem+uiSize-1) = '\0';
264 return TRUE;
265 }
266
267 //*************************************************************
268 //
269 // AddNewItem()
270 //
271 // Purpose:
272 // Add an item at the begin of the list
273 //
274 // Parameters:
275 // LPMRUMENU lpMruMenu - pointer on MRUMENU
276 // LPSTR lpItem - String contain the filename to add
277 //
278 // Return: (BOOL)
279 // TRUE - Function run successfully
280 // FALSE - Function don't run successfully
281 //
282 //
283 // Comments:
284 // Used when used open a file (using File Open common
285 // dialog, Drag and drop or MRU)
286 //
287 // History: Date Author Comment
288 // 09/24/94 G. Vollant Created
289 //
290 //*************************************************************
AddNewItem(LPMRUMENU lpMruMenu,LPSTR lpItem)291 void AddNewItem (LPMRUMENU lpMruMenu,LPSTR lpItem)
292 {
293 WORD i,j;
294 for (i=0;i<lpMruMenu->wNbItemFill;i++)
295 if (lstrcmpi(lpItem,(lpMruMenu->lpMRU) +
296 ((lpMruMenu->wMaxSizeLruItem) * (UINT)i)) == 0)
297 {
298 // Shift the other items
299 for (j=i;j>0;j--)
300 lstrcpy((lpMruMenu->lpMRU) + (lpMruMenu->wMaxSizeLruItem * (UINT)j),
301 (lpMruMenu->lpMRU) + (lpMruMenu->wMaxSizeLruItem * (UINT)(j-1)));
302 _fstrncpy(lpMruMenu->lpMRU,lpItem,lpMruMenu->wMaxSizeLruItem-1);
303 return ;
304 }
305 lpMruMenu->wNbItemFill = min(lpMruMenu->wNbItemFill+1,lpMruMenu->wNbLruMenu);
306 for (i=lpMruMenu->wNbItemFill-1;i>0;i--)
307 lstrcpy(lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)i),
308 lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)(i-1)));
309 _fstrncpy(lpMruMenu->lpMRU,lpItem,lpMruMenu->wMaxSizeLruItem-1);
310 }
311
312 //*************************************************************
313 //
314 // DelMenuItem()
315 //
316 // Purpose:
317 // Delete an item
318 //
319 // Parameters:
320 // LPMRUMENU lpMruMenu - pointer on MRUMENU
321 // WORD wItem - Number of Item to set, zero based
322 // BOOL fIDMBased - TRUE : wItem is based on ID menu item
323 // FALSE : wItem is zero-based
324 //
325 // Return: (BOOL)
326 // TRUE - Function run successfully
327 // FALSE - Function don't run successfully
328 //
329 //
330 // Comments:
331 // Used when used open a file, using MRU, and when an error
332 // occured (by example, when file was deleted)
333 //
334 // History: Date Author Comment
335 // 09/24/94 G. Vollant Created
336 //
337 //*************************************************************
DelMenuItem(LPMRUMENU lpMruMenu,WORD wItem,BOOL fIDMBased)338 BOOL DelMenuItem(LPMRUMENU lpMruMenu,WORD wItem,BOOL fIDMBased)
339 {
340 WORD i;
341 if (fIDMBased)
342 wItem -= (lpMruMenu->wIdMru + 1);
343 if (lpMruMenu->wNbItemFill <= wItem)
344 return FALSE;
345 lpMruMenu->wNbItemFill--;
346 for (i=wItem;i<lpMruMenu->wNbItemFill;i++)
347 lstrcpy(lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)i),
348 lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)(i+1)));
349 return TRUE;
350 }
351
352 //*************************************************************
353 //
354 // PlaceMenuMRUItem()
355 //
356 // Purpose:
357 // Add MRU at the end of a menu
358 //
359 // Parameters:
360 // LPMRUMENU lpMruMenu - pointer on MRUMENU
361 // HMENU hMenu - Handle of menu where MRU must be added
362 // UINT uiItem - Item of menu entry where MRU must be added
363 //
364 // Return: void
365 //
366 //
367 // Comments:
368 // Used MRU is modified, for refresh the File menu
369 //
370 // History: Date Author Comment
371 // 09/24/94 G. Vollant Created
372 //
373 //*************************************************************
PlaceMenuMRUItem(LPMRUMENU lpMruMenu,HMENU hMenu,UINT uiItem)374 void PlaceMenuMRUItem(LPMRUMENU lpMruMenu,HMENU hMenu,UINT uiItem)
375 {
376 int i;
377 WORD wNbShow;
378 if (hMenu == NULL)
379 return;
380 // remove old MRU in menu
381 for (i=0;i<=(int)(lpMruMenu->wNbLruMenu);i++)
382 RemoveMenu(hMenu,i+lpMruMenu->wIdMru,MF_BYCOMMAND);
383
384 if (lpMruMenu->wNbItemFill == 0)
385 return;
386
387 // If they are item, insert a separator before the files
388 InsertMenu(hMenu,uiItem,MF_SEPARATOR,lpMruMenu->wIdMru,NULL);
389
390 wNbShow = min(lpMruMenu->wNbItemFill,lpMruMenu->wNbLruShow);
391 for (i=(int)wNbShow-1;i>=0;i--)
392 {
393 LPSTR lpTxt;
394 if (lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20))
395 {
396 wsprintf(lpTxt,"&%lu %s",
397 (DWORD)(i+1),lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem*(UINT)i));
398 InsertMenu(hMenu,(((WORD)i)!=(wNbShow-1)) ? (lpMruMenu->wIdMru+i+2) : lpMruMenu->wIdMru,
399 MF_STRING,lpMruMenu->wIdMru+i+1,lpTxt);
400 GlobalFreePtr(lpTxt);
401 }
402 }
403
404 }
405
406 ///////////////////////////////////////////
407
408
409
410 //*************************************************************
411 //
412 // SaveMruInIni()
413 //
414 // Purpose:
415 // Save MRU in a private .INI
416 //
417 // Parameters:
418 // LPMRUMENU lpMruMenu - pointer on MRUMENU
419 // LPSTR lpszSection - Points to a null-terminated string containing
420 // the name of the section
421 // LPSTR lpszFile - Points to a null-terminated string that names
422 // the initialization file.
423 //
424 // Return: (BOOL)
425 // TRUE - Function run successfully
426 // FALSE - Function don't run successfully
427 //
428 //
429 // Comments:
430 // See WritePrivateProfileString API for more info on lpszSection and lpszFile
431 //
432 // History: Date Author Comment
433 // 09/24/94 G. Vollant Created
434 //
435 //*************************************************************
SaveMruInIni(LPMRUMENU lpMruMenu,LPSTR lpszSection,LPSTR lpszFile)436 BOOL SaveMruInIni(LPMRUMENU lpMruMenu,LPSTR lpszSection,LPSTR lpszFile)
437 {
438 LPSTR lpTxt;
439 WORD i;
440
441 lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20);
442 if (lpTxt == NULL)
443 return FALSE;
444
445 for (i=0;i<lpMruMenu->wNbLruMenu;i++)
446 {
447 char szEntry[16];
448 wsprintf(szEntry,"File%lu",(DWORD)i+1);
449 if (!GetMenuItem(lpMruMenu,i,FALSE,lpTxt,lpMruMenu->wMaxSizeLruItem + 10))
450 *lpTxt = '\0';
451 WritePrivateProfileString(lpszSection,szEntry,lpTxt,lpszFile);
452 }
453 GlobalFreePtr(lpTxt);
454 WritePrivateProfileString(NULL,NULL,NULL,lpszFile); // flush cache
455 return TRUE;
456 }
457
458
459 //*************************************************************
460 //
461 // LoadMruInIni()
462 //
463 // Purpose:
464 // Load MRU from a private .INI
465 //
466 // Parameters:
467 // LPMRUMENU lpMruMenu - pointer on MRUMENU
468 // LPSTR lpszSection - Points to a null-terminated string containing
469 // the name of the section
470 // LPSTR lpszFile - Points to a null-terminated string that names
471 // the initialization file.
472 //
473 // Return: (BOOL)
474 // TRUE - Function run successfully
475 // FALSE - Function don't run successfully
476 //
477 //
478 // Comments:
479 // See GetPrivateProfileString API for more info on lpszSection and lpszFile
480 //
481 // History: Date Author Comment
482 // 09/24/94 G. Vollant Created
483 //
484 //*************************************************************
LoadMruInIni(LPMRUMENU lpMruMenu,LPSTR lpszSection,LPSTR lpszFile)485 BOOL LoadMruInIni(LPMRUMENU lpMruMenu,LPSTR lpszSection,LPSTR lpszFile)
486 {
487 LPSTR lpTxt;
488 WORD i;
489 lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20);
490 if (lpTxt == NULL)
491 return FALSE;
492
493 for (i=0;i<lpMruMenu->wNbLruMenu;i++)
494 {
495 char szEntry[16];
496
497 wsprintf(szEntry,"File%lu",(DWORD)i+1);
498 GetPrivateProfileString(lpszSection,szEntry,"",lpTxt,
499 lpMruMenu->wMaxSizeLruItem + 10,lpszFile);
500 if (*lpTxt == '\0')
501 break;
502 SetMenuItem(lpMruMenu,i,lpTxt);
503 }
504 GlobalFreePtr(lpTxt);
505 return TRUE;
506 }
507
508 #ifdef WIN32
509
IsWin395OrHigher(void)510 BOOL IsWin395OrHigher(void)
511 {
512 WORD wVer;
513
514 wVer = LOWORD(GetVersion());
515 wVer = (((WORD)LOBYTE(wVer)) << 8) | (WORD)HIBYTE(wVer);
516
517 return (wVer >= 0x035F); // 5F = 95 dec
518 }
519
520
521 //*************************************************************
522 //
523 // SaveMruInReg()
524 //
525 // Purpose:
526 // Save MRU in the registry
527 //
528 // Parameters:
529 // LPMRUMENU lpMruMenu - pointer on MRUMENU
530 // LPSTR lpszKey - Points to a null-terminated string
531 // specifying the name of a key that
532 // this function opens or creates.
533 //
534 // Return: (BOOL)
535 // TRUE - Function run successfully
536 // FALSE - Function don't run successfully
537 //
538 //
539 // Comments:
540 // Win32 function designed for Windows NT and Windows 95
541 // See RegCreateKeyEx API for more info on lpszKey
542 //
543 // History: Date Author Comment
544 // 09/24/94 G. Vollant Created
545 //
546 //*************************************************************
SaveMruInReg(LPMRUMENU lpMruMenu,LPSTR lpszKey)547 BOOL SaveMruInReg(LPMRUMENU lpMruMenu,LPSTR lpszKey)
548 {
549 LPSTR lpTxt;
550 WORD i;
551 HKEY hCurKey;
552 DWORD dwDisp;
553
554 lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20);
555 if (lpTxt == NULL)
556 return FALSE;
557
558 RegCreateKeyEx(HKEY_CURRENT_USER,lpszKey,0,NULL,
559 REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hCurKey,&dwDisp);
560
561 for (i=0;i<lpMruMenu->wNbLruMenu;i++)
562 {
563 char szEntry[16];
564 wsprintf(szEntry,"File%lu",(DWORD)i+1);
565 if (!GetMenuItem(lpMruMenu,i,FALSE,lpTxt,lpMruMenu->wMaxSizeLruItem + 10))
566 *lpTxt = '\0';
567 RegSetValueEx(hCurKey,szEntry,0,REG_SZ,lpTxt,lstrlen(lpTxt));
568 }
569 RegCloseKey(hCurKey);
570 GlobalFreePtr(lpTxt);
571 return TRUE;
572 }
573
574 //*************************************************************
575 //
576 // LoadMruInReg()
577 //
578 // Purpose:
579 // Load MRU from the registry
580 //
581 // Parameters:
582 // LPMRUMENU lpMruMenu - pointer on MRUMENU
583 // LPSTR lpszKey - Points to a null-terminated string
584 // specifying the name of a key that
585 // this function opens or creates.
586 //
587 // Return: (BOOL)
588 // TRUE - Function run successfully
589 // FALSE - Function don't run successfully
590 //
591 //
592 // Comments:
593 // Win32 function designed for Windows NT and Windows 95
594 // See RegOpenKeyEx API for more info on lpszKey
595 //
596 // History: Date Author Comment
597 // 09/24/94 G. Vollant Created
598 //
599 //*************************************************************
LoadMruInReg(LPMRUMENU lpMruMenu,LPSTR lpszKey)600 BOOL LoadMruInReg(LPMRUMENU lpMruMenu,LPSTR lpszKey)
601 {
602 LPSTR lpTxt;
603 WORD i;
604 HKEY hCurKey;
605 DWORD dwType;
606 lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20);
607 if (lpTxt == NULL)
608 return FALSE;
609
610 RegOpenKeyEx(HKEY_CURRENT_USER,lpszKey,0,KEY_READ,&hCurKey);
611
612
613 for (i=0;i<lpMruMenu->wNbLruMenu;i++)
614 {
615 char szEntry[16];
616 DWORD dwSizeBuf;
617 wsprintf(szEntry,"File%lu",(DWORD)i+1);
618 *lpTxt = '\0';
619 dwSizeBuf = lpMruMenu->wMaxSizeLruItem + 10;
620 RegQueryValueEx(hCurKey,szEntry,NULL,&dwType,(LPBYTE)lpTxt,&dwSizeBuf);
621 *(lpTxt+dwSizeBuf)='\0';
622 if (*lpTxt == '\0')
623 break;
624 SetMenuItem(lpMruMenu,i,lpTxt);
625 }
626 RegCloseKey(hCurKey);
627 GlobalFreePtr(lpTxt);
628 return TRUE;
629 }
630
631
632 //*************************************************************
633 //
634 // GetWin32Kind()
635 //
636 // Purpose:
637 // Get the Win32 platform
638 //
639 // Parameters:
640 //
641 // Return: (WIN32KIND)
642 // WINNT - Run under Windows NT
643 // WIN32S - Run under Windows 3.1x + Win32s
644 // WIN95ORGREATHER - Run under Windows 95
645 //
646 //
647 // Comments:
648 // Win32 function designed for Windows NT and Windows 95
649 // See RegOpenKeyEx API for more info on lpszKey
650 //
651 // History: Date Author Comment
652 // 09/24/94 G. Vollant Created
653 //
654 //*************************************************************
GetWin32Kind()655 WIN32KIND GetWin32Kind()
656 {
657 BOOL IsWin395OrHigher(void);
658
659 WORD wVer;
660
661 if ((GetVersion() & 0x80000000) == 0)
662 return WINNT;
663 wVer = LOWORD(GetVersion());
664 wVer = (((WORD)LOBYTE(wVer)) << 8) | (WORD)HIBYTE(wVer);
665
666 if (wVer >= 0x035F)
667 return WIN95ORGREATHER;
668 else
669 return WIN32S;
670 }
671 #endif
672