Import my Hybrid-CD stuff from last year.
[reactos.git] / reactos / base / setup / vmwinst / vmwinst.c
1 /*
2 * ReactOS VMware(r) driver installation utility
3 * Copyright (C) 2004 ReactOS Team
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * VMware is a registered trademark of VMware, Inc.
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS VMware(r) driver installation utility
23 * FILE: subsys/system/vmwinst/vmwinst.c
24 * PROGRAMMERS: Thomas Weidenmueller (w3seek@users.sourceforge.net)
25 * Klemens Friedl (frik85@hotmail.com)
26 */
27 #include <windows.h>
28 #include <commctrl.h>
29 #include <newdev.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <pseh/pseh2.h>
33 #include "vmwinst.h"
34 #include <debug.h>
35
36 extern VOID CALLBACK InstallHinfSectionW(HWND hwnd, HINSTANCE ModuleHandle,
37 PCWSTR CmdLineBuffer, INT nCmdShow);
38
39
40 HINSTANCE hAppInstance;
41 BOOL StartVMwConfigWizard, DriverFilesFound, ActivateVBE = FALSE, UninstallDriver = FALSE;
42
43 static WCHAR DestinationDriversPath[MAX_PATH+1];
44 static WCHAR CDDrive = L'\0';
45 static WCHAR PathToVideoDrivers60[MAX_PATH+1] = L"X:\\program files\\VMWare\\VMWare Tools\\Drivers\\video\\2k\\32bit\\";
46 static WCHAR PathToVideoDrivers55[MAX_PATH+1] = L"X:\\program files\\VMware\\VMware Tools\\Drivers\\video\\winnt2k\\32Bit\\";
47 static WCHAR PathToVideoDrivers45[MAX_PATH+1] = L"X:\\program files\\VMware\\VMware Tools\\Drivers\\video\\winnt2k\\";
48 static WCHAR PathToVideoDrivers40[MAX_PATH+1] = L"X:\\video\\winnt2k\\";
49 static WCHAR DestinationPath[MAX_PATH+1];
50 static WCHAR *vmx_fb = L"vmx_fb.dll";
51 static WCHAR *vmx_mode = L"vmx_mode.dll";
52 static WCHAR *vmx_mode_v6 = L"vmx mode.dll";
53 static WCHAR *vmx_svga = L"vmx_svga.sys";
54
55 static WCHAR *SrcPath = PathToVideoDrivers45;
56
57 static HANDLE hInstallationThread = NULL;
58 static HWND hInstallationNotifyWnd = NULL;
59 static LONG AbortInstall = 0;
60 #define WM_INSTABORT (WM_USER + 2)
61 #define WM_INSTCOMPLETE (WM_USER + 3)
62 #define WM_INSTSTATUSUPDATE (WM_USER + 4)
63
64 /* Helper functions */
65 BOOL
66 DetectVMware(int *Version)
67 {
68 int magic, ver;
69
70 magic = 0;
71 ver = 0;
72
73 _SEH2_TRY
74 {
75 /* Try using a VMware I/O port. If not running in VMware this'll throw an
76 exception! */
77 #if defined(__GNUC__)
78 __asm__ __volatile__("inl %%dx, %%eax"
79 : "=a" (ver), "=b" (magic)
80 : "0" (0x564d5868), "d" (0x5658), "c" (0xa));
81 #elif defined(_MSC_VER)
82 __asm
83 {
84 push ebx
85 mov ecx, 0xa
86 mov edx, 0x5658
87 mov eax, 0x564d5868
88 in eax, dx
89 mov [ver], eax
90 mov [magic], ebx
91 pop ebx
92 }
93 #else
94 #error TODO
95 #endif
96 }
97 _SEH2_EXCEPT(_SEH2_GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
98 {
99 return FALSE;
100 }
101 _SEH2_END;
102
103 if(magic == 0x564d5868)
104 {
105 *Version = ver;
106 return TRUE;
107 }
108
109 return FALSE;
110 }
111
112 /* try to open the file */
113 static BOOL
114 DoesFileExist(WCHAR *Path, WCHAR *File)
115 {
116 WCHAR FileName[MAX_PATH + 1];
117 HANDLE FileHandle;
118
119 FileName[0] = L'\0';
120 wcscat(FileName, Path);
121 wcscat(FileName, File);
122
123 FileHandle = CreateFile(FileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
124
125 if(FileHandle == INVALID_HANDLE_VALUE)
126 {
127 /* If it was a sharing violation the file must already exist */
128 return GetLastError() == ERROR_SHARING_VIOLATION;
129 }
130
131 if(GetFileSize(FileHandle, NULL) <= 0)
132 {
133 CloseHandle(FileHandle);
134 return FALSE;
135 }
136
137 CloseHandle(FileHandle);
138 return TRUE;
139 }
140
141 static VOID
142 CenterWindow(HWND hWnd)
143 {
144 HWND hWndParent;
145 RECT rcParent;
146 RECT rcWindow;
147
148 hWndParent = GetParent(hWnd);
149 if (hWndParent == NULL)
150 hWndParent = GetDesktopWindow();
151
152 GetWindowRect(hWndParent, &rcParent);
153 GetWindowRect(hWnd, &rcWindow);
154
155 SetWindowPos(hWnd,
156 HWND_TOP,
157 ((rcParent.right - rcParent.left) - (rcWindow.right - rcWindow.left)) / 2,
158 ((rcParent.bottom - rcParent.top) - (rcWindow.bottom - rcWindow.top)) / 2,
159 0,
160 0,
161 SWP_NOSIZE);
162 }
163
164
165 /* Find the drive with the inserted VMware cd-rom */
166 static BOOL
167 IsVMwareCDInDrive(WCHAR *Drv)
168 {
169 static WCHAR Drive[4] = L"X:\\";
170 WCHAR Current;
171
172 *Drv = L'\0';
173 for(Current = 'C'; Current <= 'Z'; Current++)
174 {
175 Drive[0] = Current;
176 #if CHECKDRIVETYPE
177 if(GetDriveType(Drive) == DRIVE_CDROM)
178 {
179 #endif
180 PathToVideoDrivers60[0] = Current;
181 PathToVideoDrivers55[0] = Current;
182 PathToVideoDrivers40[0] = Current;
183 PathToVideoDrivers45[0] = Current;
184 if(SetCurrentDirectory(PathToVideoDrivers60))
185 SrcPath = PathToVideoDrivers60;
186 else if(SetCurrentDirectory(PathToVideoDrivers55))
187 SrcPath = PathToVideoDrivers55;
188 else if(SetCurrentDirectory(PathToVideoDrivers45))
189 SrcPath = PathToVideoDrivers45;
190 else if(SetCurrentDirectory(PathToVideoDrivers40))
191 SrcPath = PathToVideoDrivers40;
192 else
193 {
194 SetCurrentDirectory(DestinationPath);
195 continue;
196 }
197
198 if(DoesFileExist(SrcPath, vmx_fb) &&
199 (DoesFileExist(SrcPath, vmx_mode) || DoesFileExist(SrcPath, vmx_mode_v6)) &&
200 DoesFileExist(SrcPath, vmx_svga))
201 {
202 *Drv = Current;
203 return TRUE;
204 }
205 #if CHECKDRIVETYPE
206 }
207 #endif
208 }
209
210 return FALSE;
211 }
212
213 static BOOL
214 LoadResolutionSettings(DWORD *ResX, DWORD *ResY, DWORD *ColDepth)
215 {
216 HKEY hReg;
217 DWORD Type, Size = sizeof(DWORD);
218
219 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
220 L"SYSTEM\\CurrentControlSet\\Services\\vmx_svga\\Device0",
221 0, KEY_QUERY_VALUE, &hReg) != ERROR_SUCCESS)
222 {
223 DEVMODE CurrentDevMode;
224
225 /* If this key is absent, just get current settings */
226 memset(&CurrentDevMode, 0, sizeof(CurrentDevMode));
227 CurrentDevMode.dmSize = sizeof(CurrentDevMode);
228 if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &CurrentDevMode) == TRUE)
229 {
230 *ColDepth = CurrentDevMode.dmBitsPerPel;
231 *ResX = CurrentDevMode.dmPelsWidth;
232 *ResY = CurrentDevMode.dmPelsHeight;
233
234 return TRUE;
235 }
236 }
237
238 if(RegQueryValueEx(hReg, L"DefaultSettings.BitsPerPel", 0, &Type, (BYTE*)ColDepth, &Size) != ERROR_SUCCESS ||
239 Type != REG_DWORD)
240 {
241 *ColDepth = 8;
242 Size = sizeof(DWORD);
243 }
244
245 if(RegQueryValueEx(hReg, L"DefaultSettings.XResolution", 0, &Type, (BYTE*)ResX, &Size) != ERROR_SUCCESS ||
246 Type != REG_DWORD)
247 {
248 *ResX = 640;
249 Size = sizeof(DWORD);
250 }
251
252 if(RegQueryValueEx(hReg, L"DefaultSettings.YResolution", 0, &Type, (BYTE*)ResY, &Size) != ERROR_SUCCESS ||
253 Type != REG_DWORD)
254 {
255 *ResY = 480;
256 }
257
258 RegCloseKey(hReg);
259 return TRUE;
260 }
261
262 static BOOL
263 IsVmwSVGAEnabled(VOID)
264 {
265 HKEY hReg;
266 DWORD Type, Size, Value;
267
268 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
269 L"SYSTEM\\CurrentControlSet\\Services\\vmx_svga",
270 0, KEY_QUERY_VALUE, &hReg) != ERROR_SUCCESS)
271 {
272 return FALSE;
273 }
274 Size = sizeof(DWORD);
275 if(RegQueryValueEx(hReg, L"Start", 0, &Type, (BYTE*)&Value, &Size) != ERROR_SUCCESS ||
276 Type != REG_DWORD)
277 {
278 RegCloseKey(hReg);
279 return FALSE;
280 }
281
282 RegCloseKey(hReg);
283 return (Value == 1);
284 }
285
286
287
288 static BOOL
289 SaveResolutionSettings(DWORD ResX, DWORD ResY, DWORD ColDepth)
290 {
291 HKEY hReg;
292 DWORD VFreq = 85;
293
294 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
295 L"SYSTEM\\CurrentControlSet\\Services\\vmx_svga\\Device0",
296 0, KEY_SET_VALUE, &hReg) != ERROR_SUCCESS)
297 {
298 return FALSE;
299 }
300 if(RegSetValueEx(hReg, L"DefaultSettings.BitsPerPel", 0, REG_DWORD, (BYTE*)&ColDepth, sizeof(DWORD)) != ERROR_SUCCESS)
301 {
302 RegCloseKey(hReg);
303 return FALSE;
304 }
305
306 if(RegSetValueEx(hReg, L"DefaultSettings.XResolution", 0, REG_DWORD, (BYTE*)&ResX, sizeof(DWORD)) != ERROR_SUCCESS)
307 {
308 RegCloseKey(hReg);
309 return FALSE;
310 }
311
312 if(RegSetValueEx(hReg, L"DefaultSettings.YResolution", 0, REG_DWORD, (BYTE*)&ResY, sizeof(DWORD)) != ERROR_SUCCESS)
313 {
314 RegCloseKey(hReg);
315 return FALSE;
316 }
317
318 if(RegSetValueEx(hReg, L"DefaultSettings.VRefresh", 0, REG_DWORD, (BYTE*)&VFreq, sizeof(DWORD)) != ERROR_SUCCESS)
319 {
320 RegCloseKey(hReg);
321 return FALSE;
322 }
323
324 RegCloseKey(hReg);
325 return TRUE;
326 }
327
328 static BOOL
329 EnableDriver(WCHAR *Key, BOOL Enable)
330 {
331 DWORD Value;
332 HKEY hReg;
333
334 Value = (Enable ? 1 : 4);
335
336 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, Key, 0, KEY_SET_VALUE, &hReg) != ERROR_SUCCESS)
337 {
338 return FALSE;
339 }
340 if(RegSetValueEx(hReg, L"Start", 0, REG_DWORD, (BYTE*)&Value, sizeof(DWORD)) != ERROR_SUCCESS)
341 {
342 RegCloseKey(hReg);
343 return FALSE;
344 }
345
346 RegCloseKey(hReg);
347 return TRUE;
348 }
349
350 /* Activate the vmware driver and deactivate the others */
351 static BOOL
352 EnableVmwareDriver(BOOL VBE, BOOL VGA, BOOL VMX)
353 {
354 if(!EnableDriver(L"SYSTEM\\CurrentControlSet\\Services\\VBE", VBE))
355 {
356 return FALSE;
357 }
358 if(!EnableDriver(L"SYSTEM\\CurrentControlSet\\Services\\vga", VGA))
359 {
360 return FALSE;
361 }
362 if(!EnableDriver(L"SYSTEM\\CurrentControlSet\\Services\\vmx_svga", VMX))
363 {
364 return FALSE;
365 }
366
367 return TRUE;
368 }
369
370 /* GUI */
371
372
373 /* Property page dialog callback */
374 static INT_PTR CALLBACK
375 PageWelcomeProc(
376 HWND hwndDlg,
377 UINT uMsg,
378 WPARAM wParam,
379 LPARAM lParam
380 )
381 {
382 LPNMHDR pnmh = (LPNMHDR)lParam;
383 switch(uMsg)
384 {
385 case WM_NOTIFY:
386 {
387 HWND hwndControl;
388
389 /* Center the wizard window */
390 hwndControl = GetParent(hwndDlg);
391 CenterWindow (hwndControl);
392
393 switch(pnmh->code)
394 {
395 case PSN_SETACTIVE:
396 {
397 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
398 break;
399 }
400 case PSN_WIZNEXT:
401 {
402 if(DriverFilesFound)
403 {
404 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, IDD_CONFIG);
405 return TRUE;
406 }
407 break;
408 }
409 }
410 break;
411 }
412 }
413 return FALSE;
414 }
415
416 /* Property page dialog callback */
417 static INT_PTR CALLBACK
418 PageInsertDiscProc(
419 HWND hwndDlg,
420 UINT uMsg,
421 WPARAM wParam,
422 LPARAM lParam
423 )
424 {
425 switch(uMsg)
426 {
427 case WM_NOTIFY:
428 {
429 LPNMHDR pnmh = (LPNMHDR)lParam;
430 switch(pnmh->code)
431 {
432 case PSN_SETACTIVE:
433 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
434 break;
435 case PSN_WIZNEXT:
436 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, IDD_INSTALLING_VMWARE_TOOLS);
437 break;
438 }
439 break;
440 }
441 }
442 return FALSE;
443 }
444
445 static VOID
446 InstTerminateInstaller(BOOL Wait)
447 {
448 if(hInstallationThread != NULL)
449 {
450 if(Wait)
451 {
452 InterlockedExchange((LONG*)&AbortInstall, 2);
453 WaitForSingleObject(hInstallationThread, INFINITE);
454 }
455 else
456 {
457 InterlockedExchange((LONG*)&AbortInstall, 1);
458 }
459 }
460 }
461
462 static DWORD WINAPI
463 InstInstallationThread(LPVOID lpParameter)
464 {
465 HANDLE hThread;
466 WCHAR InfFileName[1024];
467 BOOL DriveAvailable;
468 int DrivesTested = 0;
469
470 if(AbortInstall != 0) goto done;
471 PostMessage(hInstallationNotifyWnd, WM_INSTSTATUSUPDATE, IDS_SEARCHINGFORCDROM, 0);
472
473 while(AbortInstall == 0)
474 {
475 Sleep(500);
476 DriveAvailable = IsVMwareCDInDrive(&CDDrive);
477 if(DriveAvailable)
478 break;
479 if(DrivesTested++ > 20)
480 {
481 PostMessage(hInstallationNotifyWnd, WM_INSTABORT, IDS_FAILEDTOLOCATEDRIVERS, 0);
482 goto cleanup;
483 }
484 }
485
486 if(AbortInstall != 0) goto done;
487 PostMessage(hInstallationNotifyWnd, WM_INSTSTATUSUPDATE, IDS_COPYINGFILES, 0);
488
489 wcscpy(InfFileName, SrcPath);
490 wcscat(InfFileName, L"vmx_svga.inf");
491 DPRINT1("Calling UpdateDriverForPlugAndPlayDevices()\n");
492 if (!UpdateDriverForPlugAndPlayDevices(
493 hInstallationNotifyWnd,
494 L"PCI\\VEN_15AD&DEV_0405&SUBSYS_040515AD&REV_00",
495 InfFileName,
496 0,
497 NULL))
498 {
499 AbortInstall = 1;
500 }
501 else
502 {
503 AbortInstall = 0;
504 }
505
506 done:
507 switch(AbortInstall)
508 {
509 case 0:
510 SendMessage(hInstallationNotifyWnd, WM_INSTCOMPLETE, 0, 0);
511 break;
512 case 1:
513 SendMessage(hInstallationNotifyWnd, WM_INSTABORT, 0, 0);
514 break;
515 }
516
517 cleanup:
518 hThread = InterlockedExchangePointer((PVOID*)&hInstallationThread, 0);
519 if(hThread != NULL)
520 {
521 CloseHandle(hThread);
522 }
523 return 0;
524 }
525
526 static BOOL
527 InstStartInstallationThread(HWND hwndNotify)
528 {
529 if(hInstallationThread == NULL)
530 {
531 DWORD ThreadId;
532 hInstallationNotifyWnd = hwndNotify;
533 AbortInstall = 0;
534 hInstallationThread = CreateThread(NULL,
535 0,
536 InstInstallationThread,
537 NULL,
538 CREATE_SUSPENDED,
539 &ThreadId);
540 if(hInstallationThread == NULL)
541 {
542 return FALSE;
543 }
544
545 ResumeThread(hInstallationThread);
546 return TRUE;
547 }
548
549 return FALSE;
550 }
551
552 /* Property page dialog callback */
553 static INT_PTR CALLBACK
554 PageInstallingProc(
555 HWND hwndDlg,
556 UINT uMsg,
557 WPARAM wParam,
558 LPARAM lParam
559 )
560 {
561 switch(uMsg)
562 {
563 case WM_NOTIFY:
564 {
565 LPNMHDR pnmh = (LPNMHDR)lParam;
566 switch(pnmh->code)
567 {
568 case PSN_SETACTIVE:
569 SetDlgItemText(hwndDlg, IDC_INSTALLINGSTATUS, L"");
570 SendDlgItemMessage(hwndDlg, IDC_INSTALLINGPROGRESS, PBM_SETMARQUEE, TRUE, 50);
571 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK);
572 InstStartInstallationThread(hwndDlg);
573 break;
574 case PSN_RESET:
575 InstTerminateInstaller(TRUE);
576 break;
577 case PSN_WIZBACK:
578 if(hInstallationThread != NULL)
579 {
580 PropSheet_SetWizButtons(GetParent(hwndDlg), 0);
581 InstTerminateInstaller(FALSE);
582 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, -1);
583 return -1;
584 }
585 else
586 {
587 SendDlgItemMessage(hwndDlg, IDC_INSTALLINGPROGRESS, PBM_SETMARQUEE, FALSE, 0);
588 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, IDD_INSERT_VMWARE_TOOLS);
589 }
590 break;
591 }
592 break;
593 }
594 case WM_INSTABORT:
595 /* go back in case we aborted the installation thread */
596 SendDlgItemMessage(hwndDlg, IDC_INSTALLINGPROGRESS, PBM_SETMARQUEE, FALSE, 0);
597 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_INSERT_VMWARE_TOOLS);
598 if(wParam != 0)
599 {
600 WCHAR Msg[1024];
601 LoadString(hAppInstance, wParam, Msg, sizeof(Msg) / sizeof(WCHAR));
602 MessageBox(GetParent(hwndDlg), Msg, NULL, MB_ICONWARNING);
603 }
604 break;
605 case WM_INSTCOMPLETE:
606 SendDlgItemMessage(hwndDlg, IDC_INSTALLINGPROGRESS, PBM_SETMARQUEE, FALSE, 0);
607 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
608 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_CONFIG);
609 break;
610 case WM_INSTSTATUSUPDATE:
611 {
612 WCHAR Msg[1024];
613 LoadString(hAppInstance, wParam, Msg, sizeof(Msg) / sizeof(WCHAR));
614 SetDlgItemText(hwndDlg, IDC_INSTALLINGSTATUS, Msg);
615 break;
616 }
617 }
618 return FALSE;
619 }
620
621 /* Property page dialog callback */
622 static INT_PTR CALLBACK
623 PageInstallFailedProc(
624 HWND hwndDlg,
625 UINT uMsg,
626 WPARAM wParam,
627 LPARAM lParam
628 )
629 {
630 switch(uMsg)
631 {
632 case WM_NOTIFY:
633 {
634 LPNMHDR pnmh = (LPNMHDR)lParam;
635 switch(pnmh->code)
636 {
637 case PSN_SETACTIVE:
638 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH);
639 break;
640 }
641 break;
642 }
643 }
644 return FALSE;
645 }
646
647 static void
648 FillComboBox(HWND Dlg, int idComboBox, int From, int To)
649 {
650 int i;
651 WCHAR Text[256];
652
653 for(i = From; i <= To; i++)
654 {
655 if(LoadString(hAppInstance, i, Text, 255) > 0)
656 {
657 SendDlgItemMessage(Dlg, idComboBox, CB_ADDSTRING, 0, (LPARAM)Text);
658 }
659 }
660 }
661
662 typedef struct
663 {
664 int ControlID;
665 int ResX;
666 int ResY;
667 } MAPCTLRES;
668
669 /* Property page dialog callback */
670 static INT_PTR CALLBACK
671 PageConfigProc(
672 HWND hwndDlg,
673 UINT uMsg,
674 WPARAM wParam,
675 LPARAM lParam
676 )
677 {
678 LPNMHDR pnmh = (LPNMHDR)lParam;
679 switch(uMsg)
680 {
681 case WM_INITDIALOG:
682 {
683 DWORD ResX = 0, ResY = 0, ColDepth = 0;
684 int cbSel;
685
686 FillComboBox(hwndDlg, IDC_COLORQUALITY, 10001, 10003);
687 if(LoadResolutionSettings(&ResX, &ResY, &ColDepth))
688 {
689 SendDlgItemMessage(hwndDlg, ResX + ResY, BM_SETCHECK, BST_CHECKED, 0);
690 switch(ColDepth)
691 {
692 case 8:
693 cbSel = 0;
694 break;
695 case 16:
696 cbSel = 1;
697 break;
698 case 32:
699 cbSel = 2;
700 break;
701 default:
702 cbSel = -1;
703 break;
704 }
705 SendDlgItemMessage(hwndDlg, IDC_COLORQUALITY, CB_SETCURSEL, cbSel, 0);
706 }
707 break;
708 }
709 case WM_NOTIFY:
710 {
711 HWND hwndControl;
712
713 /* Center the wizard window */
714 hwndControl = GetParent(hwndDlg);
715 CenterWindow (hwndControl);
716
717 switch(pnmh->code)
718 {
719 case PSN_SETACTIVE:
720 {
721 PropSheet_SetWizButtons(GetParent(hwndDlg), ((StartVMwConfigWizard || DriverFilesFound) ? PSWIZB_FINISH | PSWIZB_BACK : PSWIZB_FINISH));
722 break;
723 }
724 case PSN_WIZBACK:
725 {
726 if(StartVMwConfigWizard)
727 {
728 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, IDD_CHOOSEACTION);
729 return TRUE;
730 }
731 if(DriverFilesFound)
732 {
733 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, IDD_WELCOMEPAGE);
734 return TRUE;
735 }
736 break;
737 }
738 case PSN_WIZFINISH:
739 {
740 DWORD rx = 800, ry = 600, cd = 32;
741 int i;
742 static MAPCTLRES Resolutions[11] = {
743 {540, 640, 480},
744 {1400, 800, 600},
745 {1792, 1024, 768},
746 {2016, 1152, 864},
747 {2240, 1280, 960},
748 {2304, 1280, 1024},
749 {2450, 1400, 1050},
750 {2800, 1600, 1200},
751 {3136, 1792, 1344},
752 {3248, 1856, 1392},
753 {3360, 1920, 1440}
754 };
755 for(i = 0; i < 11; i++)
756 {
757 if(SendDlgItemMessage(hwndDlg, Resolutions[i].ControlID, BM_GETCHECK, 0, 0) == BST_CHECKED)
758 {
759 rx = Resolutions[i].ResX;
760 ry = Resolutions[i].ResY;
761 break;
762 }
763 }
764
765 switch(SendDlgItemMessage(hwndDlg, IDC_COLORQUALITY, CB_GETCURSEL, 0, 0))
766 {
767 case 0:
768 cd = 8;
769 break;
770 case 1:
771 cd = 16;
772 break;
773 case 2:
774 cd = 32;
775 break;
776 }
777
778 SaveResolutionSettings(rx, ry, cd);
779 break;
780 }
781 }
782 break;
783 }
784 }
785 return FALSE;
786 }
787
788 /* Property page dialog callback */
789 static INT_PTR CALLBACK
790 PageChooseActionProc(
791 HWND hwndDlg,
792 UINT uMsg,
793 WPARAM wParam,
794 LPARAM lParam
795 )
796 {
797 switch(uMsg)
798 {
799 case WM_INITDIALOG:
800 SendDlgItemMessage(hwndDlg, IDC_CONFIGSETTINGS, BM_SETCHECK, BST_CHECKED, 0);
801 break;
802 case WM_NOTIFY:
803 {
804 LPNMHDR pnmh = (LPNMHDR)lParam;
805 switch(pnmh->code)
806 {
807 case PSN_SETACTIVE:
808 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
809 break;
810 case PSN_WIZBACK:
811 {
812 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, IDD_CHOOSEACTION);
813 return TRUE;
814 }
815 case PSN_WIZNEXT:
816 {
817 static ULONG SelPage[4] = {IDD_CONFIG, IDD_SELECTDRIVER, IDD_SELECTDRIVER, IDD_CHOOSEACTION};
818 int i;
819
820 for(i = IDC_CONFIGSETTINGS; i <= IDC_UNINSTALL; i++)
821 {
822 if(SendDlgItemMessage(hwndDlg, i, BM_GETCHECK, 0, 0) == BST_CHECKED)
823 {
824 break;
825 }
826 }
827
828 UninstallDriver = (i == IDC_UNINSTALL);
829
830 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, SelPage[i - IDC_CONFIGSETTINGS]);
831 return TRUE;
832 }
833 }
834 break;
835 }
836 }
837 return FALSE;
838 }
839
840 /* Property page dialog callback */
841 static INT_PTR CALLBACK
842 PageSelectDriverProc(
843 HWND hwndDlg,
844 UINT uMsg,
845 WPARAM wParam,
846 LPARAM lParam
847 )
848 {
849 switch(uMsg)
850 {
851 case WM_INITDIALOG:
852 SendDlgItemMessage(hwndDlg, IDC_VBE, BM_SETCHECK, BST_CHECKED, 0);
853 break;
854 case WM_NOTIFY:
855 {
856 LPNMHDR pnmh = (LPNMHDR)lParam;
857 switch(pnmh->code)
858 {
859 case PSN_SETACTIVE:
860 PropSheet_SetWizButtons(GetParent(hwndDlg), (UninstallDriver ? PSWIZB_NEXT | PSWIZB_BACK : PSWIZB_BACK | PSWIZB_FINISH));
861 break;
862 case PSN_WIZBACK:
863 {
864 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, IDD_CHOOSEACTION);
865 return TRUE;
866 }
867 case PSN_WIZNEXT:
868 {
869 ActivateVBE = (SendDlgItemMessage(hwndDlg, IDC_VBE, BM_GETCHECK, 0, 0) == BST_CHECKED);
870
871 if(UninstallDriver)
872 {
873 return FALSE;
874 }
875 return TRUE;
876 }
877 case PSN_WIZFINISH:
878 {
879 if(UninstallDriver)
880 {
881 return FALSE;
882 }
883 ActivateVBE = (SendDlgItemMessage(hwndDlg, IDC_VBE, BM_GETCHECK, 0, 0) == BST_CHECKED);
884 if(!EnableVmwareDriver(ActivateVBE,
885 TRUE,
886 FALSE))
887 {
888 WCHAR Msg[1024];
889 LoadString(hAppInstance, (ActivateVBE ? IDS_FAILEDTOSELVBEDRIVER : IDS_FAILEDTOSELVGADRIVER), Msg, sizeof(Msg) / sizeof(WCHAR));
890 MessageBox(GetParent(hwndDlg), Msg, NULL, MB_ICONWARNING);
891 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, IDD_SELECTDRIVER);
892 return TRUE;
893 }
894 break;
895 }
896 }
897 break;
898 }
899 }
900 return FALSE;
901 }
902
903 static VOID
904 ShowUninstNotice(HWND Owner)
905 {
906 WCHAR Msg[1024];
907 LoadString(hAppInstance, IDS_UNINSTNOTICE, Msg, sizeof(Msg) / sizeof(WCHAR));
908 MessageBox(Owner, Msg, NULL, MB_ICONINFORMATION);
909 }
910
911 static INT_PTR CALLBACK
912 PageDoUninstallProc(
913 HWND hwndDlg,
914 UINT uMsg,
915 WPARAM wParam,
916 LPARAM lParam
917 )
918 {
919 switch(uMsg)
920 {
921 case WM_NOTIFY:
922 {
923 LPNMHDR pnmh = (LPNMHDR)lParam;
924 switch(pnmh->code)
925 {
926 case PSN_SETACTIVE:
927 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_FINISH);
928 break;
929 case PSN_WIZFINISH:
930 {
931 if(UninstallDriver)
932 {
933 if(!EnableVmwareDriver(ActivateVBE,
934 TRUE,
935 FALSE))
936 {
937 WCHAR Msg[1024];
938 LoadString(hAppInstance, (ActivateVBE ? IDS_FAILEDTOSELVBEDRIVER : IDS_FAILEDTOSELVGADRIVER), Msg, sizeof(Msg) / sizeof(WCHAR));
939 MessageBox(GetParent(hwndDlg), Msg, NULL, MB_ICONWARNING);
940 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, IDD_SELECTDRIVER);
941 return TRUE;
942 }
943 ShowUninstNotice(GetParent(hwndDlg));
944 }
945 return FALSE;
946 }
947 }
948 break;
949 }
950 }
951 return FALSE;
952 }
953
954 static LONG
955 CreateWizard(VOID)
956 {
957 PROPSHEETHEADER psh;
958 HPROPSHEETPAGE ahpsp[8];
959 PROPSHEETPAGE psp;
960 WCHAR Caption[1024];
961
962 LoadString(hAppInstance, IDS_WIZARD_NAME, Caption, sizeof(Caption) / sizeof(TCHAR));
963
964 /* Create the Welcome page */
965 ZeroMemory (&psp, sizeof(PROPSHEETPAGE));
966 psp.dwSize = sizeof(PROPSHEETPAGE);
967 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
968 psp.hInstance = hAppInstance;
969 psp.pfnDlgProc = PageWelcomeProc;
970 psp.pszTemplate = MAKEINTRESOURCE(IDD_WELCOMEPAGE);
971 ahpsp[0] = CreatePropertySheetPage(&psp);
972
973 /* Create the INSERT_VMWARE_TOOLS page */
974 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
975 psp.pszHeaderTitle = MAKEINTRESOURCE(IDD_INSERT_VMWARE_TOOLSTITLE);
976 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDD_INSERT_VMWARE_TOOLSSUBTITLE);
977 psp.pszTemplate = MAKEINTRESOURCE(IDD_INSERT_VMWARE_TOOLS);
978 psp.pfnDlgProc = PageInsertDiscProc;
979 ahpsp[1] = CreatePropertySheetPage(&psp);
980
981 /* Create the INSTALLING_VMWARE_TOOLS page */
982 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
983 psp.pszHeaderTitle = MAKEINTRESOURCE(IDD_INSTALLING_VMWARE_TOOLSTITLE);
984 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDD_INSTALLING_VMWARE_TOOLSSUBTITLE);
985 psp.pszTemplate = MAKEINTRESOURCE(IDD_INSTALLING_VMWARE_TOOLS);
986 psp.pfnDlgProc = PageInstallingProc;
987 ahpsp[2] = CreatePropertySheetPage(&psp);
988
989 /* Create the CONFIG page */
990 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
991 psp.pszHeaderTitle = MAKEINTRESOURCE(IDD_CONFIGTITLE);
992 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDD_CONFIGSUBTITLE);
993 psp.pfnDlgProc = PageConfigProc;
994 psp.pszTemplate = MAKEINTRESOURCE(IDD_CONFIG);
995 ahpsp[3] = CreatePropertySheetPage(&psp);
996
997 /* Create the INSTALLATION_FAILED page */
998 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
999 psp.pszHeaderTitle = MAKEINTRESOURCE(IDD_INSTALLATION_FAILEDTITLE);
1000 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDD_INSTALLATION_FAILEDSUBTITLE);
1001 psp.pfnDlgProc = PageInstallFailedProc;
1002 psp.pszTemplate = MAKEINTRESOURCE(IDD_INSTALLATION_FAILED);
1003 ahpsp[4] = CreatePropertySheetPage(&psp);
1004
1005 /* Create the CHOOSEACTION page */
1006 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1007 psp.pszHeaderTitle = MAKEINTRESOURCE(IDD_CHOOSEACTIONTITLE);
1008 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDD_CHOOSEACTIONSUBTITLE);
1009 psp.pfnDlgProc = PageChooseActionProc;
1010 psp.pszTemplate = MAKEINTRESOURCE(IDD_CHOOSEACTION);
1011 ahpsp[5] = CreatePropertySheetPage(&psp);
1012
1013 /* Create the SELECTDRIVER page */
1014 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1015 psp.pszHeaderTitle = MAKEINTRESOURCE(IDD_SELECTDRIVERTITLE);
1016 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDD_SELECTDRIVERSUBTITLE);
1017 psp.pfnDlgProc = PageSelectDriverProc;
1018 psp.pszTemplate = MAKEINTRESOURCE(IDD_SELECTDRIVER);
1019 ahpsp[6] = CreatePropertySheetPage(&psp);
1020
1021 /* Create the DOUNINSTALL page */
1022 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1023 psp.pszHeaderTitle = MAKEINTRESOURCE(IDD_DOUNINSTALLTITLE);
1024 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDD_DOUNINSTALLSUBTITLE);
1025 psp.pfnDlgProc = PageDoUninstallProc;
1026 psp.pszTemplate = MAKEINTRESOURCE(IDD_DOUNINSTALL);
1027 ahpsp[7] = CreatePropertySheetPage(&psp);
1028
1029 /* Create the property sheet */
1030 psh.dwSize = sizeof(PROPSHEETHEADER);
1031 psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
1032 psh.hInstance = hAppInstance;
1033 psh.hwndParent = NULL;
1034 psh.nPages = 7;
1035 psh.nStartPage = (StartVMwConfigWizard ? 5 : 0);
1036 psh.phpage = ahpsp;
1037 psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
1038 psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER);
1039
1040 /* Display the wizard */
1041 return (LONG)(PropertySheet(&psh) != -1);
1042 }
1043
1044 int WINAPI
1045 wWinMain(HINSTANCE hInstance,
1046 HINSTANCE hPrevInstance,
1047 LPWSTR lpszCmdLine,
1048 int nCmdShow)
1049 {
1050
1051 int Version;
1052 WCHAR *lc;
1053
1054 hAppInstance = hInstance;
1055
1056 if(!DetectVMware(&Version))
1057 {
1058 return 1;
1059 }
1060
1061 lc = DestinationPath;
1062 lc += GetSystemDirectory(DestinationPath, MAX_PATH) - 1;
1063 if(lc >= DestinationPath && *lc != L'\\')
1064 {
1065 wcscat(DestinationPath, L"\\");
1066 }
1067 DestinationDriversPath[0] = L'\0';
1068 wcscat(DestinationDriversPath, DestinationPath);
1069 wcscat(DestinationDriversPath, L"drivers\\");
1070
1071 SetCurrentDirectory(DestinationPath);
1072
1073 DriverFilesFound = DoesFileExist(DestinationPath, vmx_fb) &&
1074 DoesFileExist(DestinationPath, vmx_mode) &&
1075 DoesFileExist(DestinationDriversPath, vmx_svga);
1076
1077 StartVMwConfigWizard = DriverFilesFound && IsVmwSVGAEnabled();
1078
1079 /* Show the wizard */
1080 CreateWizard();
1081
1082 return 2;
1083 }
1084