Source code of Windows XP (NT5)
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.

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