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