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

/*++
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();
}