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