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.

392 lines
8.6 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. interface.c
  5. Abstract:
  6. Implements the APIs exposed by osuninst.dll
  7. Author:
  8. Jim Schmidt (jimschm) 19-Jan-2001
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. #include "pch.h"
  13. #include "undop.h"
  14. #include "psapi.h"
  15. HANDLE g_hHeap;
  16. HINSTANCE g_hInst;
  17. #ifndef UNICODE
  18. #error UNICODE required
  19. #endif
  20. #define EXECUTABLE_FILE_NAME_LENGTH_W L"osuninst.exe"
  21. BOOL g_Initialized = FALSE;
  22. //
  23. // Entry point for DLL
  24. //
  25. BOOL WINAPI MigUtil_Entry (HINSTANCE, DWORD, PVOID);
  26. BOOL
  27. pCallEntryPoints (
  28. DWORD Reason
  29. )
  30. {
  31. SuppressAllLogPopups (TRUE);
  32. if (!MigUtil_Entry (g_hInst, Reason, NULL)) {
  33. return FALSE;
  34. }
  35. //
  36. // Add others here if needed (don't forget to prototype above)
  37. //
  38. return TRUE;
  39. }
  40. CRITICAL_SECTION g_DeferredInitGuard;
  41. BOOL
  42. WINAPI
  43. DllMain (
  44. IN HINSTANCE hInstance,
  45. IN DWORD dwReason,
  46. IN LPVOID lpReserved
  47. )
  48. {
  49. switch (dwReason) {
  50. case DLL_PROCESS_ATTACH:
  51. g_hInst = hInstance;
  52. InitializeCriticalSection(&g_DeferredInitGuard);
  53. break;
  54. case DLL_PROCESS_DETACH:
  55. DeleteCriticalSection(&g_DeferredInitGuard);
  56. if (g_Initialized) {
  57. DEBUGMSG ((DBG_VERBOSE, "DllMain(DLL_PROCESS_DETACH)"));
  58. pCallEntryPoints (DLL_PROCESS_DETACH);
  59. g_Initialized = FALSE;
  60. break;
  61. }
  62. }
  63. return TRUE;
  64. }
  65. VOID
  66. DeferredInit (
  67. VOID
  68. )
  69. {
  70. EnterCriticalSection(&g_DeferredInitGuard);
  71. if (!g_Initialized) {
  72. g_Initialized = TRUE;
  73. g_hHeap = GetProcessHeap();
  74. pCallEntryPoints (DLL_PROCESS_ATTACH);
  75. }
  76. LeaveCriticalSection(&g_DeferredInitGuard);
  77. }
  78. DWORD
  79. pUninstallStatusToWin32Error (
  80. UNINSTALLSTATUS Status
  81. )
  82. {
  83. DWORD result = E_UNEXPECTED;
  84. switch (Status) {
  85. case Uninstall_Valid:
  86. result = ERROR_SUCCESS;
  87. break;
  88. case Uninstall_DidNotFindRegistryEntries:
  89. result = ERROR_RESOURCE_NOT_PRESENT;
  90. break;
  91. case Uninstall_DidNotFindDirOrFiles:
  92. result = ERROR_FILE_NOT_FOUND;
  93. break;
  94. case Uninstall_InvalidOsVersion:
  95. result = ERROR_OLD_WIN_VERSION;
  96. break;
  97. case Uninstall_NotEnoughPrivileges:
  98. result = ERROR_ACCESS_DENIED;
  99. break;
  100. case Uninstall_FileWasModified:
  101. result = ERROR_FILE_INVALID;
  102. break;
  103. case Uninstall_Unsupported:
  104. result = ERROR_CALL_NOT_IMPLEMENTED;
  105. break;
  106. case Uninstall_NewImage:
  107. result = ERROR_INVALID_TIME;
  108. break;
  109. case Uninstall_Exception:
  110. result = ERROR_NOACCESS;
  111. break;
  112. case Uninstall_OldImage:
  113. result = ERROR_TIMEOUT;
  114. break;
  115. case Uninstall_NotEnoughMemory:
  116. result = ERROR_NOT_ENOUGH_MEMORY;
  117. break;
  118. default:
  119. break;
  120. }
  121. SetLastError (result);
  122. return result;
  123. }
  124. BOOL
  125. pGetVersionDword (
  126. IN HKEY Key,
  127. IN PCTSTR ValueName,
  128. OUT PDWORD ValueData
  129. )
  130. {
  131. PDWORD data;
  132. MYASSERT(ValueName);
  133. data = (PDWORD) GetRegValueDword (Key, ValueName);
  134. if (!data) {
  135. return FALSE;
  136. }
  137. MYASSERT(data);
  138. MYASSERT(ValueData);
  139. *ValueData = *data;
  140. MemFree (g_hHeap, 0, data);
  141. return TRUE;
  142. }
  143. UNINSTALLSTATUS
  144. IsUninstallImageValid (
  145. UNINSTALLTESTCOMPONENT ComponentType,
  146. OSVERSIONINFOEX *BackedUpOsVersion OPTIONAL
  147. )
  148. {
  149. UNINSTALLSTATUS status = Uninstall_Valid;
  150. DWORD orgVersionSize;
  151. HKEY key = NULL;
  152. ULONG error;
  153. PDWORD value;
  154. HKEY versionKey = NULL;
  155. OSVERSIONINFOEX ourVersion = {
  156. sizeof (OSVERSIONINFOEX),
  157. 4,
  158. 10,
  159. 1998,
  160. VER_PLATFORM_WIN32_NT,
  161. TEXT(""),
  162. 0,
  163. 0,
  164. 0,
  165. 0
  166. };
  167. DeferredInit();
  168. __try {
  169. //
  170. // Fill in version structure if possible, default to Win98 gold if not
  171. //
  172. key = OpenRegKeyStr (S_WINLOGON_REGKEY);
  173. if (key) {
  174. value = (PDWORD) GetRegValueDword (key, S_WIN9XUPG_FLAG_VALNAME);
  175. if (!value) {
  176. //
  177. // It is not looking like a Win9x upgrade!
  178. //
  179. DEBUGMSG ((DBG_VERBOSE, "Can't find %s in WinLogon reg key", S_WIN9XUPG_FLAG_VALNAME));
  180. status = Uninstall_DidNotFindRegistryEntries;
  181. } else {
  182. if (*value) {
  183. //
  184. // Version info should be present
  185. //
  186. versionKey = OpenRegKey (key, TEXT("PrevOsVersion"));
  187. if (versionKey) {
  188. pGetVersionDword (versionKey, MEMDB_ITEM_MAJOR_VERSION, &ourVersion.dwMajorVersion);
  189. pGetVersionDword (versionKey, MEMDB_ITEM_MINOR_VERSION, &ourVersion.dwMinorVersion);
  190. pGetVersionDword (versionKey, MEMDB_ITEM_BUILD_NUMBER, &ourVersion.dwBuildNumber);
  191. pGetVersionDword (versionKey, MEMDB_ITEM_PLATFORM_ID, &ourVersion.dwPlatformId);
  192. } else {
  193. DEBUGMSG ((DBG_VERBOSE, "Did not find PrevOsVersion; defaulting to Win98 gold"));
  194. }
  195. } else {
  196. DEBUGMSG ((DBG_VERBOSE, "Not a Win9x upgrade"));
  197. status = Uninstall_DidNotFindRegistryEntries;
  198. }
  199. MemFree (g_hHeap, 0, value);
  200. }
  201. }
  202. }
  203. __finally {
  204. if (versionKey)
  205. CloseRegKey (versionKey);
  206. if (key)
  207. CloseRegKey (key);
  208. }
  209. //
  210. // ComponentType is provided to allow special-case behavior to be
  211. // performed. For example, maybe we want to warn on FAT-to-NTFS
  212. // conversion when coming from Win9x, but we don't care when coming
  213. // from Win2k.
  214. //
  215. if (status == Uninstall_Valid) {
  216. status = SanityCheck (QUICK_CHECK, NULL, NULL);
  217. if (ComponentType == Uninstall_FatToNtfsConversion) {
  218. if (status == Uninstall_OldImage) {
  219. //
  220. // Do not suppress convert.exe warning even if uninstall is old
  221. //
  222. status = Uninstall_Valid;
  223. }
  224. }
  225. }
  226. if (status == Uninstall_Valid) {
  227. if (BackedUpOsVersion) {
  228. __try {
  229. orgVersionSize = BackedUpOsVersion->dwOSVersionInfoSize;
  230. orgVersionSize = min (orgVersionSize, sizeof (ourVersion));
  231. CopyMemory (BackedUpOsVersion, &ourVersion, orgVersionSize);
  232. BackedUpOsVersion->dwOSVersionInfoSize = orgVersionSize;
  233. }
  234. __except (1) {
  235. status = Uninstall_Exception;
  236. }
  237. }
  238. }
  239. pUninstallStatusToWin32Error (status);
  240. return status;
  241. }
  242. ULONGLONG
  243. GetUninstallImageSize (
  244. VOID
  245. )
  246. {
  247. ULONGLONG diskSpace;
  248. DeferredInit();
  249. //
  250. // SanityCheck returns the disk space used by the uninstall image,
  251. // regardless if it is valid or not.
  252. //
  253. SanityCheck (QUICK_CHECK, NULL, &diskSpace);
  254. return diskSpace;
  255. }
  256. BOOL
  257. RemoveUninstallImage (
  258. VOID
  259. )
  260. {
  261. DeferredInit();
  262. return DoCleanup();
  263. }
  264. BOOL
  265. pIsEligibleCaller(
  266. VOID
  267. )
  268. {
  269. WCHAR callerExecutablePath[MAX_PATH];
  270. WCHAR callerEtalonPath[MAX_PATH];
  271. if(!GetSystemDirectoryW(callerEtalonPath,
  272. ARRAYSIZE(callerEtalonPath) -
  273. ARRAYSIZE(EXECUTABLE_FILE_NAME_LENGTH_W) - 1)){
  274. return FALSE;
  275. }
  276. wcscat(AppendWackW(callerEtalonPath), EXECUTABLE_FILE_NAME_LENGTH_W);
  277. if(GetModuleFileNameExW(GetCurrentProcess(), NULL, callerExecutablePath, ARRAYSIZE(callerExecutablePath))){
  278. return (!_wcsicmp(callerExecutablePath, callerEtalonPath));
  279. }
  280. return FALSE;
  281. }
  282. BOOL
  283. ExecuteUninstall (
  284. VOID
  285. )
  286. {
  287. UNINSTALLSTATUS status;
  288. DeferredInit();
  289. if(!pIsEligibleCaller()){
  290. LOG((LOG_ERROR, "Uninstall was executed by malicious executable"));
  291. SetLastError(ERROR_ACCESS_DENIED);
  292. return FALSE;
  293. }
  294. status = SanityCheck (VERIFY_CAB, NULL, NULL);
  295. if (status != Uninstall_Valid && status != Uninstall_OldImage) {
  296. pUninstallStatusToWin32Error (status);
  297. return FALSE;
  298. }
  299. return DoUninstall();
  300. }