mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-31 12:08:41 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			613 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			613 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /**
 | |
|  * @file hooks.c
 | |
|  *
 | |
|  * @copyright 2015-2025 Bill Zissimopoulos
 | |
|  */
 | |
| /*
 | |
|  * This file is part of WinFsp.
 | |
|  *
 | |
|  * You can redistribute it and/or modify it under the terms of the GNU
 | |
|  * General Public License version 3 as published by the Free Software
 | |
|  * Foundation.
 | |
|  *
 | |
|  * Licensees holding a valid commercial license may use this software
 | |
|  * in accordance with the commercial license agreement provided in
 | |
|  * conjunction with the software.  The terms and conditions of any such
 | |
|  * commercial license agreement shall govern, supersede, and render
 | |
|  * ineffective any application of the GPLv3 license to this software,
 | |
|  * notwithstanding of any reference thereto in the software or
 | |
|  * associated repository.
 | |
|  */
 | |
| 
 | |
| #define WIN32_NO_STATUS
 | |
| #include <windows.h>
 | |
| #undef WIN32_NO_STATUS
 | |
| #include <winternl.h>
 | |
| #pragma warning(push)
 | |
| #pragma warning(disable:4005)           /* macro redefinition */
 | |
| #include <ntstatus.h>
 | |
| #pragma warning(pop)
 | |
| 
 | |
| #define WINFSP_TESTS_NO_HOOKS
 | |
| #include "winfsp-tests.h"
 | |
| #include <winfsp/winfsp.h>
 | |
| 
 | |
| #define FILENAMEBUF_SIZE                1024
 | |
| 
 | |
| static VOID PrepareFileName(PCWSTR FileName, PWSTR FileNameBuf)
 | |
| {
 | |
|     static WCHAR DevicePrefix[] =
 | |
|         L"\\\\?\\GLOBALROOT\\Device\\Volume{01234567-0123-0123-0101-010101010101}";
 | |
|     static WCHAR MemfsSharePrefix[] =
 | |
|         L"\\\\memfs\\share";
 | |
|     static const int TogglePercent = 25;
 | |
|     PWSTR P, EndP;
 | |
|     size_t L1, L2, L3;
 | |
| 
 | |
|     wcscpy_s(FileNameBuf, FILENAMEBUF_SIZE, FileName);
 | |
| 
 | |
|     if (OptCaseRandomize)
 | |
|     {
 | |
|         if (L'\\' == FileNameBuf[0] && L'\\' == FileNameBuf[1] &&
 | |
|             L'?' == FileNameBuf[2] && L'\\' == FileNameBuf[3] &&
 | |
|             testalpha(FileNameBuf[4]) && L':' == FileNameBuf[5] && L'\\' == FileNameBuf[6])
 | |
|             P = FileNameBuf + 6;
 | |
|         else if (0 == wcsncmp(FileNameBuf, DevicePrefix, wcschr(DevicePrefix, L'{') - DevicePrefix))
 | |
|             P = FileNameBuf + wcslen(DevicePrefix);
 | |
|         else if (L'\\' == FileNameBuf[0] && L'\\' == FileNameBuf[1])
 | |
|             P = FileNameBuf + 2;
 | |
|         else if (testalpha(FileNameBuf[0]) && L':' == FileNameBuf[1] && L'\\' == FileNameBuf[2])
 | |
|             P = FileNameBuf + 2;
 | |
|         else
 | |
|             P = FileNameBuf;
 | |
| 
 | |
|         for (EndP = P + wcslen(P); EndP > P; P++)
 | |
|             if (testalpha(*P) && myrand() <= (TogglePercent) * 0x7fff / 100)
 | |
|                 *P = togglealpha(*P);
 | |
|     }
 | |
| 
 | |
|     if (OptMountPoint && memfs_running)
 | |
|     {
 | |
|         if (L'\\' == FileNameBuf[0] && L'\\' == FileNameBuf[1] &&
 | |
|             L'?' == FileNameBuf[2] && L'\\' == FileNameBuf[3] &&
 | |
|             testalpha(FileNameBuf[4]) && L':' == FileNameBuf[5] && L'\\' == FileNameBuf[6])
 | |
|             ABORT("--mountpoint not supported with NTFS");
 | |
|         else if (0 == wcsncmp(FileNameBuf, DevicePrefix, wcschr(DevicePrefix, L'{') - DevicePrefix))
 | |
|             P = FileNameBuf + wcslen(DevicePrefix);
 | |
|         else if (0 == mywcscmp(
 | |
|             FileNameBuf, (int)wcslen(MemfsSharePrefix), MemfsSharePrefix, (int)wcslen(MemfsSharePrefix)))
 | |
|             P = FileNameBuf + wcslen(MemfsSharePrefix);
 | |
|         else if (testalpha(FileNameBuf[0]) && L':' == FileNameBuf[1] && L'\\' == FileNameBuf[2])
 | |
|             ABORT("--mountpoint not supported with NTFS");
 | |
|         else
 | |
|             P = FileNameBuf;
 | |
| 
 | |
|         L1 = wcslen(P) + 1;
 | |
|         L2 = wcslen(OptMountPoint);
 | |
|         memmove(FileNameBuf + FILENAMEBUF_SIZE - L1, P, L1 * sizeof(WCHAR));
 | |
|         memmove(FileNameBuf, OptMountPoint, L2 * sizeof(WCHAR));
 | |
|         memmove(FileNameBuf + L2, FileNameBuf + FILENAMEBUF_SIZE - L1, L1 * sizeof(WCHAR));
 | |
|     }
 | |
| 
 | |
|     if (OptShareName && memfs_running)
 | |
|     {
 | |
|         if (L'\\' == FileNameBuf[0] && L'\\' == FileNameBuf[1] &&
 | |
|             L'?' == FileNameBuf[2] && L'\\' == FileNameBuf[3] &&
 | |
|             testalpha(FileNameBuf[4]) && L':' == FileNameBuf[5] && L'\\' == FileNameBuf[6])
 | |
|             /* NTFS testing can only been done when the whole drive is being shared */
 | |
|             P = FileNameBuf + 6;
 | |
|         else if (0 == wcsncmp(FileNameBuf, DevicePrefix, wcschr(DevicePrefix, L'{') - DevicePrefix))
 | |
|             P = FileNameBuf + wcslen(DevicePrefix);
 | |
|         else if (0 == mywcscmp(
 | |
|             FileNameBuf, (int)wcslen(MemfsSharePrefix), MemfsSharePrefix, (int)wcslen(MemfsSharePrefix)))
 | |
|             P = FileNameBuf + wcslen(MemfsSharePrefix);
 | |
|         else if (testalpha(FileNameBuf[0]) && L':' == FileNameBuf[1] && L'\\' == FileNameBuf[2])
 | |
|             /* NTFS testing can only been done when the whole drive is being shared */
 | |
|             P = FileNameBuf + 2;
 | |
|         else
 | |
|             P = FileNameBuf;
 | |
| 
 | |
|         L1 = wcslen(P) + 1;
 | |
|         L2 = wcslen(OptShareComputer);
 | |
|         L3 = wcslen(OptShareName);
 | |
|         memmove(FileNameBuf + FILENAMEBUF_SIZE - L1, P, L1 * sizeof(WCHAR));
 | |
|         memmove(FileNameBuf, OptShareComputer, L2 * sizeof(WCHAR));
 | |
|         memmove(FileNameBuf + L2, OptShareName, L3 * sizeof(WCHAR));
 | |
|         memmove(FileNameBuf + L2 + L3, FileNameBuf + FILENAMEBUF_SIZE - L1, L1 * sizeof(WCHAR));
 | |
|     }
 | |
| }
 | |
| 
 | |
| typedef struct
 | |
| {
 | |
|     HANDLE VolumeHandle;
 | |
|     FSP_FSCTL_NOTIFY_INFO *NotifyInfo;
 | |
| } MAYBE_NOTIFY_DATA;
 | |
| 
 | |
| static DWORD WINAPI MaybeNotifyRoutine(PVOID Context)
 | |
| {
 | |
|     MAYBE_NOTIFY_DATA *NotifyData = Context;
 | |
| 
 | |
|     /*
 | |
|      * The supplied VolumeHandle may be invalid or refer to the wrong object.
 | |
|      * This is ok because:
 | |
|      *
 | |
|      * - If the VolumeHandle is invalid, Windows will catch it and will fail the operation.
 | |
|      * - If the VolumeHandle refers to the wrong object, the FspFsctlNotify "should" fail
 | |
|      * because of an unknown DeviceIoControl code.
 | |
|      * - If the VolumeHandle refers to the wrong file system, it is still ok if we send an
 | |
|      * extraneous notify.
 | |
|      */
 | |
| 
 | |
|     FspFsctlNotify(NotifyData->VolumeHandle,
 | |
|         NotifyData->NotifyInfo, NotifyData->NotifyInfo->Size);
 | |
| 
 | |
|     HeapFree(GetProcessHeap(), 0, NotifyData->NotifyInfo);
 | |
|     HeapFree(GetProcessHeap(), 0, NotifyData);
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static VOID MaybeNotify(PWSTR FileName, ULONG Filter, ULONG Action)
 | |
| {
 | |
|     static WCHAR DevicePrefix[] =
 | |
|         L"\\\\?\\GLOBALROOT\\Device\\Volume{01234567-0123-0123-0101-010101010101}";
 | |
|     static WCHAR MemfsSharePrefix[] =
 | |
|         L"\\\\memfs\\share";
 | |
|     MAYBE_NOTIFY_DATA *NotifyData;
 | |
|     FSP_FSCTL_NOTIFY_INFO *NotifyInfo;
 | |
|     size_t L;
 | |
| 
 | |
|     if (!OptNotify || OptExternal || 0 == memfs_handle)
 | |
|         return;
 | |
| 
 | |
|     if (0 == wcsncmp(FileName, DevicePrefix, wcschr(DevicePrefix, L'{') - DevicePrefix))
 | |
|         FileName += wcslen(DevicePrefix);
 | |
|     else if (0 == mywcscmp(
 | |
|         FileName, (int)wcslen(MemfsSharePrefix), MemfsSharePrefix, (int)wcslen(MemfsSharePrefix)))
 | |
|         FileName += wcslen(MemfsSharePrefix);
 | |
|     else
 | |
|         return;
 | |
| 
 | |
|     L = wcslen(FileName);
 | |
|     NotifyData = HeapAlloc(GetProcessHeap(), 0, sizeof *NotifyData);
 | |
|     NotifyInfo = HeapAlloc(GetProcessHeap(), 0, sizeof *NotifyInfo + L * sizeof(WCHAR));
 | |
|     if (0 == NotifyData || 0 == NotifyInfo)
 | |
|         ABORT("cannot malloc notify data");
 | |
| 
 | |
|     NotifyInfo->Size = (UINT16)(sizeof *NotifyInfo + L * sizeof(WCHAR));
 | |
|     NotifyInfo->Filter = Filter;
 | |
|     NotifyInfo->Action = Action;
 | |
|     memcpy(NotifyInfo->FileNameBuf, FileName, L * sizeof(WCHAR));
 | |
| 
 | |
|     NotifyData->VolumeHandle = memfs_handle;
 | |
|     NotifyData->NotifyInfo = NotifyInfo;
 | |
| 
 | |
|     if (!QueueUserWorkItem(MaybeNotifyRoutine, NotifyData, 0))
 | |
|         ABORT("cannot queue notify data");
 | |
| }
 | |
| 
 | |
| typedef struct
 | |
| {
 | |
|     HANDLE File;
 | |
|     HANDLE Wait;
 | |
|     OVERLAPPED Overlapped;
 | |
| } OPLOCK_BREAK_WAIT_DATA;
 | |
| 
 | |
| static VOID CALLBACK OplockBreakWait(PVOID Context, BOOLEAN Timeout)
 | |
| {
 | |
|     OPLOCK_BREAK_WAIT_DATA *Data = Context;
 | |
| 
 | |
|     UnregisterWaitEx(Data->Wait, 0);
 | |
|     CloseHandle(Data->File);
 | |
|     HeapFree(GetProcessHeap(), 0, Data);
 | |
| }
 | |
| 
 | |
| static VOID MaybeRequestOplock(PCWSTR FileName)
 | |
| {
 | |
|     HANDLE File;
 | |
|     OPLOCK_BREAK_WAIT_DATA *Data;
 | |
|     DWORD FsControlCode;
 | |
|     BOOL Success;
 | |
|     DWORD BytesTransferred;
 | |
| 
 | |
|     if (0 == OptOplock)
 | |
|         return;
 | |
| 
 | |
|     File = CreateFileW(
 | |
|         FileName,
 | |
|         FILE_READ_ATTRIBUTES | SYNCHRONIZE,
 | |
|         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
 | |
|         0,
 | |
|         OPEN_EXISTING,
 | |
|         FILE_FLAG_OVERLAPPED,
 | |
|         0);
 | |
|     if (INVALID_HANDLE_VALUE == File)
 | |
|         return;
 | |
| 
 | |
|     Data = HeapAlloc(GetProcessHeap(), 0, sizeof *Data);
 | |
|     if (0 == Data)
 | |
|         ABORT("cannot malloc filter oplock data");
 | |
|     memset(Data, 0, sizeof *Data);
 | |
| 
 | |
|     switch (OptOplock)
 | |
|     {
 | |
|     case 'B':
 | |
|         FsControlCode = FSCTL_REQUEST_BATCH_OPLOCK;
 | |
|         break;
 | |
|     case 'F':
 | |
|         FsControlCode = FSCTL_REQUEST_FILTER_OPLOCK;
 | |
|         break;
 | |
|     default:
 | |
|         FsControlCode = FSCTL_REQUEST_FILTER_OPLOCK;
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     Success = DeviceIoControl(File, FsControlCode, 0, 0, 0, 0, &BytesTransferred,
 | |
|         &Data->Overlapped);
 | |
|     if (!Success && ERROR_IO_PENDING == GetLastError())
 | |
|     {
 | |
|         Data->File = File;
 | |
|         if (!RegisterWaitForSingleObject(&Data->Wait, File,
 | |
|             OplockBreakWait, Data, INFINITE, WT_EXECUTEONLYONCE))
 | |
|             ABORT("cannot register wait for filter oplock");
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         CloseHandle(File);
 | |
|         HeapFree(GetProcessHeap(), 0, Data);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static VOID MaybeAdjustTraversePrivilege(BOOL Enable)
 | |
| {
 | |
|     if (OptNoTraverseToken)
 | |
|     {
 | |
|         TOKEN_PRIVILEGES Privileges;
 | |
|         DWORD LastError = GetLastError();
 | |
| 
 | |
|         Privileges.PrivilegeCount = 1;
 | |
|         Privileges.Privileges[0].Attributes = Enable ? SE_PRIVILEGE_ENABLED : 0;
 | |
|         Privileges.Privileges[0].Luid = OptNoTraverseLuid;
 | |
|         if (!AdjustTokenPrivileges(OptNoTraverseToken, FALSE, &Privileges, 0, 0, 0))
 | |
|             ABORT("cannot adjust traverse privilege");
 | |
| 
 | |
|         SetLastError(LastError);
 | |
|     }
 | |
| }
 | |
| 
 | |
| NTSTATUS NTAPI HookNtCreateFile(
 | |
|     PHANDLE FileHandle,
 | |
|     ACCESS_MASK DesiredAccess,
 | |
|     POBJECT_ATTRIBUTES ObjectAttributes,
 | |
|     PIO_STATUS_BLOCK IoStatusBlock,
 | |
|     PLARGE_INTEGER AllocationSize,
 | |
|     ULONG FileAttributes,
 | |
|     ULONG ShareAccess,
 | |
|     ULONG CreateDisposition,
 | |
|     ULONG CreateOptions,
 | |
|     PVOID EaBuffer,
 | |
|     ULONG EaLength)
 | |
| {
 | |
|     return (OptResilient ? ResilientNtCreateFile : NtCreateFile)(
 | |
|         FileHandle,
 | |
|         DesiredAccess,
 | |
|         ObjectAttributes,
 | |
|         IoStatusBlock,
 | |
|         AllocationSize,
 | |
|         FileAttributes,
 | |
|         ShareAccess,
 | |
|         CreateDisposition,
 | |
|         CreateOptions,
 | |
|         EaBuffer,
 | |
|         EaLength);
 | |
| }
 | |
| 
 | |
| NTSTATUS NTAPI HookNtClose(
 | |
|     HANDLE Handle)
 | |
| {
 | |
|     return (OptResilient ? ResilientNtClose : NtClose)(
 | |
|         Handle);
 | |
| }
 | |
| 
 | |
| HANDLE WINAPI HookCreateFileW(
 | |
|     LPCWSTR lpFileName,
 | |
|     DWORD dwDesiredAccess,
 | |
|     DWORD dwShareMode,
 | |
|     LPSECURITY_ATTRIBUTES lpSecurityAttributes,
 | |
|     DWORD dwCreationDisposition,
 | |
|     DWORD dwFlagsAndAttributes,
 | |
|     HANDLE hTemplateFile)
 | |
| {
 | |
|     WCHAR FileNameBuf[FILENAMEBUF_SIZE];
 | |
|     HANDLE Handle;
 | |
| 
 | |
|     PrepareFileName(lpFileName, FileNameBuf);
 | |
| 
 | |
|     MaybeNotify(FileNameBuf,
 | |
|         FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
 | |
| 
 | |
|     MaybeRequestOplock(FileNameBuf);
 | |
| 
 | |
|     MaybeAdjustTraversePrivilege(FALSE);
 | |
|     Handle = (OptResilient ? ResilientCreateFileW : CreateFileW)(
 | |
|         FileNameBuf,
 | |
|         dwDesiredAccess,
 | |
|         dwShareMode,
 | |
|         lpSecurityAttributes,
 | |
|         dwCreationDisposition,
 | |
|         dwFlagsAndAttributes,
 | |
|         hTemplateFile);
 | |
|     MaybeAdjustTraversePrivilege(TRUE);
 | |
|     return Handle;
 | |
| }
 | |
| 
 | |
| BOOL WINAPI HookCloseHandle(
 | |
|     HANDLE hObject)
 | |
| {
 | |
|     return (OptResilient ? ResilientCloseHandle : CloseHandle)(
 | |
|         hObject);
 | |
| }
 | |
| 
 | |
| BOOL WINAPI HookSetFileAttributesW(
 | |
|     LPCWSTR lpFileName,
 | |
|     DWORD dwFileAttributes)
 | |
| {
 | |
|     WCHAR FileNameBuf[FILENAMEBUF_SIZE];
 | |
|     BOOL Success;
 | |
| 
 | |
|     PrepareFileName(lpFileName, FileNameBuf);
 | |
| 
 | |
|     MaybeNotify(FileNameBuf,
 | |
|         FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
 | |
| 
 | |
|     MaybeAdjustTraversePrivilege(FALSE);
 | |
|     Success = SetFileAttributesW(FileNameBuf, dwFileAttributes);
 | |
|     MaybeAdjustTraversePrivilege(TRUE);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| BOOL WINAPI HookCreateDirectoryW(
 | |
|     LPCWSTR lpPathName,
 | |
|     LPSECURITY_ATTRIBUTES lpSecurityAttributes)
 | |
| {
 | |
|     WCHAR FileNameBuf[FILENAMEBUF_SIZE];
 | |
|     BOOL Success;
 | |
| 
 | |
|     PrepareFileName(lpPathName, FileNameBuf);
 | |
| 
 | |
|     MaybeNotify(FileNameBuf,
 | |
|         FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
 | |
| 
 | |
|     MaybeAdjustTraversePrivilege(FALSE);
 | |
|     Success = CreateDirectoryW(FileNameBuf, lpSecurityAttributes);
 | |
|     MaybeAdjustTraversePrivilege(TRUE);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| BOOL WINAPI HookDeleteFileW(
 | |
|     LPCWSTR lpFileName)
 | |
| {
 | |
|     WCHAR FileNameBuf[FILENAMEBUF_SIZE];
 | |
|     BOOL Success;
 | |
| 
 | |
|     PrepareFileName(lpFileName, FileNameBuf);
 | |
| 
 | |
|     MaybeNotify(FileNameBuf,
 | |
|         FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
 | |
| 
 | |
|     MaybeRequestOplock(FileNameBuf);
 | |
| 
 | |
|     MaybeAdjustTraversePrivilege(FALSE);
 | |
|     Success = (OptResilient ? ResilientDeleteFileW : DeleteFileW)(
 | |
|         FileNameBuf);
 | |
|     MaybeAdjustTraversePrivilege(TRUE);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| BOOL WINAPI HookRemoveDirectoryW(
 | |
|     LPCWSTR lpPathName)
 | |
| {
 | |
|     WCHAR FileNameBuf[FILENAMEBUF_SIZE];
 | |
|     BOOL Success;
 | |
| 
 | |
|     PrepareFileName(lpPathName, FileNameBuf);
 | |
| 
 | |
|     MaybeNotify(FileNameBuf,
 | |
|         FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
 | |
| 
 | |
|     MaybeAdjustTraversePrivilege(FALSE);
 | |
|     Success = (OptResilient ? ResilientRemoveDirectoryW : RemoveDirectoryW)(
 | |
|         FileNameBuf);
 | |
|     MaybeAdjustTraversePrivilege(TRUE);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| BOOL WINAPI HookMoveFileExW(
 | |
|     LPCWSTR lpExistingFileName,
 | |
|     LPCWSTR lpNewFileName,
 | |
|     DWORD dwFlags)
 | |
| {
 | |
|     WCHAR OldFileNameBuf[FILENAMEBUF_SIZE];
 | |
|     WCHAR NewFileNameBuf[FILENAMEBUF_SIZE];
 | |
|     BOOL Success;
 | |
| 
 | |
|     PrepareFileName(lpExistingFileName, OldFileNameBuf);
 | |
|     PrepareFileName(lpNewFileName, NewFileNameBuf);
 | |
| 
 | |
|     MaybeNotify(OldFileNameBuf,
 | |
|         FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
 | |
|     if (OptCaseInsensitive ?
 | |
|         _wcsicmp(OldFileNameBuf, NewFileNameBuf) : wcscmp(OldFileNameBuf, NewFileNameBuf))
 | |
|         MaybeNotify(NewFileNameBuf,
 | |
|             FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
 | |
| 
 | |
|     MaybeRequestOplock(OldFileNameBuf);
 | |
|     if (OptCaseInsensitive ?
 | |
|         _wcsicmp(OldFileNameBuf, NewFileNameBuf) : wcscmp(OldFileNameBuf, NewFileNameBuf))
 | |
|         MaybeRequestOplock(NewFileNameBuf);
 | |
| 
 | |
|     MaybeAdjustTraversePrivilege(FALSE);
 | |
|     Success = MoveFileExW(OldFileNameBuf, NewFileNameBuf, dwFlags);
 | |
|     MaybeAdjustTraversePrivilege(TRUE);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| HANDLE WINAPI HookFindFirstFileW(
 | |
|     LPCWSTR lpFileName,
 | |
|     LPWIN32_FIND_DATAW lpFindFileData)
 | |
| {
 | |
|     WCHAR FileNameBuf[FILENAMEBUF_SIZE];
 | |
|     HANDLE Handle;
 | |
| 
 | |
|     PrepareFileName(lpFileName, FileNameBuf);
 | |
| 
 | |
|     MaybeNotify(FileNameBuf,
 | |
|         FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
 | |
| 
 | |
|     MaybeAdjustTraversePrivilege(FALSE);
 | |
|     Handle = FindFirstFileW(FileNameBuf, lpFindFileData);
 | |
|     MaybeAdjustTraversePrivilege(TRUE);
 | |
|     return Handle;
 | |
| }
 | |
| 
 | |
| HANDLE WINAPI HookFindFirstStreamW(
 | |
|     LPCWSTR lpFileName,
 | |
|     STREAM_INFO_LEVELS InfoLevel,
 | |
|     LPVOID lpFindStreamData,
 | |
|     DWORD dwFlags)
 | |
| {
 | |
|     WCHAR FileNameBuf[FILENAMEBUF_SIZE];
 | |
|     HANDLE Handle;
 | |
| 
 | |
|     PrepareFileName(lpFileName, FileNameBuf);
 | |
| 
 | |
|     MaybeNotify(FileNameBuf,
 | |
|         FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
 | |
| 
 | |
|     MaybeAdjustTraversePrivilege(FALSE);
 | |
|     Handle = FindFirstStreamW(FileNameBuf, InfoLevel, lpFindStreamData, dwFlags);
 | |
|     MaybeAdjustTraversePrivilege(TRUE);
 | |
|     return Handle;
 | |
| }
 | |
| 
 | |
| BOOL WINAPI HookGetDiskFreeSpaceW(
 | |
|     LPCWSTR lpRootPathName,
 | |
|     LPDWORD lpSectorsPerCluster,
 | |
|     LPDWORD lpBytesPerSector,
 | |
|     LPDWORD lpNumberOfFreeClusters,
 | |
|     LPDWORD lpTotalNumberOfClusters)
 | |
| {
 | |
|     WCHAR FileNameBuf[FILENAMEBUF_SIZE];
 | |
|     BOOL Success;
 | |
| 
 | |
|     PrepareFileName(lpRootPathName, FileNameBuf);
 | |
| 
 | |
|     MaybeAdjustTraversePrivilege(FALSE);
 | |
|     Success = GetDiskFreeSpaceW(
 | |
|         FileNameBuf,
 | |
|         lpSectorsPerCluster,
 | |
|         lpBytesPerSector,
 | |
|         lpNumberOfFreeClusters,
 | |
|         lpTotalNumberOfClusters);
 | |
|     MaybeAdjustTraversePrivilege(TRUE);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| BOOL WINAPI HookGetVolumeInformationW(
 | |
|     LPCWSTR lpRootPathName,
 | |
|     LPWSTR lpVolumeNameBuffer,
 | |
|     DWORD nVolumeNameSize,
 | |
|     LPDWORD lpVolumeSerialNumber,
 | |
|     LPDWORD lpMaximumComponentLength,
 | |
|     LPDWORD lpFileSystemFlags,
 | |
|     LPWSTR lpFileSystemNameBuffer,
 | |
|     DWORD nFileSystemNameSize)
 | |
| {
 | |
|     WCHAR FileNameBuf[FILENAMEBUF_SIZE];
 | |
|     BOOL Success;
 | |
| 
 | |
|     PrepareFileName(lpRootPathName, FileNameBuf);
 | |
| 
 | |
|     MaybeAdjustTraversePrivilege(FALSE);
 | |
|     Success = GetVolumeInformationW(
 | |
|         FileNameBuf,
 | |
|         lpVolumeNameBuffer,
 | |
|         nVolumeNameSize,
 | |
|         lpVolumeSerialNumber,
 | |
|         lpMaximumComponentLength,
 | |
|         lpFileSystemFlags,
 | |
|         lpFileSystemNameBuffer,
 | |
|         nFileSystemNameSize);
 | |
|     MaybeAdjustTraversePrivilege(TRUE);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| BOOL WINAPI HookSetVolumeLabelW(
 | |
|     LPCWSTR lpRootPathName,
 | |
|     LPCWSTR lpVolumeName)
 | |
| {
 | |
|     WCHAR FileNameBuf[FILENAMEBUF_SIZE];
 | |
|     BOOL Success;
 | |
| 
 | |
|     PrepareFileName(lpRootPathName, FileNameBuf);
 | |
| 
 | |
|     MaybeAdjustTraversePrivilege(FALSE);
 | |
|     Success = SetVolumeLabelW(
 | |
|         FileNameBuf,
 | |
|         lpVolumeName);
 | |
|     MaybeAdjustTraversePrivilege(TRUE);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| BOOL WINAPI HookSetCurrentDirectoryW(
 | |
|     LPCWSTR lpPathName)
 | |
| {
 | |
|     WCHAR FileNameBuf[FILENAMEBUF_SIZE];
 | |
|     BOOL Success;
 | |
| 
 | |
|     PrepareFileName(lpPathName, FileNameBuf);
 | |
| 
 | |
|     MaybeNotify(FileNameBuf,
 | |
|         FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
 | |
| 
 | |
|     MaybeAdjustTraversePrivilege(FALSE);
 | |
|     Success = SetCurrentDirectoryW(FileNameBuf);
 | |
|     MaybeAdjustTraversePrivilege(TRUE);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| BOOL WINAPI HookCreateProcessW(
 | |
|     LPCWSTR lpApplicationName,
 | |
|     LPWSTR lpCommandLine,
 | |
|     LPSECURITY_ATTRIBUTES lpProcessAttributes,
 | |
|     LPSECURITY_ATTRIBUTES lpThreadAttributes,
 | |
|     BOOL bInheritHandles,
 | |
|     DWORD dwCreationFlags,
 | |
|     LPVOID lpEnvironment,
 | |
|     LPCWSTR lpCurrentDirectory,
 | |
|     LPSTARTUPINFOW lpStartupInfo,
 | |
|     LPPROCESS_INFORMATION lpProcessInformation)
 | |
| {
 | |
|     WCHAR FileNameBuf[FILENAMEBUF_SIZE];
 | |
|     BOOL Success;
 | |
| 
 | |
|     PrepareFileName(lpApplicationName, FileNameBuf);
 | |
| 
 | |
|     MaybeNotify(FileNameBuf,
 | |
|         FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_ACTION_MODIFIED);
 | |
| 
 | |
|     MaybeAdjustTraversePrivilege(FALSE);
 | |
|     Success = CreateProcessW(FileNameBuf,
 | |
|         lpCommandLine,  /* we should probably change this as well */
 | |
|         lpProcessAttributes,
 | |
|         lpThreadAttributes,
 | |
|         bInheritHandles,
 | |
|         dwCreationFlags,
 | |
|         lpEnvironment,
 | |
|         lpCurrentDirectory,
 | |
|         lpStartupInfo,
 | |
|         lpProcessInformation);
 | |
|     MaybeAdjustTraversePrivilege(TRUE);
 | |
|     return Success;
 | |
| }
 |