f31d141d5ede7b48606a8615c8809d85df469967
[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 if(!AddVmwareRegistryEntries())
507 {
508 WCHAR Msg[1024];
509 LoadString(hAppInstance, IDS_FAILEDTOADDREGENTRIES, Msg, sizeof(Msg) / sizeof(WCHAR));
510 MessageBox(GetParent(hwndDlg), Msg, NULL, MB_ICONWARNING);
511 SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_WELCOMEPAGE);
512 return TRUE;
513 }
514 if(!EnableVmwareDriver(TRUE, TRUE, TRUE))
515 {
516
517 WCHAR Msg[1024];
518 LoadString(hAppInstance, IDS_FAILEDTOACTIVATEDRIVER, Msg, sizeof(Msg) / sizeof(WCHAR));
519 MessageBox(GetParent(hwndDlg), Msg, NULL, MB_ICONWARNING);
520 SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_WELCOMEPAGE);
521 return TRUE;
522 }
523 SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_CONFIG);
524 return TRUE;
525 }
526 break;
527 }
528 }
529 break;
530 }
531 }
532 return FALSE;
533 }
534
535 /* Property page dialog callback */
536 INT_PTR CALLBACK
537 PageInsertDiscProc(
538 HWND hwndDlg,
539 UINT uMsg,
540 WPARAM wParam,
541 LPARAM lParam
542 )
543 {
544 switch(uMsg)
545 {
546 case WM_NOTIFY:
547 {
548 LPNMHDR pnmh = (LPNMHDR)lParam;
549 switch(pnmh->code)
550 {
551 case PSN_SETACTIVE:
552 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
553 break;
554 case PSN_WIZNEXT:
555 SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_INSTALLING_VMWARE_TOOLS);
556 break;
557 }
558 break;
559 }
560 }
561 return FALSE;
562 }
563
564 VOID
565 InstTerminateInstaller(BOOL Wait)
566 {
567 if(hInstallationThread != NULL)
568 {
569 if(Wait)
570 {
571 InterlockedExchange((LONG*)&AbortInstall, 2);
572 WaitForSingleObject(hInstallationThread, INFINITE);
573 }
574 else
575 {
576 InterlockedExchange((LONG*)&AbortInstall, 1);
577 }
578 }
579 }
580
581 DWORD STDCALL
582 InstInstallationThread(LPVOID lpParameter)
583 {
584 HANDLE hThread;
585 BOOL DriveAvailable;
586 int DrivesTested = 0;
587
588 if(AbortInstall != 0) goto done;
589 PostMessage(hInstallationNotifyWnd, WM_INSTSTATUSUPDATE, IDS_SEARCHINGFORCDROM, 0);
590
591 while(AbortInstall == 0)
592 {
593 Sleep(500);
594 DriveAvailable = IsVMwareCDInDrive(&CDDrive);
595 if(DriveAvailable)
596 break;
597 if(DrivesTested++ > 20)
598 {
599 PostMessage(hInstallationNotifyWnd, WM_INSTABORT, IDS_FAILEDTOLOCATEDRIVERS, 0);
600 goto cleanup;
601 }
602 }
603
604 if(AbortInstall != 0) goto done;
605 PostMessage(hInstallationNotifyWnd, WM_INSTSTATUSUPDATE, IDS_COPYINGFILES, 0);
606
607 if(AbortInstall != 0) goto done;
608 if(!InstallFile(DestinationPath, vmx_fb))
609 {
610 PostMessage(hInstallationNotifyWnd, WM_INSTABORT, IDS_FAILEDTOCOPYFILES, 0);
611 goto cleanup;
612 }
613
614 Sleep(250);
615
616 if(AbortInstall != 0) goto done;
617 if(!InstallFile(DestinationPath, vmx_mode))
618 {
619 PostMessage(hInstallationNotifyWnd, WM_INSTABORT, IDS_FAILEDTOCOPYFILES, 0);
620 goto cleanup;
621 }
622
623 Sleep(250);
624
625 if(AbortInstall != 0) goto done;
626 if(!InstallFile(DestinationDriversPath, vmx_svga))
627 {
628 PostMessage(hInstallationNotifyWnd, WM_INSTABORT, IDS_FAILEDTOCOPYFILES, 0);
629 goto cleanup;
630 }
631
632 Sleep(250);
633
634 if(AbortInstall != 0) goto done;
635 PostMessage(hInstallationNotifyWnd, WM_INSTSTATUSUPDATE, IDS_ENABLINGDRIVER, 0);
636 if(!EnableVmwareDriver(TRUE, TRUE, TRUE))
637 {
638 PostMessage(hInstallationNotifyWnd, WM_INSTABORT, IDS_FAILEDTOACTIVATEDRIVER, 0);
639 goto cleanup;
640 }
641
642 Sleep(500);
643
644 done:
645 switch(AbortInstall)
646 {
647 case 0:
648 SendMessage(hInstallationNotifyWnd, WM_INSTCOMPLETE, 0, 0);
649 break;
650 case 1:
651 SendMessage(hInstallationNotifyWnd, WM_INSTABORT, 0, 0);
652 break;
653 }
654
655 cleanup:
656 hThread = (HANDLE)InterlockedExchange((LONG*)&hInstallationThread, 0);
657 if(hThread != NULL)
658 {
659 CloseHandle(hThread);
660 }
661 return 0;
662 }
663
664 BOOL
665 InstStartInstallationThread(HWND hwndNotify)
666 {
667 if(hInstallationThread == NULL)
668 {
669 DWORD ThreadId;
670 hInstallationNotifyWnd = hwndNotify;
671 AbortInstall = 0;
672 hInstallationThread = CreateThread(NULL,
673 0,
674 InstInstallationThread,
675 NULL,
676 CREATE_SUSPENDED,
677 &ThreadId);
678 if(hInstallationThread == NULL)
679 {
680 return FALSE;
681 }
682
683 ResumeThread(hInstallationThread);
684 return TRUE;
685 }
686
687 return FALSE;
688 }
689
690 /* Property page dialog callback */
691 INT_PTR CALLBACK
692 PageInstallingProc(
693 HWND hwndDlg,
694 UINT uMsg,
695 WPARAM wParam,
696 LPARAM lParam
697 )
698 {
699 switch(uMsg)
700 {
701 case WM_NOTIFY:
702 {
703 LPNMHDR pnmh = (LPNMHDR)lParam;
704 switch(pnmh->code)
705 {
706 case PSN_SETACTIVE:
707 SetDlgItemText(hwndDlg, IDC_INSTALLINGSTATUS, NULL);
708 SendDlgItemMessage(hwndDlg, IDC_INSTALLINGPROGRESS, PBM_SETMARQUEE, TRUE, 50);
709 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK);
710 InstStartInstallationThread(hwndDlg);
711 break;
712 case PSN_RESET:
713 InstTerminateInstaller(TRUE);
714 break;
715 case PSN_WIZBACK:
716 if(hInstallationThread != NULL)
717 {
718 PropSheet_SetWizButtons(GetParent(hwndDlg), 0);
719 InstTerminateInstaller(FALSE);
720 SetWindowLong(hwndDlg, DWL_MSGRESULT, -1);
721 return -1;
722 }
723 else
724 {
725 SendDlgItemMessage(hwndDlg, IDC_INSTALLINGPROGRESS, PBM_SETMARQUEE, FALSE, 0);
726 SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_INSERT_VMWARE_TOOLS);
727 }
728 break;
729 }
730 break;
731 }
732 case WM_INSTABORT:
733 /* go back in case we aborted the installation thread */
734 SendDlgItemMessage(hwndDlg, IDC_INSTALLINGPROGRESS, PBM_SETMARQUEE, FALSE, 0);
735 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_INSERT_VMWARE_TOOLS);
736 if(wParam != 0)
737 {
738 WCHAR Msg[1024];
739 LoadString(hAppInstance, wParam, Msg, sizeof(Msg) / sizeof(WCHAR));
740 MessageBox(GetParent(hwndDlg), Msg, NULL, MB_ICONWARNING);
741 }
742 break;
743 case WM_INSTCOMPLETE:
744 SendDlgItemMessage(hwndDlg, IDC_INSTALLINGPROGRESS, PBM_SETMARQUEE, FALSE, 0);
745 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
746 PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_CONFIG);
747 break;
748 case WM_INSTSTATUSUPDATE:
749 {
750 WCHAR Msg[1024];
751 LoadString(hAppInstance, wParam, Msg, sizeof(Msg) / sizeof(WCHAR));
752 SetDlgItemText(hwndDlg, IDC_INSTALLINGSTATUS, Msg);
753 break;
754 }
755 }
756 return FALSE;
757 }
758
759 /* Property page dialog callback */
760 INT_PTR CALLBACK
761 PageInstallFailedProc(
762 HWND hwndDlg,
763 UINT uMsg,
764 WPARAM wParam,
765 LPARAM lParam
766 )
767 {
768 switch(uMsg)
769 {
770 case WM_NOTIFY:
771 {
772 LPNMHDR pnmh = (LPNMHDR)lParam;
773 switch(pnmh->code)
774 {
775 case PSN_SETACTIVE:
776 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH);
777 break;
778 }
779 break;
780 }
781 }
782 return FALSE;
783 }
784
785 void
786 FillComboBox(HWND Dlg, int idComboBox, int From, int To)
787 {
788 int i;
789 WCHAR Text[256];
790
791 for(i = From; i <= To; i++)
792 {
793 if(LoadString(hAppInstance, i, Text, 255) > 0)
794 {
795 SendDlgItemMessage(Dlg, idComboBox, CB_ADDSTRING, 0, (LPARAM)Text);
796 }
797 }
798 }
799
800 typedef struct
801 {
802 int ControlID;
803 int ResX;
804 int ResY;
805 } MAPCTLRES;
806
807 /* Property page dialog callback */
808 INT_PTR CALLBACK
809 PageConfigProc(
810 HWND hwndDlg,
811 UINT uMsg,
812 WPARAM wParam,
813 LPARAM lParam
814 )
815 {
816 switch(uMsg)
817 {
818 case WM_INITDIALOG:
819 {
820 DWORD ResX = 0, ResY = 0, ColDepth = 0;
821 int cbSel;
822
823 FillComboBox(hwndDlg, IDC_COLORQUALITY, 10001, 10003);
824 if(LoadResolutionSettings(&ResX, &ResY, &ColDepth))
825 {
826 SendDlgItemMessage(hwndDlg, ResX + ResY, BM_SETCHECK, BST_CHECKED, 0);
827 switch(ColDepth)
828 {
829 case 8:
830 cbSel = 0;
831 break;
832 case 16:
833 cbSel = 1;
834 break;
835 case 32:
836 cbSel = 2;
837 break;
838 default:
839 cbSel = -1;
840 break;
841 }
842 SendDlgItemMessage(hwndDlg, IDC_COLORQUALITY, CB_SETCURSEL, cbSel, 0);
843 }
844 break;
845 }
846 case WM_NOTIFY:
847 {
848 HWND hwndControl;
849
850 /* Center the wizard window */
851 hwndControl = GetParent(hwndDlg);
852 CenterWindow (hwndControl);
853
854 LPNMHDR pnmh = (LPNMHDR)lParam;
855 switch(pnmh->code)
856 {
857 case PSN_SETACTIVE:
858 {
859 PropSheet_SetWizButtons(GetParent(hwndDlg), ((StartVMwConfigWizard || DriverFilesFound) ? PSWIZB_FINISH | PSWIZB_BACK : PSWIZB_FINISH));
860 break;
861 }
862 case PSN_WIZBACK:
863 {
864 if(StartVMwConfigWizard)
865 {
866 SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_CHOOSEACTION);
867 return TRUE;
868 }
869 if(DriverFilesFound)
870 {
871 SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_WELCOMEPAGE);
872 return TRUE;
873 }
874 break;
875 }
876 case PSN_WIZFINISH:
877 {
878 DWORD rx = 800, ry = 600, cd = 32;
879 int i;
880 static MAPCTLRES Resolutions[11] = {
881 {540, 640, 480},
882 {1400, 800, 600},
883 {1792, 1024, 768},
884 {2016, 1152, 864},
885 {2240, 1280, 960},
886 {2304, 1280, 1024},
887 {2450, 1400, 1050},
888 {2800, 1600, 1200},
889 {3136, 1792, 1344},
890 {3248, 1856, 1392},
891 {3360, 1920, 1440}
892 };
893 for(i = 0; i < 11; i++)
894 {
895 if(SendDlgItemMessage(hwndDlg, Resolutions[i].ControlID, BM_GETCHECK, 0, 0) == BST_CHECKED)
896 {
897 rx = Resolutions[i].ResX;
898 ry = Resolutions[i].ResY;
899 break;
900 }
901 }
902
903 switch(SendDlgItemMessage(hwndDlg, IDC_COLORQUALITY, CB_GETCURSEL, 0, 0))
904 {
905 case 0:
906 cd = 8;
907 break;
908 case 1:
909 cd = 16;
910 break;
911 case 2:
912 cd = 32;
913 break;
914 }
915
916 SaveResolutionSettings(rx, ry, cd);
917 break;
918 }
919 }
920 break;
921 }
922 }
923 return FALSE;
924 }
925
926 /* Property page dialog callback */
927 INT_PTR CALLBACK
928 PageChooseActionProc(
929 HWND hwndDlg,
930 UINT uMsg,
931 WPARAM wParam,
932 LPARAM lParam
933 )
934 {
935 switch(uMsg)
936 {
937 case WM_INITDIALOG:
938 SendDlgItemMessage(hwndDlg, IDC_CONFIGSETTINGS, BM_SETCHECK, BST_CHECKED, 0);
939 break;
940 case WM_NOTIFY:
941 {
942 LPNMHDR pnmh = (LPNMHDR)lParam;
943 switch(pnmh->code)
944 {
945 case PSN_SETACTIVE:
946 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
947 break;
948 case PSN_WIZBACK:
949 {
950 SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_CHOOSEACTION);
951 return TRUE;
952 }
953 case PSN_WIZNEXT:
954 {
955 static ULONG SelPage[4] = {IDD_CONFIG, IDD_SELECTDRIVER, IDD_SELECTDRIVER, IDD_CHOOSEACTION};
956 int i;
957
958 for(i = IDC_CONFIGSETTINGS; i <= IDC_UNINSTALL; i++)
959 {
960 if(SendDlgItemMessage(hwndDlg, i, BM_GETCHECK, 0, 0) == BST_CHECKED)
961 {
962 break;
963 }
964 }
965
966 UninstallDriver = (i == IDC_UNINSTALL);
967
968 SetWindowLong(hwndDlg, DWL_MSGRESULT, SelPage[i - IDC_CONFIGSETTINGS]);
969 return TRUE;
970 }
971 }
972 break;
973 }
974 }
975 return FALSE;
976 }
977
978 /* Property page dialog callback */
979 INT_PTR CALLBACK
980 PageSelectDriverProc(
981 HWND hwndDlg,
982 UINT uMsg,
983 WPARAM wParam,
984 LPARAM lParam
985 )
986 {
987 switch(uMsg)
988 {
989 case WM_INITDIALOG:
990 SendDlgItemMessage(hwndDlg, IDC_VBE, BM_SETCHECK, BST_CHECKED, 0);
991 break;
992 case WM_NOTIFY:
993 {
994 LPNMHDR pnmh = (LPNMHDR)lParam;
995 switch(pnmh->code)
996 {
997 case PSN_SETACTIVE:
998 PropSheet_SetWizButtons(GetParent(hwndDlg), (UninstallDriver ? PSWIZB_NEXT | PSWIZB_BACK : PSWIZB_BACK | PSWIZB_FINISH));
999 break;
1000 case PSN_WIZBACK:
1001 {
1002 SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_CHOOSEACTION);
1003 return TRUE;
1004 }
1005 case PSN_WIZNEXT:
1006 {
1007 ActivateVBE = (SendDlgItemMessage(hwndDlg, IDC_VBE, BM_GETCHECK, 0, 0) == BST_CHECKED);
1008
1009 if(UninstallDriver)
1010 {
1011 return FALSE;
1012 }
1013 return TRUE;
1014 }
1015 case PSN_WIZFINISH:
1016 {
1017 if(UninstallDriver)
1018 {
1019 return FALSE;
1020 }
1021 ActivateVBE = (SendDlgItemMessage(hwndDlg, IDC_VBE, BM_GETCHECK, 0, 0) == BST_CHECKED);
1022 if(!EnableVmwareDriver(ActivateVBE,
1023 TRUE,
1024 FALSE))
1025 {
1026 WCHAR Msg[1024];
1027 LoadString(hAppInstance, (ActivateVBE ? IDS_FAILEDTOSELVBEDRIVER : IDS_FAILEDTOSELVGADRIVER), Msg, sizeof(Msg) / sizeof(WCHAR));
1028 MessageBox(GetParent(hwndDlg), Msg, NULL, MB_ICONWARNING);
1029 SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_SELECTDRIVER);
1030 return TRUE;
1031 }
1032 break;
1033 }
1034 }
1035 break;
1036 }
1037 }
1038 return FALSE;
1039 }
1040
1041 VOID
1042 ShowUninstNotice(HWND Owner)
1043 {
1044 WCHAR Msg[1024];
1045 LoadString(hAppInstance, IDS_UNINSTNOTICE, Msg, sizeof(Msg) / sizeof(WCHAR));
1046 MessageBox(Owner, Msg, NULL, MB_ICONINFORMATION);
1047 }
1048
1049 INT_PTR CALLBACK
1050 PageDoUninstallProc(
1051 HWND hwndDlg,
1052 UINT uMsg,
1053 WPARAM wParam,
1054 LPARAM lParam
1055 )
1056 {
1057 switch(uMsg)
1058 {
1059 case WM_NOTIFY:
1060 {
1061 LPNMHDR pnmh = (LPNMHDR)lParam;
1062 switch(pnmh->code)
1063 {
1064 case PSN_SETACTIVE:
1065 PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_FINISH);
1066 break;
1067 case PSN_WIZFINISH:
1068 {
1069 if(UninstallDriver)
1070 {
1071 if(!EnableVmwareDriver(ActivateVBE,
1072 TRUE,
1073 FALSE))
1074 {
1075 WCHAR Msg[1024];
1076 LoadString(hAppInstance, (ActivateVBE ? IDS_FAILEDTOSELVBEDRIVER : IDS_FAILEDTOSELVGADRIVER), Msg, sizeof(Msg) / sizeof(WCHAR));
1077 MessageBox(GetParent(hwndDlg), Msg, NULL, MB_ICONWARNING);
1078 SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_SELECTDRIVER);
1079 return TRUE;
1080 }
1081 ShowUninstNotice(GetParent(hwndDlg));
1082 }
1083 return FALSE;
1084 }
1085 }
1086 break;
1087 }
1088 }
1089 return FALSE;
1090 }
1091
1092 static LONG
1093 CreateWizard(VOID)
1094 {
1095 PROPSHEETHEADER psh;
1096 HPROPSHEETPAGE ahpsp[8];
1097 PROPSHEETPAGE psp;
1098 WCHAR Caption[1024];
1099
1100 LoadString(hAppInstance, IDS_WIZARD_NAME, Caption, sizeof(Caption) / sizeof(TCHAR));
1101
1102 /* Create the Welcome page */
1103 ZeroMemory (&psp, sizeof(PROPSHEETPAGE));
1104 psp.dwSize = sizeof(PROPSHEETPAGE);
1105 psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
1106 psp.hInstance = hAppInstance;
1107 psp.pfnDlgProc = PageWelcomeProc;
1108 psp.pszTemplate = MAKEINTRESOURCE(IDD_WELCOMEPAGE);
1109 ahpsp[0] = CreatePropertySheetPage(&psp);
1110
1111 /* Create the INSERT_VMWARE_TOOLS page */
1112 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1113 psp.pszHeaderTitle = MAKEINTRESOURCE(IDD_INSERT_VMWARE_TOOLSTITLE);
1114 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDD_INSERT_VMWARE_TOOLSSUBTITLE);
1115 psp.pszTemplate = MAKEINTRESOURCE(IDD_INSERT_VMWARE_TOOLS);
1116 psp.pfnDlgProc = PageInsertDiscProc;
1117 ahpsp[1] = CreatePropertySheetPage(&psp);
1118
1119 /* Create the INSTALLING_VMWARE_TOOLS page */
1120 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1121 psp.pszHeaderTitle = MAKEINTRESOURCE(IDD_INSTALLING_VMWARE_TOOLSTITLE);
1122 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDD_INSTALLING_VMWARE_TOOLSSUBTITLE);
1123 psp.pszTemplate = MAKEINTRESOURCE(IDD_INSTALLING_VMWARE_TOOLS);
1124 psp.pfnDlgProc = PageInstallingProc;
1125 ahpsp[2] = CreatePropertySheetPage(&psp);
1126
1127 /* Create the CONFIG page */
1128 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1129 psp.pszHeaderTitle = MAKEINTRESOURCE(IDD_CONFIGTITLE);
1130 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDD_CONFIGSUBTITLE);
1131 psp.pfnDlgProc = PageConfigProc;
1132 psp.pszTemplate = MAKEINTRESOURCE(IDD_CONFIG);
1133 ahpsp[3] = CreatePropertySheetPage(&psp);
1134
1135 /* Create the INSTALLATION_FAILED page */
1136 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1137 psp.pszHeaderTitle = MAKEINTRESOURCE(IDD_INSTALLATION_FAILEDTITLE);
1138 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDD_INSTALLATION_FAILEDSUBTITLE);
1139 psp.pfnDlgProc = PageInstallFailedProc;
1140 psp.pszTemplate = MAKEINTRESOURCE(IDD_INSTALLATION_FAILED);
1141 ahpsp[4] = CreatePropertySheetPage(&psp);
1142
1143 /* Create the CHOOSEACTION page */
1144 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1145 psp.pszHeaderTitle = MAKEINTRESOURCE(IDD_CHOOSEACTIONTITLE);
1146 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDD_CHOOSEACTIONSUBTITLE);
1147 psp.pfnDlgProc = PageChooseActionProc;
1148 psp.pszTemplate = MAKEINTRESOURCE(IDD_CHOOSEACTION);
1149 ahpsp[5] = CreatePropertySheetPage(&psp);
1150
1151 /* Create the SELECTDRIVER page */
1152 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1153 psp.pszHeaderTitle = MAKEINTRESOURCE(IDD_SELECTDRIVERTITLE);
1154 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDD_SELECTDRIVERSUBTITLE);
1155 psp.pfnDlgProc = PageSelectDriverProc;
1156 psp.pszTemplate = MAKEINTRESOURCE(IDD_SELECTDRIVER);
1157 ahpsp[6] = CreatePropertySheetPage(&psp);
1158
1159 /* Create the DOUNINSTALL page */
1160 psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
1161 psp.pszHeaderTitle = MAKEINTRESOURCE(IDD_DOUNINSTALLTITLE);
1162 psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDD_DOUNINSTALLSUBTITLE);
1163 psp.pfnDlgProc = PageDoUninstallProc;
1164 psp.pszTemplate = MAKEINTRESOURCE(IDD_DOUNINSTALL);
1165 ahpsp[7] = CreatePropertySheetPage(&psp);
1166
1167 /* Create the property sheet */
1168 psh.dwSize = sizeof(PROPSHEETHEADER);
1169 psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
1170 psh.hInstance = hAppInstance;
1171 psh.hwndParent = NULL;
1172 psh.nPages = 7;
1173 psh.nStartPage = (StartVMwConfigWizard ? 5 : 0);
1174 psh.phpage = ahpsp;
1175 psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
1176 psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER);
1177
1178 /* Display the wizard */
1179 return (LONG)(PropertySheet(&psh) != -1);
1180 }
1181
1182 int WINAPI
1183 WinMain(HINSTANCE hInstance,
1184 HINSTANCE hPrevInstance,
1185 LPSTR lpszCmdLine,
1186 int nCmdShow)
1187 {
1188
1189 LPTOP_LEVEL_EXCEPTION_FILTER OldHandler;
1190 int Version;
1191 WCHAR *lc;
1192
1193 hAppInstance = hInstance;
1194
1195 /* Setup our exception "handler" ;-) */
1196 OldHandler = SetUnhandledExceptionFilter(ExceptionHandler);
1197
1198 if(!DetectVMware(&Version))
1199 {
1200 ExitProcess(1);
1201 return 1;
1202 }
1203
1204 /* restore the exception handler */
1205 SetUnhandledExceptionFilter(OldHandler);
1206
1207 lc = DestinationPath;
1208 lc += GetSystemDirectory(DestinationPath, MAX_PATH) - 1;
1209 if(lc >= DestinationPath && *lc != L'\\')
1210 {
1211 wcscat(DestinationPath, L"\\");
1212 }
1213 DestinationDriversPath[0] = L'\0';
1214 wcscat(DestinationDriversPath, DestinationPath);
1215 wcscat(DestinationDriversPath, L"drivers\\");
1216
1217 SetCurrentDirectory(DestinationPath);
1218
1219 DriverFilesFound = FileExists(DestinationPath, vmx_fb) &&
1220 FileExists(DestinationPath, vmx_mode) &&
1221 FileExists(DestinationDriversPath, vmx_svga);
1222
1223 StartVMwConfigWizard = DriverFilesFound && IsVmwSVGAEnabled();
1224
1225 /* Show the wizard */
1226 CreateWizard();
1227
1228 return 2;
1229 }
1230