248 lines
6 KiB
C++
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
|
||
|
|