|
|
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
interface.c
Abstract:
Implements the APIs exposed by osuninst.dll
Author:
Jim Schmidt (jimschm) 19-Jan-2001
Revision History:
<alias> <date> <comments>
--*/
#include "pch.h"
#include "undop.h"
#include "psapi.h"
HANDLE g_hHeap; HINSTANCE g_hInst;
#ifndef UNICODE
#error UNICODE required
#endif
#define EXECUTABLE_FILE_NAME_LENGTH_W L"osuninst.exe"
BOOL g_Initialized = FALSE;
//
// Entry point for DLL
//
BOOL WINAPI MigUtil_Entry (HINSTANCE, DWORD, PVOID);
BOOL pCallEntryPoints ( DWORD Reason ) { SuppressAllLogPopups (TRUE);
if (!MigUtil_Entry (g_hInst, Reason, NULL)) { return FALSE; }
//
// Add others here if needed (don't forget to prototype above)
//
return TRUE; }
CRITICAL_SECTION g_DeferredInitGuard;
BOOL WINAPI DllMain ( IN HINSTANCE hInstance, IN DWORD dwReason, IN LPVOID lpReserved )
{ switch (dwReason) {
case DLL_PROCESS_ATTACH: g_hInst = hInstance; InitializeCriticalSection(&g_DeferredInitGuard); break;
case DLL_PROCESS_DETACH: DeleteCriticalSection(&g_DeferredInitGuard); if (g_Initialized) { DEBUGMSG ((DBG_VERBOSE, "DllMain(DLL_PROCESS_DETACH)")); pCallEntryPoints (DLL_PROCESS_DETACH); g_Initialized = FALSE; break; } }
return TRUE; }
VOID DeferredInit ( VOID ) { EnterCriticalSection(&g_DeferredInitGuard); if (!g_Initialized) { g_Initialized = TRUE;
g_hHeap = GetProcessHeap();
pCallEntryPoints (DLL_PROCESS_ATTACH); } LeaveCriticalSection(&g_DeferredInitGuard); }
DWORD pUninstallStatusToWin32Error ( UNINSTALLSTATUS Status ) { DWORD result = E_UNEXPECTED;
switch (Status) {
case Uninstall_Valid: result = ERROR_SUCCESS; break;
case Uninstall_DidNotFindRegistryEntries: result = ERROR_RESOURCE_NOT_PRESENT; break;
case Uninstall_DidNotFindDirOrFiles: result = ERROR_FILE_NOT_FOUND; break;
case Uninstall_InvalidOsVersion: result = ERROR_OLD_WIN_VERSION; break;
case Uninstall_NotEnoughPrivileges: result = ERROR_ACCESS_DENIED; break;
case Uninstall_FileWasModified: result = ERROR_FILE_INVALID; break;
case Uninstall_Unsupported: result = ERROR_CALL_NOT_IMPLEMENTED; break;
case Uninstall_NewImage: result = ERROR_INVALID_TIME; break;
case Uninstall_Exception: result = ERROR_NOACCESS; break;
case Uninstall_OldImage: result = ERROR_TIMEOUT; break;
case Uninstall_NotEnoughMemory: result = ERROR_NOT_ENOUGH_MEMORY; break;
default: break; }
SetLastError (result); return result; }
BOOL pGetVersionDword ( IN HKEY Key, IN PCTSTR ValueName, OUT PDWORD ValueData ) { PDWORD data;
MYASSERT(ValueName); data = (PDWORD) GetRegValueDword (Key, ValueName); if (!data) { return FALSE; }
MYASSERT(data);
MYASSERT(ValueData); *ValueData = *data; MemFree (g_hHeap, 0, data);
return TRUE; }
UNINSTALLSTATUS IsUninstallImageValid ( UNINSTALLTESTCOMPONENT ComponentType, OSVERSIONINFOEX *BackedUpOsVersion OPTIONAL ) { UNINSTALLSTATUS status = Uninstall_Valid; DWORD orgVersionSize; HKEY key = NULL; ULONG error; PDWORD value; HKEY versionKey = NULL; OSVERSIONINFOEX ourVersion = { sizeof (OSVERSIONINFOEX), 4, 10, 1998, VER_PLATFORM_WIN32_NT, TEXT(""), 0, 0, 0, 0 };
DeferredInit();
__try { //
// Fill in version structure if possible, default to Win98 gold if not
//
key = OpenRegKeyStr (S_WINLOGON_REGKEY); if (key) { value = (PDWORD) GetRegValueDword (key, S_WIN9XUPG_FLAG_VALNAME); if (!value) { //
// It is not looking like a Win9x upgrade!
//
DEBUGMSG ((DBG_VERBOSE, "Can't find %s in WinLogon reg key", S_WIN9XUPG_FLAG_VALNAME)); status = Uninstall_DidNotFindRegistryEntries; } else { if (*value) { //
// Version info should be present
//
versionKey = OpenRegKey (key, TEXT("PrevOsVersion"));
if (versionKey) { pGetVersionDword (versionKey, MEMDB_ITEM_MAJOR_VERSION, &ourVersion.dwMajorVersion); pGetVersionDword (versionKey, MEMDB_ITEM_MINOR_VERSION, &ourVersion.dwMinorVersion); pGetVersionDword (versionKey, MEMDB_ITEM_BUILD_NUMBER, &ourVersion.dwBuildNumber); pGetVersionDword (versionKey, MEMDB_ITEM_PLATFORM_ID, &ourVersion.dwPlatformId); } else { DEBUGMSG ((DBG_VERBOSE, "Did not find PrevOsVersion; defaulting to Win98 gold")); }
} else { DEBUGMSG ((DBG_VERBOSE, "Not a Win9x upgrade")); status = Uninstall_DidNotFindRegistryEntries; } MemFree (g_hHeap, 0, value); } } } __finally { if (versionKey) CloseRegKey (versionKey); if (key) CloseRegKey (key); }
//
// ComponentType is provided to allow special-case behavior to be
// performed. For example, maybe we want to warn on FAT-to-NTFS
// conversion when coming from Win9x, but we don't care when coming
// from Win2k.
//
if (status == Uninstall_Valid) { status = SanityCheck (QUICK_CHECK, NULL, NULL);
if (ComponentType == Uninstall_FatToNtfsConversion) { if (status == Uninstall_OldImage) { //
// Do not suppress convert.exe warning even if uninstall is old
//
status = Uninstall_Valid; } } }
if (status == Uninstall_Valid) { if (BackedUpOsVersion) { __try { orgVersionSize = BackedUpOsVersion->dwOSVersionInfoSize; orgVersionSize = min (orgVersionSize, sizeof (ourVersion)); CopyMemory (BackedUpOsVersion, &ourVersion, orgVersionSize); BackedUpOsVersion->dwOSVersionInfoSize = orgVersionSize; } __except (1) { status = Uninstall_Exception; } } }
pUninstallStatusToWin32Error (status); return status; }
ULONGLONG GetUninstallImageSize ( VOID ) { ULONGLONG diskSpace;
DeferredInit();
//
// SanityCheck returns the disk space used by the uninstall image,
// regardless if it is valid or not.
//
SanityCheck (QUICK_CHECK, NULL, &diskSpace);
return diskSpace; }
BOOL RemoveUninstallImage ( VOID ) { DeferredInit(); return DoCleanup(); }
BOOL pIsEligibleCaller( VOID ) { WCHAR callerExecutablePath[MAX_PATH]; WCHAR callerEtalonPath[MAX_PATH];
if(!GetSystemDirectoryW(callerEtalonPath, ARRAYSIZE(callerEtalonPath) - ARRAYSIZE(EXECUTABLE_FILE_NAME_LENGTH_W) - 1)){ return FALSE; } wcscat(AppendWackW(callerEtalonPath), EXECUTABLE_FILE_NAME_LENGTH_W);
if(GetModuleFileNameExW(GetCurrentProcess(), NULL, callerExecutablePath, ARRAYSIZE(callerExecutablePath))){ return (!_wcsicmp(callerExecutablePath, callerEtalonPath)); } return FALSE; }
BOOL ExecuteUninstall ( VOID ) { UNINSTALLSTATUS status;
DeferredInit();
if(!pIsEligibleCaller()){ LOG((LOG_ERROR, "Uninstall was executed by malicious executable")); SetLastError(ERROR_ACCESS_DENIED); return FALSE; }
status = SanityCheck (VERIFY_CAB, NULL, NULL);
if (status != Uninstall_Valid && status != Uninstall_OldImage) { pUninstallStatusToWin32Error (status); return FALSE; }
return DoUninstall(); }
|