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.
239 lines
6.0 KiB
239 lines
6.0 KiB
/*++
|
|
|
|
Copyright (c) 2000-2002 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
|
|
03/12/2002 robkenny Security review
|
|
|
|
--*/
|
|
|
|
#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
|
|
|
|
|
|
/*++
|
|
|
|
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))
|
|
{
|
|
// 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
|
|
|