windows-nt/Source/XPSP1/NT/windows/appcompat/shims/general/removereadonlyattribute.cpp
2020-09-26 16:20:57 +08:00

248 lines
6 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
RemoveReadOnlyAttribute.cpp
Abstract:
Removes read only attributes from directories: used to fix some apps that
aren't used to shell folders being read-only.
Notes:
This is a general purpose shim.
History:
01/03/2000 a-jamd Created
12/02/2000 linstev Separated functionality into 2 shims: this one and EmulateCDFS
--*/
#include "precomp.h"
IMPLEMENT_SHIM_BEGIN(RemoveReadOnlyAttribute)
#include "ShimHookMacro.h"
APIHOOK_ENUM_BEGIN
APIHOOK_ENUM_ENTRY(GetFileAttributesW)
APIHOOK_ENUM_ENTRY(GetFileAttributesA)
APIHOOK_ENUM_ENTRY(FindFirstFileW)
APIHOOK_ENUM_ENTRY(FindFirstFileA)
APIHOOK_ENUM_ENTRY(FindNextFileW)
APIHOOK_ENUM_ENTRY(FindNextFileA)
APIHOOK_ENUM_ENTRY(GetFileInformationByHandle)
APIHOOK_ENUM_END
typedef struct _FINDFILE_HANDLE
{
HANDLE DirectoryHandle;
PVOID FindBufferBase;
PVOID FindBufferNext;
ULONG FindBufferLength;
ULONG FindBufferValidLength;
RTL_CRITICAL_SECTION FindBufferLock;
} FINDFILE_HANDLE, *PFINDFILE_HANDLE;
/*++
Remove read only attribute if it's a directory
--*/
DWORD
APIHOOK(GetFileAttributesA)(LPCSTR lpFileName)
{
DWORD dwFileAttributes = ORIGINAL_API(GetFileAttributesA)(lpFileName);
// Check for READONLY and DIRECTORY attributes
if ((dwFileAttributes != INT_PTR(-1)) &&
(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(dwFileAttributes & FILE_ATTRIBUTE_READONLY))
{
// Flip the read-only bit.
LOGN( eDbgLevelWarning, "[GetFileAttributesA] Removing FILE_ATTRIBUTE_READONLY");
dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
}
return dwFileAttributes;
}
/*++
Remove read only attribute if it's a directory
--*/
DWORD
APIHOOK(GetFileAttributesW)(LPCWSTR wcsFileName)
{
DWORD dwFileAttributes = ORIGINAL_API(GetFileAttributesW)(wcsFileName);
// Check for READONLY and DIRECTORY attributes
if ((dwFileAttributes != INT_PTR(-1)) &&
(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(dwFileAttributes & FILE_ATTRIBUTE_READONLY))
{
// Flip the read-only bit.
LOGN( eDbgLevelWarning, "[GetFileAttributesW] Removing FILE_ATTRIBUTE_READONLY");
dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
}
return dwFileAttributes;
}
/*++
Remove read only attribute if it's a directory
--*/
HANDLE
APIHOOK(FindFirstFileA)(
LPCSTR lpFileName,
LPWIN32_FIND_DATAA lpFindFileData
)
{
HANDLE hFindFile = ORIGINAL_API(FindFirstFileA)(lpFileName, lpFindFileData);
if ((hFindFile != INVALID_HANDLE_VALUE) &&
(lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_READONLY))
{
// Flip the read-only bit
LOGN( eDbgLevelWarning, "[FindFirstFileA] Removing FILE_ATTRIBUTE_READONLY");
lpFindFileData->dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
}
return hFindFile;
}
/*++
Remove read only attribute if it's a directory.
--*/
HANDLE
APIHOOK(FindFirstFileW)(
LPCWSTR wcsFileName,
LPWIN32_FIND_DATAW lpFindFileData
)
{
HANDLE hFindFile = ORIGINAL_API(FindFirstFileW)(wcsFileName, lpFindFileData);
if ((hFindFile != INVALID_HANDLE_VALUE) &&
(lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_READONLY))
{
// It's a directory: flip the read-only bit
LOGN( eDbgLevelInfo, "[FindFirstFileW] Removing FILE_ATTRIBUTE_READONLY");
lpFindFileData->dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
}
return hFindFile;
}
/*++
Remove read only attribute if it's a directory.
--*/
BOOL
APIHOOK(FindNextFileA(
HANDLE hFindFile,
LPWIN32_FIND_DATAA lpFindFileData
)
{
BOOL bRet = ORIGINAL_API(FindNextFileA)(hFindFile, lpFindFileData);
if (bRet &&
(lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_READONLY))
{
// Flip the read-only bit.
LOGN( eDbgLevelWarning, "[FindNextFileA] Removing FILE_ATTRIBUTE_READONLY"));
lpFindFileData->dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
}
return bRet;
}
/*++
Remove read only attribute if it's a directory.
--*/
BOOL
APIHOOK(FindNextFileW)(
HANDLE hFindFile,
LPWIN32_FIND_DATAW lpFindFileData
)
{
BOOL bRet = ORIGINAL_API(FindNextFileW)(hFindFile, lpFindFileData);
if (bRet &&
(lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_READONLY))
{
// Flip the read-only bit
LOGN( eDbgLevelWarning, "[FindNextFileW] Removing FILE_ATTRIBUTE_READONLY");
lpFindFileData->dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
}
return bRet;
}
/*++
Remove read only attribute if it's a directory.
--*/
BOOL
APIHOOK(GetFileInformationByHandle)(
HANDLE hFile,
LPBY_HANDLE_FILE_INFORMATION lpFileInformation
)
{
BOOL bRet = ORIGINAL_API(GetFileInformationByHandle)(hFile, lpFileInformation);
if (bRet &&
(lpFileInformation->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(lpFileInformation->dwFileAttributes & FILE_ATTRIBUTE_READONLY))
{
// It's a CDROM too. Flip the read-only bit.
LOGN( eDbgLevelWarning, "[GetFileInformationByHandle] Removing FILE_ATTRIBUTE_READONLY");
lpFileInformation->dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
}
return bRet;
}
/*++
Register hooked functions
--*/
HOOK_BEGIN
APIHOOK_ENTRY(KERNEL32.DLL, GetFileAttributesW);
APIHOOK_ENTRY(KERNEL32.DLL, GetFileAttributesA);
APIHOOK_ENTRY(KERNEL32.DLL, FindFirstFileW);
APIHOOK_ENTRY(KERNEL32.DLL, FindFirstFileA);
APIHOOK_ENTRY(KERNEL32.DLL, FindNextFileW);
APIHOOK_ENTRY(KERNEL32.DLL, FindNextFileA);
APIHOOK_ENTRY(KERNEL32.DLL, GetFileInformationByHandle);
HOOK_END
IMPLEMENT_SHIM_END