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