274 lines
7.3 KiB
C++
274 lines
7.3 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 2000-2002 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
CorrectVerInstallFile.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
In Windows XP, due to a modification in the caching between MoveFile and
|
||
|
DeleteFile API's, when the VerInstallFileW API was called, the SHORT
|
||
|
filename gets SET instead of the long filename.
|
||
|
|
||
|
This SHIM corrects this problem which effects the installation of a few
|
||
|
apps when the older version is still present.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
This can be a layer shim. This is a general purpose shim.
|
||
|
|
||
|
History:
|
||
|
|
||
|
04/05/2001 prashkud Created
|
||
|
02/28/2002 mnikkel Added check for nulls passed in for temporary file name
|
||
|
buffer and size. This was not checked on win9x but is
|
||
|
immediately used on XP.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
|
||
|
IMPLEMENT_SHIM_BEGIN(CorrectVerInstallFile)
|
||
|
#include "ShimHookMacro.h"
|
||
|
|
||
|
APIHOOK_ENUM_BEGIN
|
||
|
APIHOOK_ENUM_ENTRY(VerInstallFileW)
|
||
|
APIHOOK_ENUM_ENTRY(VerInstallFileA)
|
||
|
APIHOOK_ENUM_END
|
||
|
|
||
|
/*++
|
||
|
|
||
|
GetTitle takes the app path and returns just the EXE name.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
VOID
|
||
|
SplitTitleAndPath(CString& csAppName, CString& csAppTitle)
|
||
|
{
|
||
|
//
|
||
|
// Go to the first '\' from the end.
|
||
|
// The return value is the number of characters
|
||
|
// from the beginning of the string starting at
|
||
|
// index 0.
|
||
|
//
|
||
|
int len = csAppName.ReverseFind(L'\\');
|
||
|
if (len)
|
||
|
{
|
||
|
csAppTitle.Delete(0, len+1);
|
||
|
}
|
||
|
int DirLen = csAppName.GetLength() - len;
|
||
|
csAppName.Delete(len, DirLen);
|
||
|
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
APIHOOK(VerInstallFileA)(
|
||
|
DWORD uFlags,
|
||
|
LPSTR szSrcFileName,
|
||
|
LPSTR szDestFileName,
|
||
|
LPSTR szSrcDir,
|
||
|
LPSTR szDestDir,
|
||
|
LPSTR szCurDir,
|
||
|
LPSTR szTmpFile,
|
||
|
PUINT lpuTmpFileLen
|
||
|
)
|
||
|
{
|
||
|
CHAR DummyBuffer[MAX_PATH];
|
||
|
UINT DummySize = MAX_PATH;
|
||
|
DWORD dwRet = 0;
|
||
|
|
||
|
|
||
|
// check for a null szTmpFile or a null lpuTmpFileLen.
|
||
|
if (szTmpFile == NULL)
|
||
|
{
|
||
|
szTmpFile = DummyBuffer;
|
||
|
DPFN(eDbgLevelInfo, "VerInstallFileA using dummy TmpFile.");
|
||
|
}
|
||
|
|
||
|
if (lpuTmpFileLen == NULL)
|
||
|
{
|
||
|
lpuTmpFileLen = &DummySize;
|
||
|
DPFN(eDbgLevelInfo, "VerInstallFileA using dummy TmpFileLen.");
|
||
|
}
|
||
|
|
||
|
CSTRING_TRY
|
||
|
{
|
||
|
CString csDestFilePath(szDestDir);
|
||
|
CString csDestFileName(szDestFileName);
|
||
|
csDestFilePath.AppendPath(csDestFileName);
|
||
|
|
||
|
//
|
||
|
// Now csDestFileName possibly contains the SHORT path name
|
||
|
// Convert it into long pathname
|
||
|
//
|
||
|
DWORD dwAttr = GetFileAttributesW(csDestFilePath.Get());
|
||
|
if ((dwAttr != 0xFFFFFFFF) &&
|
||
|
(dwAttr != FILE_ATTRIBUTE_DIRECTORY))
|
||
|
{
|
||
|
//
|
||
|
// This file exists in the current destination directory.
|
||
|
// This API had problems replacing it if the filename
|
||
|
// is a SHORT name. Convert it into LONG name.
|
||
|
//
|
||
|
|
||
|
if (csDestFilePath.GetLongPathNameW())
|
||
|
{
|
||
|
DPFN( eDbgLevelWarning, "Short Path \
|
||
|
converted to Long Path = %S",
|
||
|
csDestFilePath.Get());
|
||
|
|
||
|
csDestFileName = csDestFilePath;
|
||
|
SplitTitleAndPath(csDestFilePath,csDestFileName);
|
||
|
|
||
|
dwRet= ORIGINAL_API(VerInstallFileA)(uFlags,szSrcFileName,
|
||
|
(char*)csDestFileName.GetAnsi(), szSrcDir,
|
||
|
(char*)csDestFilePath.GetAnsi(), szCurDir,
|
||
|
szTmpFile,lpuTmpFileLen);
|
||
|
|
||
|
// If using the dummy buffer then they had a null temp buffer
|
||
|
// Set the buffer too small flag.
|
||
|
if (szTmpFile == DummyBuffer)
|
||
|
{
|
||
|
dwRet &= VIF_BUFFTOOSMALL;
|
||
|
}
|
||
|
|
||
|
return dwRet;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
CSTRING_CATCH
|
||
|
{
|
||
|
DPFN(eDbgLevelError,
|
||
|
"Exception raised ! Calling Original API");
|
||
|
}
|
||
|
|
||
|
dwRet = ORIGINAL_API(VerInstallFileA)(uFlags,szSrcFileName,szDestFileName,
|
||
|
szSrcDir,szDestDir,szCurDir,szTmpFile,lpuTmpFileLen);
|
||
|
|
||
|
// If using the dummy buffer then they had a null temp buffer
|
||
|
// Set the buffer too small flag.
|
||
|
if (szTmpFile == DummyBuffer)
|
||
|
{
|
||
|
dwRet &= VIF_BUFFTOOSMALL;
|
||
|
}
|
||
|
|
||
|
return dwRet;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Modify the Short filename to its corresponding long filename.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
DWORD
|
||
|
APIHOOK(VerInstallFileW)(
|
||
|
DWORD uFlags,
|
||
|
LPWSTR szSrcFileName,
|
||
|
LPWSTR szDestFileName,
|
||
|
LPWSTR szSrcDir,
|
||
|
LPWSTR szDestDir,
|
||
|
LPWSTR szCurDir,
|
||
|
LPWSTR szTmpFile,
|
||
|
PUINT lpuTmpFileLen
|
||
|
)
|
||
|
{
|
||
|
WCHAR DummyBuffer[MAX_PATH];
|
||
|
UINT DummySize = MAX_PATH;
|
||
|
DWORD dwRet = 0;
|
||
|
|
||
|
|
||
|
// check for a null szTmpFile or a null lpuTmpFileLen.
|
||
|
if (szTmpFile == NULL)
|
||
|
{
|
||
|
szTmpFile = DummyBuffer;
|
||
|
DPFN(eDbgLevelInfo, "VerInstallFileA using dummy TmpFile.");
|
||
|
}
|
||
|
|
||
|
if (lpuTmpFileLen == NULL)
|
||
|
{
|
||
|
lpuTmpFileLen = &DummySize;
|
||
|
DPFN(eDbgLevelInfo, "VerInstallFileA using dummy TmpFileLen.");
|
||
|
}
|
||
|
|
||
|
CSTRING_TRY
|
||
|
{
|
||
|
CString csDestFilePath(szDestDir);
|
||
|
csDestFilePath.AppendPath(szDestFileName);
|
||
|
|
||
|
//
|
||
|
// Now csDestFileName possibly contains the SHORT path name
|
||
|
// Convert it into long pathname
|
||
|
//
|
||
|
DWORD dwAttr = GetFileAttributesW(csDestFilePath.Get());
|
||
|
if ((dwAttr != 0xFFFFFFFF) &&
|
||
|
(dwAttr != FILE_ATTRIBUTE_DIRECTORY))
|
||
|
{
|
||
|
//
|
||
|
// This file exists in the current destination directory.
|
||
|
// This API had problems replacing it if the filename
|
||
|
// is a SHORT name. Convert it into LONG name.
|
||
|
//
|
||
|
|
||
|
if (csDestFilePath.GetLongPathNameW())
|
||
|
{
|
||
|
DPFN( eDbgLevelWarning, "Short Path \
|
||
|
converted to Long Path = %S",
|
||
|
csDestFilePath.Get());
|
||
|
|
||
|
CString csDestFileName(csDestFilePath);
|
||
|
SplitTitleAndPath(csDestFilePath,csDestFileName);
|
||
|
|
||
|
dwRet = ORIGINAL_API(VerInstallFileW)(uFlags,szSrcFileName,
|
||
|
(WCHAR*)csDestFileName.Get(), szSrcDir,
|
||
|
(WCHAR*)csDestFilePath.Get(), szCurDir,
|
||
|
szTmpFile,lpuTmpFileLen);
|
||
|
|
||
|
// If using the dummy buffer then they had a null temp buffer
|
||
|
// Set the buffer too small flag.
|
||
|
if (szTmpFile == DummyBuffer)
|
||
|
{
|
||
|
dwRet &= VIF_BUFFTOOSMALL;
|
||
|
}
|
||
|
|
||
|
return dwRet;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
CSTRING_CATCH
|
||
|
{
|
||
|
DPFN( eDbgLevelError,
|
||
|
"Exception raised ! Calling Original API");
|
||
|
}
|
||
|
|
||
|
dwRet = ORIGINAL_API(VerInstallFileW)(uFlags,szSrcFileName,szDestFileName,
|
||
|
szSrcDir,szDestDir,szCurDir,szTmpFile,lpuTmpFileLen);
|
||
|
|
||
|
// If using the dummy buffer then they had a null temp buffer
|
||
|
// Set the buffer too small flag.
|
||
|
if (szTmpFile == DummyBuffer)
|
||
|
{
|
||
|
dwRet &= VIF_BUFFTOOSMALL;
|
||
|
}
|
||
|
|
||
|
return dwRet;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Register hooked functions
|
||
|
|
||
|
--*/
|
||
|
|
||
|
HOOK_BEGIN
|
||
|
APIHOOK_ENTRY(VERSION.DLL, VerInstallFileW)
|
||
|
APIHOOK_ENTRY(VERSION.DLL, VerInstallFileA)
|
||
|
HOOK_END
|
||
|
|
||
|
IMPLEMENT_SHIM_END
|
||
|
|