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