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.
 
 
 
 
 
 

474 lines
19 KiB

/*++
Copyright (c) Microsoft Corporation
Module Name:
sxssfc_repairshortnames.cpp
Abstract:
after textmode setup extracts asms*.cab and write hivesxs.inf,
write the correct shortnames into the registry
Author:
Jay Krell (Jaykrell) June 2002
Revision History:
--*/
#include "stdinc.h"
#include "recover.h"
#include "cassemblyrecoveryinfo.h"
#include "sxssfcscan.h"
BOOL
SxspSetupGetSourceInfo(
HINF InfHandle, // handle to the INF file
UINT SourceId, // ID of the source media
UINT InfoDesired, // information to retrieve
CBaseStringBuffer &buff,
LPDWORD RequiredSize // optional, buffer size needed
)
{
FN_PROLOG_WIN32
CStringBufferAccessor acc;
DWORD RequiredSize2 = 0;
BOOL fTooSmall = FALSE;
if (RequiredSize == NULL)
{
RequiredSize = &RequiredSize2;
}
acc.Attach(&buff);
IFW32FALSE_EXIT_UNLESS2(
::SetupGetSourceInfoW(
InfHandle,
SourceId,
InfoDesired,
acc,
acc.GetBufferCchAsDWORD(),
RequiredSize
),
LIST_1(ERROR_INSUFFICIENT_BUFFER),
fTooSmall);
if (fTooSmall)
{
acc.Detach();
IFW32FALSE_EXIT(buff.Win32ResizeBuffer(*RequiredSize + 1, eDoNotPreserveBufferContents));
acc.Attach(&buff);
IFW32FALSE_EXIT(
::SetupGetSourceInfoW(
InfHandle,
SourceId,
InfoDesired,
acc,
acc.GetBufferCchAsDWORD(),
RequiredSize
));
}
FN_EPILOG
}
BOOL
SxspGetWindowsSetupPrompt(
CBaseStringBuffer &rbuffWinsxsRoot
)
//
// This code is based closely on code in base\ntsetup\syssetup\copy.c
// Legacy wfp is a little different, it opens layout.inf, but the results
// should be the same.
//
{
FN_PROLOG_WIN32
CFusionSetupInfFile InfFile;
CStringBuffer InfPath;
const static UNICODE_STRING inf = RTL_CONSTANT_STRING(L"inf");
const static UNICODE_STRING filename_inf = RTL_CONSTANT_STRING(L"layout.inf");
UINT SourceId = 0;
const PCWSTR SystemRoot = USER_SHARED_DATA->NtSystemRoot;
IFW32FALSE_EXIT(InfPath.Win32Assign(SystemRoot, ::wcslen(SystemRoot)));
IFW32FALSE_EXIT(InfPath.Win32AppendPathElement(&inf));
IFW32FALSE_EXIT(InfPath.Win32AppendPathElement(&filename_inf));
IFW32FALSE_EXIT(InfFile.Win32SetupOpenInfFileW(InfPath, NULL, INF_STYLE_WIN4, NULL));
IFW32FALSE_EXIT(::SetupGetSourceFileLocationW(InfFile, NULL, L"shell32.dll", &SourceId, NULL, 0, NULL));
IFW32FALSE_EXIT(::SxspSetupGetSourceInfo(InfFile, SourceId, SRCINFO_DESCRIPTION, rbuffWinsxsRoot, NULL));
FN_EPILOG
}
BOOL
SxspModifyRegistryData(
DWORD Flags
)
{
//
// In postbuild we run sxsofflineinstall.
// This includes creating hivesxs.inf to populate the registry
// with data needed for windows file protection.
//
// The data includes short names, but we don't know the short names
// until textmode setup. The code in textmode setup is fairly generic
// and just expands .cabs.
//
// We do not need the short names to be correct until we expect
// bogus file changes against short file names to induce recovery
// of assemblies. It is reasonable to assume that these won't happen
// until setup is done and the system is running.
//
// Therefore it is sufficient to fixup the shortnames after textmode setup,
// such as in a RunOnce entry.
//
/*
Here is an example of what we are fixing up.
[AddReg]
HKLM,"\Software\Microsoft\Windows\CurrentVersion\SideBySide\Installations
HKLM,"\...\IA64_Microsoft.Windows.Common-Controls_6595b64144ccf1df_5.82.0.0_x-ww_B9C4A0A5","Identity",0x00001000,"Microsoft.Windows.Common-Controls,processorArchitecture="IA64",publicKeyToken="6595b64144ccf1df",type="win32",version="5.82.0.0""
HKLM,"\...\IA64_Microsoft.Windows.Common-Controls_6595b64144ccf1df_5.82.0.0_x-ww_B9C4A0A5","Catalog",0x00011001,0x00000001
HKLM,"\...\IA64_Microsoft.Windows.Common-Controls_6595b64144ccf1df_5.82.0.0_x-ww_B9C4A0A5","ManifestSHA1Hash",0x00001001,3b,26,4a,90,08,0f,6a,dd,b6,00,55,5b,a5,a4,9e,21,ad,e3,90,84
HKLM,"\...\IA64_Microsoft.Windows.Common-Controls_6595b64144ccf1df_5.82.0.0_x-ww_B9C4A0A5","ShortName",0x00001000,"IA64_M~2.0_X"
HKLM,"\...\IA64_Microsoft.Windows.Common-Controls_6595b64144ccf1df_5.82.0.0_x-ww_B9C4A0A5","ShortCatalogName",0x00001000,"IA64_M~4.CAT"
HKLM,"\...\IA64_Microsoft.Windows.Common-Controls_6595b64144ccf1df_5.82.0.0_x-ww_B9C4A0A5","ShortManifestName",0x00001000,"IA64_M~4.MAN"
HKLM,"\...\IA64_Microsoft.Windows.Common-Controls_6595b64144ccf1df_5.82.0.0_x-ww_B9C4A0A5","PublicKeyToken",0x00001001,65,95,b6,41,44,cc,f1,df
HKLM,"\...\IA64_Microsoft.Windows.Common-Controls_6595b64144ccf1df_5.82.0.0_x-ww_B9C4A0A5","Codebase",0x00001000,"x-ms-windows-source:W_fusi_bin.IA64chk/asms/58200/Msft/Windows/Common/Controls/Controls.man"
HKLM,"\...\IA64_Microsoft.Windows.Common-Controls_6595b64144ccf1df_5.82.0.0_x-ww_B9C4A0A5\Codebases\OS","Prompt",0x00001000,"(textmode setup placeholder)"
HKLM,"\...\IA64_Microsoft.Windows.Common-Controls_6595b64144ccf1df_5.82.0.0_x-ww_B9C4A0A5\Codebases\OS","URL",0x00001000,"x-ms-windows-source:W_fusi_bin.IA64chk/asms/58200/Msft/Windows/Common/Controls/Controls.man"
HKLM,"\...\IA64_Microsoft.Windows.Common-Controls_6595b64144ccf1df_5.82.0.0_x-ww_B9C4A0A5\Files\0","",0x00001000,"comctl32.dll"
HKLM,"\...\IA64_Microsoft.Windows.Common-Controls_6595b64144ccf1df_5.82.0.0_x-ww_B9C4A0A5\Files\0","SHA1",0x00001001,76,c3,6e,4c,c4,10,14,7f,38,c8,bc,cd,4b,4f,b2,90,d8,0a,7c,d7
HKLM,"\...\IA64_Microsoft.Windows.Common-Controls_6595b64144ccf1df_5.82.0.0_x-ww_B9C4A0A5\References","OS",0x00001000,"Foom"
IA64_Microsoft.Windows.Common-Controls_6595b64144ccf1df_5.82.0.0_x-ww_B9C4A0A5
*/
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
CFusionRegKey regkeyInstallations;
CFusionRegKey regkeyInstallation;
DWORD dwRegSubKeyIndex = 0;
BOOL fNoMoreItems = FALSE;
FILETIME LastWriteFileTimeIgnored = { 0 };
CTinyStringBuffer buffInstallationName;
CTinyStringBuffer buffWinsxsRoot;
CTinyStringBuffer *buffLongFullPath = NULL;
CTinyStringBuffer buffShortFullPath;
CTinyStringBuffer buffShortPathLastElement;
CTinyStringBuffer buffTextualIdentity;
CTinyStringBuffer buffEmpty;
CTinyStringBuffer buffWindowsSetupPrompt;
CTinyStringBuffer buffCurrentPromptInRegistry;
CTinyStringBuffer buffFullPathToManifest;
CTinyStringBuffer buffFullPathToCatalog;
CTinyStringBuffer buffFullPathToPayloadDirectory;
SIZE_T i = 0;
const bool fRepairAll = ((Flags & SXSP_MODIFY_REGISTRY_DATA_FLAG_REPAIR_ALL) != 0);
const bool fRepairShort = fRepairAll || ((Flags & SXSP_MODIFY_REGISTRY_DATA_FLAG_REPAIR_SHORT_NAMES) != 0);
const bool fDeleteShort = ((Flags & SXSP_MODIFY_REGISTRY_DATA_FLAG_DELETE_SHORT_NAMES) != 0);
const bool fRepairPrompt = fRepairAll || ((Flags & SXSP_MODIFY_REGISTRY_DATA_FLAG_REPAIR_OFFLINE_INSTALL_REFRESH_PROMPTS) != 0);
const bool fValidate = ((Flags & SXSP_MODIFY_REGISTRY_DATA_VALIDATE) != 0);
#if DBG
bool fDbgPrintBecauseHashValidationFailed = false;
#endif
PARAMETER_CHECK(Flags != 0);
PARAMETER_CHECK((Flags & ~SXSP_MODIFY_REGISTRY_DATA_FLAG_VALID_FLAGS) == 0);
IFW32FALSE_EXIT(::SxspGetAssemblyRootDirectory(buffWinsxsRoot));
IFW32FALSE_EXIT(::SxspOpenAssemblyInstallationKey(0, KEY_READ | KEY_SET_VALUE | FUSIONP_KEY_WOW64_64KEY, regkeyInstallations));
if (fRepairPrompt)
{
IFW32FALSE_EXIT(::SxspGetWindowsSetupPrompt(buffWindowsSetupPrompt));
}
for ((dwRegSubKeyIndex = 0), (fNoMoreItems = FALSE); !fNoMoreItems ; ++dwRegSubKeyIndex)
{
bool fNotFound = false;
CSmartAssemblyIdentity AssemblyIdentity;
PROBING_ATTRIBUTE_CACHE AttributeCache = { 0 };
CFusionRegKey codebase_os;
IFW32FALSE_EXIT(
regkeyInstallations.EnumKey(
dwRegSubKeyIndex,
buffInstallationName,
&LastWriteFileTimeIgnored,
&fNoMoreItems));
if (fNoMoreItems)
{
break;
}
IFW32FALSE_EXIT(
regkeyInstallations.OpenSubKey(
regkeyInstallation,
buffInstallationName,
KEY_READ | KEY_SET_VALUE | ((fRepairPrompt || fValidate) ? KEY_ENUMERATE_SUB_KEYS : 0)
));
IFW32FALSE_EXIT(
regkeyInstallation.GetValue(
CSMD_TOPLEVEL_IDENTITY,
buffTextualIdentity
));
IFW32FALSE_EXIT(::SxspCreateAssemblyIdentityFromTextualString(buffTextualIdentity, &AssemblyIdentity));
typedef struct _SXSP_GENERATE_PATH_FUNCTION_REGISTRY_VALUE_NAME
{
BOOL (*GeneratePathFunction)(
IN const CBaseStringBuffer &AssemblyRootDirectory,
IN PCASSEMBLY_IDENTITY pAssemblyIdentity,
IN OUT PPROBING_ATTRIBUTE_CACHE ppac,
IN OUT CBaseStringBuffer &PathBuffer
);
PCWSTR RegistryValueName;
} SXSP_GENERATE_PATH_FUNCTION_REGISTRY_VALUE_NAME, *PSXSP_GENERATE_PATH_FUNCTION_REGISTRY_VALUE_NAME;
typedef const SXSP_GENERATE_PATH_FUNCTION_REGISTRY_VALUE_NAME *PCSXSP_GENERATE_PATH_FUNCTION_REGISTRY_VALUE_NAME;
const static SXSP_GENERATE_PATH_FUNCTION_REGISTRY_VALUE_NAME s_rgFunctionRegistryValueName[] =
{
//
// Note that policies are not currently wfp protected,
// but it's easy and obvious to put reasonable data
// in the registry for them.
//
{ &::SxspGenerateSxsPath_FullPathToManifestOrPolicyFile, CSMD_TOPLEVEL_SHORTMANIFEST },
{ &::SxspGenerateSxsPath_FullPathToCatalogFile, CSMD_TOPLEVEL_SHORTCATALOG },
{ &::SxspGenerateSxsPath_FullPathToPayloadOrPolicyDirectory, CSMD_TOPLEVEL_SHORTNAME }
};
CBaseStringBuffer * const rgpbuffFullPaths[] =
{
&buffFullPathToManifest,
&buffFullPathToCatalog,
&buffFullPathToPayloadDirectory
};
//
// first generate all three fullpaths
//
for (i = 0 ; i != NUMBER_OF(s_rgFunctionRegistryValueName) ; ++i)
{
const PCSXSP_GENERATE_PATH_FUNCTION_REGISTRY_VALUE_NAME p = &s_rgFunctionRegistryValueName[i];
CBaseStringBuffer * const pbuffLongFullPath = rgpbuffFullPaths[i];
IFW32FALSE_EXIT((*p->GeneratePathFunction)(
buffWinsxsRoot,
AssemblyIdentity,
&AttributeCache,
*pbuffLongFullPath));
IFW32FALSE_EXIT(pbuffLongFullPath->Win32RemoveTrailingPathSeparators());
}
//
// optionally repair short names
//
if (fRepairShort)
{
for (i = 0 ; i != NUMBER_OF(s_rgFunctionRegistryValueName) ; ++i)
{
const PCSXSP_GENERATE_PATH_FUNCTION_REGISTRY_VALUE_NAME p = &s_rgFunctionRegistryValueName[i];
CBaseStringBuffer * const pbuffLongFullPath = rgpbuffFullPaths[i];
{
DWORD dwWin32Error = NO_ERROR;
IFW32FALSE_EXIT(
::SxspGetShortPathName(
*pbuffLongFullPath,
buffShortFullPath,
dwWin32Error,
static_cast<SIZE_T>(4),
ERROR_PATH_NOT_FOUND,
ERROR_FILE_NOT_FOUND,
ERROR_BAD_NET_NAME,
ERROR_BAD_NETPATH));
if (dwWin32Error == NO_ERROR)
{
IFW32FALSE_EXIT(buffShortFullPath.Win32GetLastPathElement(buffShortPathLastElement));
IFW32FALSE_EXIT(regkeyInstallation.SetValue(p->RegistryValueName, buffShortPathLastElement));
}
}
}
}
//
// optionally delete short names
//
if (fDeleteShort)
{
for (i = 0 ; i != NUMBER_OF(s_rgFunctionRegistryValueName) ; ++i)
{
IFW32FALSE_EXIT(regkeyInstallation.DeleteValue(s_rgFunctionRegistryValueName[i].RegistryValueName));
}
}
//
// validate hashes and repair prompts
// BE SURE TO validate hashes first, as we filter what assemblies
// to repair based on the placeholder prompt
//
IFW32FALSE_EXIT_UNLESS2(
regkeyInstallation.OpenSubKey(
codebase_os,
CSMD_TOPLEVEL_CODEBASES L"\\" SXS_INSTALL_REFERENCE_SCHEME_OSINSTALL_STRING,
KEY_READ | KEY_SET_VALUE),
LIST_2(ERROR_PATH_NOT_FOUND, ERROR_FILE_NOT_FOUND),
fNotFound);
//
// OpenSubKey actually eats some errors, so you can't trust
// fNotFound or the BOOL returned.
//
if (!fNotFound && codebase_os.IsValid())
{
fNotFound = false;
IFW32FALSE_EXIT_UNLESS2(
codebase_os.GetValue(
CSMD_CODEBASES_PROMPTSTRING,
buffCurrentPromptInRegistry),
LIST_2(ERROR_PATH_NOT_FOUND, ERROR_FILE_NOT_FOUND),
fNotFound);
if (!fNotFound)
{
if (::FusionpEqualStringsI(
buffCurrentPromptInRegistry,
SXSP_OFFLINE_INSTALL_REFRESH_PROMPT_PLACEHOLDER,
NUMBER_OF(SXSP_OFFLINE_INSTALL_REFRESH_PROMPT_PLACEHOLDER) - 1))
{
if (fValidate)
{
CAssemblyRecoveryInfo AssemblyRecoveryInfo;
bool fNoAssembly = false;
DWORD dwResult = 0;
IFW32FALSE_EXIT(AssemblyRecoveryInfo.Initialize());
IFW32FALSE_EXIT(AssemblyRecoveryInfo.AssociateWithAssembly(buffInstallationName, fNoAssembly));
IFW32FALSE_EXIT(::SxspValidateEntireAssembly(
SXS_VALIDATE_ASM_FLAG_CHECK_EVERYTHING,
AssemblyRecoveryInfo,
dwResult,
AssemblyIdentity
));
if (dwResult != SXS_VALIDATE_ASM_FLAG_VALID_PERFECT)
{
::FusionpDbgPrintEx(
FUSION_DBG_LEVEL_SETUPLOG,
"The assembly %ls contains file hash errors.\n",
static_cast<PCWSTR>(buffTextualIdentity));
::FusionpDbgPrintEx(
FUSION_DBG_LEVEL_ERROR,
"SXS.DLL %s: The assembly %ls contains file hash errors.\n",
__FUNCTION__,
static_cast<PCWSTR>(buffTextualIdentity));
::FusionpSetLastWin32Error(ERROR_SXS_FILE_HASH_MISMATCH);
#if DBG
fDbgPrintBecauseHashValidationFailed = true;
#endif
goto Exit;
}
}
if (fRepairPrompt)
{
IFW32FALSE_EXIT(
codebase_os.SetValue(
CSMD_CODEBASES_PROMPTSTRING,
buffWindowsSetupPrompt));
}
}
}
}
}
fSuccess = TRUE;
Exit:
if ((!fSuccess && ::FusionpDbgWouldPrintAtFilterLevel(FUSION_DBG_LEVEL_ERROR))
#if DBG
|| fDbgPrintBecauseHashValidationFailed
#endif
)
{
//
// multiple dbgprints due to 511 limit
// use tick count to link together seperate prints
//
CSxsPreserveLastError ple;
DWORD TickCount = ::GetTickCount();
::FusionpDbgPrintEx(
FUSION_DBG_LEVEL_ERROR,
"SXS.DLL: %s 0x%lx error 0x%lx\n", __FUNCTION__, TickCount, ple.LastError());
::FusionpDbgPrintEx(
FUSION_DBG_LEVEL_ERROR,
"SXS.DLL: %s 0x%lx dwRegSubKeyIndex 0x%lx\n", __FUNCTION__, TickCount, dwRegSubKeyIndex);
::FusionpDbgPrintEx(
FUSION_DBG_LEVEL_ERROR,
"SXS.DLL: %s 0x%lx i 0x%Ix\n", __FUNCTION__, TickCount, i);
::FusionpDbgPrintEx(
FUSION_DBG_LEVEL_ERROR,
"SXS.DLL: %s 0x%lx buffInstallationName %ls\n", __FUNCTION__, TickCount, static_cast<PCWSTR>(buffInstallationName));
::FusionpDbgPrintEx(
FUSION_DBG_LEVEL_ERROR,
"SXS.DLL: %s 0x%lx buffTextualIdentity %ls\n", __FUNCTION__, TickCount, static_cast<PCWSTR>(buffTextualIdentity));
::FusionpDbgPrintEx(
FUSION_DBG_LEVEL_ERROR,
"SXS.DLL: %s 0x%lx buffFullPathToManifest %ls\n", __FUNCTION__, TickCount, static_cast<PCWSTR>(buffFullPathToManifest));
::FusionpDbgPrintEx(
FUSION_DBG_LEVEL_ERROR,
"SXS.DLL: %s 0x%lx buffFullPathToCatalog %ls\n", __FUNCTION__, TickCount, static_cast<PCWSTR>(buffFullPathToCatalog));
::FusionpDbgPrintEx(
FUSION_DBG_LEVEL_ERROR,
"SXS.DLL: %s 0x%lx buffFullPathToPayloadDirectory %ls\n", __FUNCTION__, TickCount, static_cast<PCWSTR>(buffFullPathToPayloadDirectory));
::FusionpDbgPrintEx(
FUSION_DBG_LEVEL_ERROR,
"SXS.DLL: %s 0x%lx buffShortFullPath %ls\n", __FUNCTION__, TickCount, static_cast<PCWSTR>(buffShortFullPath));
::FusionpDbgPrintEx(
FUSION_DBG_LEVEL_ERROR,
"SXS.DLL: %s 0x%lx buffShortPathLastElement %ls\n", __FUNCTION__, TickCount, static_cast<PCWSTR>(buffShortPathLastElement));
ple.Restore();
}
return fSuccess;
}
BOOL
SxspDeleteShortNamesInRegistry(
VOID
)
{
return ::SxspModifyRegistryData(SXSP_MODIFY_REGISTRY_DATA_FLAG_DELETE_SHORT_NAMES);
}
STDAPI
DllInstall(
BOOL fInstall,
PCWSTR pszCmdLine
)
{
FN_PROLOG_HR
//
// Just ignore uninstall requests.
//
if (!fInstall)
{
FN_SUCCESSFUL_EXIT();
}
//
// It doesn't look like guimode setup ever passes in
// anything for pszCmdLine, so we don't look at it.
//
IFW32FALSE_EXIT(::SxspModifyRegistryData(SXSP_MODIFY_REGISTRY_DATA_FLAG_REPAIR_ALL | SXSP_MODIFY_REGISTRY_DATA_VALIDATE));
FN_EPILOG
}