Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

519 lines
11 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. osuninst.c
  5. Abstract:
  6. Implements a GUI executable that gets added as part of Add/Remove
  7. Programs, to allow the user to roll back to Win9x.
  8. Author:
  9. Jim Schmidt (jimschm) 20-Nov-2000
  10. Revision History:
  11. --*/
  12. #include "pch.h"
  13. #ifdef __cplusplus
  14. extern "C" {
  15. #endif
  16. #define MIGISOL_INCLUDES
  17. #include "master.h"
  18. #include <undo.h>
  19. #ifdef __cplusplus
  20. }
  21. #endif
  22. #include "resource.h"
  23. #include "memmsg.h"
  24. BOOL g_DisableUninstall;
  25. BOOL g_OldImage;
  26. HINSTANCE g_hInst;
  27. #define DO_UNINSTALL 1
  28. #define DO_CLEANUP 2
  29. VOID
  30. pGetMsgFromRc (
  31. OUT PWSTR Buffer,
  32. IN UINT BufferSize,
  33. IN UINT Id
  34. )
  35. {
  36. *Buffer = 0;
  37. LoadString (GetModuleHandle(NULL), Id, Buffer, BufferSize);
  38. }
  39. BOOL
  40. pYesNoMsgFromRcDlg (
  41. IN HWND Parent,
  42. IN UINT Id
  43. )
  44. {
  45. WCHAR title[256];
  46. WCHAR msg[1024];
  47. pGetMsgFromRc (title, ARRAYSIZE(title), IDS_TITLE);
  48. pGetMsgFromRc (msg, ARRAYSIZE(msg), Id);
  49. return MessageBox (Parent, msg, title, MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2) == IDYES;
  50. }
  51. BOOL
  52. pYesNoMsgFromMcDlg (
  53. IN HWND Parent,
  54. IN UINT Id
  55. )
  56. {
  57. WCHAR title[256];
  58. PCWSTR msg;
  59. BOOL result = FALSE;
  60. pGetMsgFromRc (title, ARRAYSIZE(title), IDS_TITLE);
  61. msg = NULL;
  62. FormatMessageW (
  63. FORMAT_MESSAGE_ALLOCATE_BUFFER|
  64. FORMAT_MESSAGE_ARGUMENT_ARRAY|
  65. FORMAT_MESSAGE_FROM_HMODULE,
  66. (PVOID) g_hInst,
  67. Id,
  68. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  69. (PVOID) &msg,
  70. 0,
  71. (va_list *) NULL // array of PCWSTR pointers
  72. );
  73. if (msg) {
  74. result = MessageBox (Parent, msg, title, MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2) == IDYES;
  75. LocalFree ((HLOCAL) msg);
  76. }
  77. return result;
  78. }
  79. VOID
  80. pOkBoxFromRc (
  81. IN HWND Parent,
  82. IN UINT Id
  83. )
  84. {
  85. WCHAR title[256];
  86. WCHAR msg[1024];
  87. pGetMsgFromRc (title, ARRAYSIZE(title), IDS_TITLE);
  88. pGetMsgFromRc (msg, ARRAYSIZE(msg), Id);
  89. MessageBox (Parent, msg, title, MB_OK|MB_ICONEXCLAMATION);
  90. }
  91. INT_PTR
  92. CALLBACK
  93. pUndoDlgProc (
  94. HWND hdlg,
  95. UINT uMsg,
  96. WPARAM wParam,
  97. LPARAM lParam
  98. )
  99. {
  100. switch (uMsg) {
  101. case WM_INITDIALOG:
  102. EnableWindow (GetDlgItem (hdlg, IDOK), FALSE);
  103. if (g_DisableUninstall) {
  104. EnableWindow (GetDlgItem (hdlg, IDC_RADIO1), FALSE);
  105. SetFocus (GetDlgItem (hdlg, IDC_RADIO2));
  106. }
  107. break;
  108. case WM_COMMAND:
  109. switch (LOWORD (wParam)) {
  110. case IDC_RADIO1:
  111. case IDC_RADIO2:
  112. if (HIWORD (wParam) == BN_CLICKED) {
  113. EnableWindow (
  114. GetDlgItem (hdlg, IDOK),
  115. IsDlgButtonChecked (hdlg, IDC_RADIO1) ||
  116. IsDlgButtonChecked (hdlg, IDC_RADIO2)
  117. );
  118. }
  119. break;
  120. case IDOK:
  121. if (IsDlgButtonChecked (hdlg, IDC_RADIO1)) {
  122. EndDialog (hdlg, DO_UNINSTALL);
  123. } else if (IsDlgButtonChecked (hdlg, IDC_RADIO2)) {
  124. EndDialog (hdlg, DO_CLEANUP);
  125. }
  126. break;
  127. case IDCANCEL:
  128. EndDialog (hdlg, 0);
  129. return TRUE;
  130. }
  131. break;
  132. }
  133. return FALSE;
  134. }
  135. UINT
  136. pTranslateUninstallStatusToRc (
  137. UNINSTALLSTATUS Status
  138. )
  139. {
  140. switch (Status) {
  141. case Uninstall_DidNotFindRegistryEntries:
  142. return IDS_NO_REGISTRY;
  143. case Uninstall_DidNotFindDirOrFiles:
  144. return IDS_NO_BACKUP;
  145. case Uninstall_InvalidOsVersion:
  146. return IDS_NO_INVALID_OS;
  147. case Uninstall_NotEnoughPrivileges:
  148. return IDS_NO_ENOUGH_PRIVILEGE;
  149. case Uninstall_FileWasModified:
  150. return IDS_FILES_MODIFIED;
  151. case Uninstall_CantRetrieveSystemInfo:
  152. return IDS_CANT_RETRIEVE_SYSTEMINFO;
  153. case Uninstall_WrongDrive:
  154. return IDS_WRONG_DRIVE;
  155. case Uninstall_NotEnoughSpace:
  156. return IDS_NOT_ENOUGH_SPACE;
  157. case Uninstall_NewImage:
  158. return IDS_NEW_IMAGE;
  159. case Uninstall_OldImage:
  160. return IDS_OLD_IMAGE;
  161. case Uninstall_DifferentNumberOfDrives:
  162. return IDS_DIFFERENT_DISK_NUMBER;
  163. case Uninstall_NotEnoughMemory:
  164. return IDS_NOT_ENOUGH_MEMORY;
  165. case Uninstall_DifferentDriveLetter:
  166. return IDS_DIFFERENT_DRIVE_LETTER;
  167. case Uninstall_DifferentDriveFileSystem:
  168. return IDS_DIFFERENT_DRIVE_FILE_SYSTEM;
  169. case Uninstall_DifferentDriveGeometry:
  170. return IDS_DIFFERENT_DRIVE_GEOMETRY;
  171. case Uninstall_DifferentDrivePartitionInfo:
  172. return IDS_DIFFERENT_DRIVE_PARTITION;
  173. }
  174. return IDS_NO_BACKUP;
  175. }
  176. UINT
  177. pTranslateLastErrorToRc (
  178. VOID
  179. )
  180. {
  181. UINT result;
  182. switch (GetLastError()) {
  183. case ERROR_SUCCESS:
  184. result = 0;
  185. break;
  186. case ERROR_RESOURCE_NOT_PRESENT:
  187. result = IDS_NO_REGISTRY;
  188. break;
  189. case ERROR_FILE_NOT_FOUND:
  190. result = IDS_NO_BACKUP;
  191. break;
  192. case ERROR_OLD_WIN_VERSION:
  193. result = IDS_NO_INVALID_OS;
  194. break;
  195. case ERROR_ACCESS_DENIED:
  196. result = IDS_NO_ENOUGH_PRIVILEGE;
  197. break;
  198. case ERROR_FILE_INVALID:
  199. result = IDS_FILES_MODIFIED;
  200. break;
  201. case ERROR_CALL_NOT_IMPLEMENTED:
  202. result = ERROR_CALL_NOT_IMPLEMENTED;
  203. break;
  204. case ERROR_INVALID_TIME:
  205. result = IDS_NEW_IMAGE;
  206. break;
  207. case ERROR_NOACCESS:
  208. result = ERROR_NOACCESS;
  209. break;
  210. case ERROR_TIMEOUT:
  211. result = IDS_OLD_IMAGE;
  212. break;
  213. case ERROR_NOT_ENOUGH_MEMORY:
  214. result = IDS_NOT_ENOUGH_MEMORY;
  215. break;
  216. default:
  217. result = IDS_UNINSTALL_PREPARATION_FAILED;
  218. break;
  219. }
  220. return result;
  221. }
  222. BOOL
  223. pCanRemoveImage (
  224. UNINSTALLSTATUS Status
  225. )
  226. {
  227. switch (Status) {
  228. case Uninstall_Valid:
  229. case Uninstall_DidNotFindDirOrFiles:
  230. case Uninstall_FileWasModified:
  231. case Uninstall_CantRetrieveSystemInfo:
  232. case Uninstall_WrongDrive:
  233. case Uninstall_DifferentNumberOfDrives:
  234. case Uninstall_NotEnoughSpace:
  235. case Uninstall_OldImage:
  236. case Uninstall_NewImage:
  237. case Uninstall_DifferentDriveLetter:
  238. case Uninstall_DifferentDriveFileSystem:
  239. case Uninstall_DifferentDriveGeometry:
  240. case Uninstall_DifferentDrivePartitionInfo:
  241. return TRUE;
  242. }
  243. return FALSE;
  244. }
  245. BOOL
  246. pIsFloppyDiskInDrive(
  247. VOID
  248. )
  249. {
  250. WCHAR Drive[] = L"?:\\";
  251. WCHAR DriveNT[] = L"\\\\.\\?:";
  252. UINT i;
  253. HANDLE hDiskDrive;
  254. BOOL bDiskInDrive = FALSE;
  255. BOOL bResult;
  256. DISK_GEOMETRY diskGeometry;
  257. DWORD bytesReturned;
  258. DWORD Drives;
  259. for(i = 0, Drives = 0x7/*GetLogicalDrives()*/; Drives; Drives >>= 1, i++){
  260. if(!(Drives&1)){
  261. continue;
  262. }
  263. Drive[0] = 'A' + i;
  264. if(DRIVE_REMOVABLE != GetDriveTypeW(Drive)){
  265. continue;
  266. }
  267. DriveNT[4] = Drive[0];
  268. while(1){
  269. hDiskDrive = CreateFileW(DriveNT,
  270. GENERIC_READ,
  271. FILE_SHARE_READ | FILE_SHARE_WRITE,
  272. NULL,
  273. OPEN_EXISTING,
  274. 0,
  275. NULL);
  276. if(INVALID_HANDLE_VALUE == hDiskDrive){
  277. break;
  278. }
  279. bResult = DeviceIoControl(hDiskDrive,
  280. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  281. NULL,
  282. 0,
  283. &diskGeometry,
  284. sizeof(diskGeometry),
  285. &bytesReturned,
  286. NULL);
  287. CloseHandle(hDiskDrive);
  288. if(bResult){
  289. bDiskInDrive = diskGeometry.MediaType != Unknown &&
  290. diskGeometry.MediaType != RemovableMedia &&
  291. diskGeometry.MediaType != FixedMedia;
  292. break;
  293. }
  294. if(ERROR_MEDIA_CHANGED != GetLastError()){
  295. break;
  296. }
  297. }
  298. if(bDiskInDrive){
  299. break;
  300. }
  301. }
  302. return bDiskInDrive;
  303. }
  304. INT
  305. WINAPI
  306. WinMain (
  307. HINSTANCE hInstance,
  308. HINSTANCE hPrevInstance,
  309. PSTR AnsiCmdLine,
  310. INT CmdShow
  311. )
  312. /*++
  313. Routine Description:
  314. The entry point to osuninst.exe.
  315. Arguments:
  316. hInstance - The instance handle of this EXE
  317. hPrevInstance - The previous instance handle of this EXE if it is
  318. running, or NULL if no other instances exist.
  319. AnsiCmdLine - The command line (ANSI version)
  320. CmdShow - The ShowWindow command passed by the shell
  321. Return Value:
  322. Returns -1 if an error occurred, or 0 if the exe completed.
  323. --*/
  324. {
  325. INT rc = 0;
  326. UNINSTALLSTATUS status;
  327. UINT uninstallWarningMsg;
  328. PCSTR p;
  329. INITCOMMONCONTROLSEX init = {sizeof (INITCOMMONCONTROLSEX), 0};
  330. BOOL unattended = FALSE;
  331. InitCommonControlsEx (&init);
  332. g_hInst = hInstance;
  333. #ifdef PRERELEASE
  334. //
  335. // Parse cmd line
  336. //
  337. p = _mbschr (AnsiCmdLine, '/');
  338. if (!p) {
  339. p = _mbschr (AnsiCmdLine, '-');
  340. }
  341. if (p) {
  342. if (tolower(p[1]) == 'u') {
  343. rc = DO_UNINSTALL;
  344. unattended = TRUE;
  345. } else if (tolower(p[1]) == 'c') {
  346. rc = DO_CLEANUP;
  347. unattended = TRUE;
  348. }
  349. }
  350. #endif
  351. //
  352. // Validate image
  353. //
  354. status = IsUninstallImageValid (Uninstall_DontCare, NULL);
  355. if (status != Uninstall_Valid && status != Uninstall_OldImage) {
  356. pOkBoxFromRc (NULL, pTranslateUninstallStatusToRc (status));
  357. if (!pCanRemoveImage (status)) {
  358. //
  359. // Abnormal failure -- do not continue
  360. //
  361. return 0;
  362. }
  363. //
  364. // Allow user to run osuninst.exe, but restrict functionality to
  365. // cleanup only
  366. //
  367. g_DisableUninstall = TRUE;
  368. }
  369. if (status == Uninstall_OldImage) {
  370. uninstallWarningMsg = MSG_DO_OLD_UNINSTALL;
  371. } else {
  372. uninstallWarningMsg = MSG_DO_UNINSTALL;
  373. }
  374. //
  375. // Ask user what to do (if not unattended)
  376. //
  377. if (!rc) {
  378. rc = DialogBox (hInstance, MAKEINTRESOURCE(IDD_UNDO), NULL, pUndoDlgProc);
  379. }
  380. //
  381. // Perform action
  382. //
  383. if (rc == DO_CLEANUP) {
  384. if (unattended || pYesNoMsgFromMcDlg (NULL, MSG_DO_CLEANUP)) {
  385. RemoveUninstallImage();
  386. }
  387. } else if (rc == DO_UNINSTALL) {
  388. if (unattended || ProvideUiAlerts (GetDesktopWindow())) {
  389. if (unattended || pYesNoMsgFromMcDlg (NULL, uninstallWarningMsg)) {
  390. if(!unattended && pIsFloppyDiskInDrive()){
  391. pOkBoxFromRc (NULL, IDS_FLOPPYDISK_IN_DRIVE);
  392. }
  393. if(!ExecuteUninstall()) {
  394. pOkBoxFromRc (NULL, pTranslateLastErrorToRc());
  395. }
  396. }
  397. }
  398. }
  399. return 0;
  400. }