├── .gitmodules ├── res ├── FileTest.ico ├── IconWait.ico ├── IconError.ico ├── IconWarning.ico ├── IconInformation.ico ├── IconRightArrow.ico └── FileTest.exe.manifest ├── Page07NtFsInfo.cpp ├── .gitignore ├── doc ├── AceConditions.txt ├── ntstatus-to-cpp.py ├── ReadMe.txt └── History.txt ├── LICENSE ├── make.bat ├── FileTest_vs08.sln ├── FileTest.sln ├── sources ├── TToolTip.h ├── README.md ├── CMakeLists.txt ├── TDataEditor.h ├── ReparseDataHsm.h ├── AceCondition.h ├── make-msvc.bat ├── DlgDataEditor.cpp ├── TFlagString.h ├── DlgSimple.cpp ├── TToolTip.cpp ├── FileTest.vcxproj.filters ├── AceResource.h ├── Page08Ea.cpp ├── Page00Transaction.cpp ├── TAceHelper.h ├── TestCode.cpp ├── ReparseDataHsm.cpp ├── DlgEaEditor.cpp ├── FileTest.vcxproj ├── WinMain.cpp ├── FileTest_vs08.vcproj └── TFastString.h /.gitmodules: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /res/FileTest.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ladislav-zezula/FileTest/HEAD/res/FileTest.ico -------------------------------------------------------------------------------- /res/IconWait.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ladislav-zezula/FileTest/HEAD/res/IconWait.ico -------------------------------------------------------------------------------- /res/IconError.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ladislav-zezula/FileTest/HEAD/res/IconError.ico -------------------------------------------------------------------------------- /res/IconWarning.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ladislav-zezula/FileTest/HEAD/res/IconWarning.ico -------------------------------------------------------------------------------- /res/IconInformation.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ladislav-zezula/FileTest/HEAD/res/IconInformation.ico -------------------------------------------------------------------------------- /res/IconRightArrow.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ladislav-zezula/FileTest/HEAD/res/IconRightArrow.ico -------------------------------------------------------------------------------- /Page07NtFsInfo.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This is dummy source file. 3 | // All handlers for 7-th page are in Page06NtFileInfo.cpp 4 | // 5 | 6 | #include "FileTest.h" 7 | #include "resource.h" 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Compiled Dynamic libraries 8 | *.so 9 | *.dylib 10 | *.dll 11 | 12 | # Compiled Static libraries 13 | *.lai 14 | *.la 15 | *.a 16 | *.lib 17 | 18 | # Executables 19 | *.exe 20 | *.out 21 | *.app 22 | -------------------------------------------------------------------------------- /doc/AceConditions.txt: -------------------------------------------------------------------------------- 1 | Examples of an ACE condition: 2 | 3 | WIN://SYSAPPID Contains Microsoft.549981C3F5F10_8wekyb3d8bbwe 4 | APPID://PATH Contains "%WINDIR%\* 5 | (Exists APPID://SHA256HASH) && (APPID://SHA256HASH Any_of {#5bf6ccc91dd715e18d6769af97dd3ad6a15d2b70326e834474d952753118c670}) 6 | (Exists APPID://FQBN) && (APPID://FQBN >= {"O=MICROSOFT CORPORATION, L=REDMOND, S=WASHINGTON, C=US\MICROSOFT® WINDOWS ® OPERATING SYSTEM\*", 0}) 7 | APPID://PATH Contains "%SYSTEM32%\NOTEPAD.EXE" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Ladislav Zezula 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /make.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | if not "x%WDKDIR%" == "x" goto SELECT_BINARY 3 | echo The WDKDIR environment variable is not set 4 | echo Set this variable to your WDK directory (without ending backslash) 5 | echo Example: set WDKDIR C:\WinDDK\6001 6 | pause 7 | goto:eof 8 | 9 | :SELECT_BINARY 10 | set PROJECT_DIR=%~dp0 11 | set SAVE_PATH=%PATH% 12 | set BINARY_NAME=FileTest 13 | set LANGUAGE=En 14 | set BUILD_TYPE=fre 15 | 16 | :BUILD_BINARY_64 17 | echo Building %BINARY_NAME%.exe (64-bit) ... 18 | set DDKBUILDENV= 19 | call %WDKDIR%\bin\setenv.bat %WDKDIR%\ %BUILD_TYPE% x64 wnet 20 | cd /d %PROJECT_DIR% 21 | build.exe -czgw 22 | del build%BUILD_TYPE%_wnet_amd64.log 23 | echo. 24 | 25 | :BUILD_BINARY_32 26 | echo Building %BINARY_NAME%.exe (32-bit) ... 27 | set DDKBUILDENV= 28 | call %WDKDIR%\bin\setenv.bat %WDKDIR%\ %BUILD_TYPE% w2k 29 | cd /d %PROJECT_DIR% 30 | build.exe -czgw 31 | del build%BUILD_TYPE%_w2k_x86.log 32 | echo. 33 | 34 | :POST_BUILD_STEPS 35 | PostBuild.exe .\obj%BUILD_TYPE%_wnet_amd64\amd64\%BINARY_NAME%.exe /tools /subsystem4 36 | PostBuild.exe .\obj%BUILD_TYPE%_w2k_x86\i386\%BINARY_NAME%.exe /tools /subsystem4 37 | 38 | :CLEANUP 39 | if exist %BINARY_NAME%_WDK.rc del %BINARY_NAME%_WDK.rc 40 | if exist build.bat del build.bat 41 | set PATH=%SAVE_PATH% 42 | -------------------------------------------------------------------------------- /FileTest_vs08.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 10.00 2 | # Visual Studio 2008 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileTest", "FileTest_vs08.vcproj", "{73D582FC-D08A-4322-AFDB-C244E9716CB4}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Win32 = Debug|Win32 8 | Debug|x64 = Debug|x64 9 | Release|Win32 = Release|Win32 10 | Release|x64 = Release|x64 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Debug|Win32.ActiveCfg = Debug|Win32 14 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Debug|Win32.Build.0 = Debug|Win32 15 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Debug|x64.ActiveCfg = Debug|x64 16 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Debug|x64.Build.0 = Debug|x64 17 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Release|Win32.ActiveCfg = Release|Win32 18 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Release|Win32.Build.0 = Release|Win32 19 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Release|x64.ActiveCfg = Release|x64 20 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Release|x64.Build.0 = Release|x64 21 | EndGlobalSection 22 | GlobalSection(SolutionProperties) = preSolution 23 | HideSolutionNode = FALSE 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /doc/ntstatus-to-cpp.py: -------------------------------------------------------------------------------- 1 | # Converting ntstatus.h into array used in FileTest 2 | import re, sys 3 | 4 | def main(argc, argv): 5 | 6 | try: 7 | # Process the lines in the detections file 8 | ntstatus_source = 'ntstatus.h' 9 | file_lines = [line.rstrip('\n') for line in open(ntstatus_source)] 10 | 11 | # Create the deletion script 12 | f = open('nstatus.cpp', 'wt') 13 | 14 | # Parse all lines 15 | for single_line in file_lines: 16 | 17 | # Check for lines like "#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) // ntsubauth" 18 | if re.match(r"#define [A-Z_]+ +\(\(NTSTATUS\)0x[0-9a-fA-F]{8}L\)", single_line, re.I): 19 | 20 | # Split the line to words 21 | word_list = single_line.split(' ') 22 | if(len(word_list) >= 2): 23 | 24 | # Avoid lines like "NTSTATUS_FROM_WIN32(x)" 25 | ntstatus_name = word_list[1] 26 | if(ntstatus_name.find('(') != -1): 27 | continue 28 | 29 | # Write the second word to the output file 30 | f.write(' DEFINE_NTSTATUS_ENTRY(%s),\n' % ntstatus_name) 31 | print(ntstatus_name) 32 | 33 | # Close the delete file 34 | f.close() 35 | 36 | except: 37 | print("Exception in processing the header file") 38 | pass 39 | 40 | if __name__ == "__main__" : 41 | main(len(sys.argv), sys.argv) 42 | 43 | -------------------------------------------------------------------------------- /FileTest.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 15 3 | VisualStudioVersion = 15.0.28306.52 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileTest", "FileTest.vcxproj", "{73D582FC-D08A-4322-AFDB-C244E9716CB4}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|x64 = Debug|x64 10 | Debug|Win32 = Debug|Win32 11 | Release|x64 = Release|x64 12 | Release|Win32 = Release|Win32 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Debug|x64.ActiveCfg = Debug|x64 16 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Debug|x64.Build.0 = Debug|x64 17 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Debug|Win32.Build.0 = Debug|Win32 19 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Release|x64.ActiveCfg = Release|x64 20 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Release|x64.Build.0 = Release|x64 21 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Release|Win32.ActiveCfg = Release|Win32 22 | {73D582FC-D08A-4322-AFDB-C244E9716CB4}.Release|Win32.Build.0 = Release|Win32 23 | EndGlobalSection 24 | GlobalSection(SolutionProperties) = preSolution 25 | HideSolutionNode = FALSE 26 | EndGlobalSection 27 | GlobalSection(ExtensibilityGlobals) = postSolution 28 | SolutionGuid = {9CB3CCB1-A106-4310-9D77-FCC1746D908D} 29 | EndGlobalSection 30 | EndGlobal 31 | -------------------------------------------------------------------------------- /sources: -------------------------------------------------------------------------------- 1 | NOT_LEAN_AND_MEAN=1 2 | TARGETNAME=FileTest 3 | TARGETTYPE=PROGRAM 4 | UMTYPE=windows 5 | UMENTRY=_tWinMain 6 | UMENTRYABS = wWinMainCRTStartup 7 | USE_NATIVE_EH=1 8 | USE_MSVCRT=1 9 | USE_STL=1 10 | STL_VER=70 11 | #USE_LIBCMT=1 12 | MSC_WARNING_LEVEL=/W4 13 | PRECOMPILED_CXX=1 14 | PRECOMPILED_INCLUDE=FileTest.h 15 | 16 | INCLUDES=$(WDKDIR)\inc\mfc42;..\aaa\inc 17 | 18 | C_DEFINES=$(C_DEFINES) -DUNICODE -D_UNICODE -DWDK_BUILD 19 | 20 | LINKER_FLAGS=/PDBALTPATH:%_PDB% 21 | 22 | !if $(AMD64) 23 | USR_LIB_PATH=..\aaa\lib64 24 | !else 25 | USR_LIB_PATH=..\aaa\lib32 26 | !endif 27 | 28 | SOURCES=AceCondition.cpp \ 29 | AceResource.cpp \ 30 | DateTime.cpp \ 31 | DlgCopyFile.cpp \ 32 | DlgDataEditor.cpp \ 33 | DlgEaEditor.cpp \ 34 | DlgEasEditor.cpp \ 35 | DlgFileTest.cpp \ 36 | DlgFlags.cpp \ 37 | DlgPrivileges.cpp \ 38 | DlgSimple.cpp \ 39 | NtStatus2Text.cpp \ 40 | Page00Transaction.cpp \ 41 | Page01Create.cpp \ 42 | Page02NtCreate.cpp \ 43 | Page03ReadWrite.cpp \ 44 | Page04Mapping.cpp \ 45 | Page05FileOps.cpp \ 46 | Page06NtFileInfo.cpp \ 47 | Page07NtFsInfo.cpp \ 48 | Page08Ea.cpp \ 49 | Page09Security.cpp \ 50 | Page10Links.cpp \ 51 | Page11Streams.cpp \ 52 | Page12Ioctl.cpp \ 53 | ReparseDataHsm.cpp \ 54 | TestCode.cpp \ 55 | TAceHelper.cpp \ 56 | TDataEditor.cpp \ 57 | TToolTip.cpp \ 58 | Utils.cpp \ 59 | WinMain.cpp \ 60 | FileTest.rc 61 | 62 | TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ 63 | $(SDK_LIB_PATH)\shell32.lib \ 64 | $(SDK_LIB_PATH)\Comctl32.lib \ 65 | $(SDK_LIB_PATH)\Comdlg32.lib \ 66 | $(SDK_LIB_PATH)\Version.lib \ 67 | $(USR_LIB_PATH)\UtilsWDK.lib \ 68 | $(USR_LIB_PATH)\ntdll.lib 69 | -------------------------------------------------------------------------------- /res/FileTest.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true/pm 6 | permonitorv2,permonitor 7 | true 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 23 | 24 | 25 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /TToolTip.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* TToolTip.h Copyright (c) Ladislav Zezula 2014 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Interface to class TTooltip, used as helper for displaying flags */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 16.03.14 1.00 Lad The first version of TToolTip.h */ 9 | /*****************************************************************************/ 10 | 11 | #ifndef __TTOOLTIP_H__ 12 | #define __TTOOLTIP_H__ 13 | 14 | //----------------------------------------------------------------------------- 15 | // Definition of the TTooltip class 16 | 17 | class TToolTip 18 | { 19 | public: 20 | 21 | TToolTip(); 22 | ~TToolTip(); 23 | 24 | // Initializes the tooltip. Call once per application 25 | BOOL Initialize(HINSTANCE hInst, HWND hWndParent); 26 | void Destroy(); 27 | 28 | // Adds a flag-based tooltip for the specified child window 29 | BOOL AddToolTip(HWND hDlg, UINT nIDCtrl, TFlagInfo * pFlags); 30 | BOOL AddToolTip(HWND hDlg, UINT nIDCtrl, UINT nIDTip); 31 | 32 | // Handles all messages 33 | LRESULT HandleMessages(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL * pbHandled); 34 | 35 | protected: 36 | 37 | BOOL AddToolTipInternal(HWND hDlg, UINT nIDCtrl, LPCTSTR szTip, TFlagInfo * pFlags); 38 | void OnGetTooltipText(LPNMTTDISPINFO pTTDispInfo); 39 | 40 | LPTSTR szToolTipText; // Text for preparing the buffer 41 | size_t cchTooltipText; // Length of the buffer 42 | HWND hWndToolTip; // Handle to the tooltip window 43 | }; 44 | 45 | #endif // __TTOOLTIP_H__ 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | FileTest 2 | ======== 3 | 4 | ## Interactive File System Test Tool 5 | You can use this tool for testing, debugging and learning [Windows FileSystem APIs](http://msdn.microsoft.com/en-us/library/windows/desktop/aa364232(v=vs.85).aspx). 6 | If you use this tool with [Process Monitor](http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx), you can understand how Windows FileSystems internally works. 7 | 8 | ![Interactive File System Test Tool](http://www.zezula.net/images/tools/filetest_github.png) 9 | 10 | ## Supported ways to build 11 | FileTest can be built with one of these build environments: 12 | * Visual Studio 2022+ 13 | * Visual Studio 2008 14 | * WDK 6001 15 | * CMake 16 | 17 | ### How to build with Visual Studio 2008 or 2022+ 18 | ``` 19 | md C:\Projects 20 | cd C:\Projects 21 | git clone https://github.com/ladislav-zezula/Aaa.git 22 | git clone https://github.com/ladislav-zezula/FileTest.git 23 | cd FileTest 24 | call make-msvc.bat 25 | ``` 26 | The final EXEs will be in `./bin/Win32/Release` and `./bin/x64/Release` 27 | 28 | ### How to build with WDK 6001 29 | 1. Clone the repository `https://github.com/ladislav-zezula/WDK_6001` 30 | 2. Clone the repository `https://github.com/ladislav-zezula/FileTest` 31 | 3. Clone the repository `https://github.com/ladislav-zezula/Aaa` 32 | 4. Set the environment variable `WDKDIR` to the folder where you cloned the WDK 33 | 5. Run the build script 34 | ``` 35 | :: Assume C:\Projects as the current folder 36 | git clone https://github.com/ladislav-zezula/WDK_6001.git 37 | git clone https://github.com/ladislav-zezula/FileTest.git 38 | git clone https://github.com/ladislav-zezula/Aaa.git 39 | set WDKDIR=C:\Projects\WDK 40 | cd FileTest 41 | make.bat 42 | ``` 43 | The final EXEs will be in `.\objfre_w2k_x86\i386` and `.\objfre_wlh_amd64\amd64` 44 | 45 | ### How to build with CMake 46 | ``` 47 | git clone https://github.com/ladislav-zezula/FileTest.git 48 | cd FileTest 49 | git submodule add https://github.com/ladislav-zezula/Aaa.git ./lib/Aaa/ 50 | md build 51 | cd build 52 | cmake .. -G "Visual Studio 17 2022" :: For 64-bit build 53 | cmake .. -G "Visual Studio 17 2022" -A Win32 :: For 32-bit build 54 | cmake --build . --config Release 55 | ``` 56 | The final EXE fill be in `.\build\Release` -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.20) 2 | 3 | set(LIB_AAA_ROOT "./lib/Aaa") 4 | 5 | add_executable(FileTest 6 | ${CMAKE_SOURCE_DIR}/AceCondition.cpp 7 | ${CMAKE_SOURCE_DIR}/AceResource.cpp 8 | ${CMAKE_SOURCE_DIR}/DateTime.cpp 9 | ${CMAKE_SOURCE_DIR}/DlgCopyFile.cpp 10 | ${CMAKE_SOURCE_DIR}/DlgDataEditor.cpp 11 | ${CMAKE_SOURCE_DIR}/DlgEaEditor.cpp 12 | ${CMAKE_SOURCE_DIR}/DlgEasEditor.cpp 13 | ${CMAKE_SOURCE_DIR}/DlgFileTest.cpp 14 | ${CMAKE_SOURCE_DIR}/DlgFlags.cpp 15 | ${CMAKE_SOURCE_DIR}/DlgPrivileges.cpp 16 | ${CMAKE_SOURCE_DIR}/DlgSimple.cpp 17 | ${CMAKE_SOURCE_DIR}/NtStatus2Text.cpp 18 | ${CMAKE_SOURCE_DIR}/Page00Transaction.cpp 19 | ${CMAKE_SOURCE_DIR}/Page01Create.cpp 20 | ${CMAKE_SOURCE_DIR}/Page02NtCreate.cpp 21 | ${CMAKE_SOURCE_DIR}/Page03ReadWrite.cpp 22 | ${CMAKE_SOURCE_DIR}/Page04Mapping.cpp 23 | ${CMAKE_SOURCE_DIR}/Page05FileOps.cpp 24 | ${CMAKE_SOURCE_DIR}/Page06NtFileInfo.cpp 25 | ${CMAKE_SOURCE_DIR}/Page07NtFsInfo.cpp 26 | ${CMAKE_SOURCE_DIR}/Page08Ea.cpp 27 | ${CMAKE_SOURCE_DIR}/Page09Security.cpp 28 | ${CMAKE_SOURCE_DIR}/Page10Links.cpp 29 | ${CMAKE_SOURCE_DIR}/Page11Streams.cpp 30 | ${CMAKE_SOURCE_DIR}/Page12Ioctl.cpp 31 | ${CMAKE_SOURCE_DIR}/ReparseDataHsm.cpp 32 | ${CMAKE_SOURCE_DIR}/TestCode.cpp 33 | ${CMAKE_SOURCE_DIR}/TAceHelper.cpp 34 | ${CMAKE_SOURCE_DIR}/TDataEditor.cpp 35 | ${CMAKE_SOURCE_DIR}/TToolTip.cpp 36 | ${CMAKE_SOURCE_DIR}/Utils.cpp 37 | ${CMAKE_SOURCE_DIR}/WinMain.cpp 38 | ${CMAKE_SOURCE_DIR}/FileTest.rc 39 | ) 40 | 41 | add_definitions(-D_AFXDLL) 42 | set(CMAKE_MFC_FLAG 2) 43 | 44 | target_link_options(FileTest PRIVATE "/SUBSYSTEM:WINDOWS") 45 | 46 | target_include_directories(FileTest PRIVATE "${LIB_AAA_ROOT}/inc") 47 | 48 | # Make sure that CRT library is statically linked 49 | target_compile_options(FileTest PUBLIC /MT) 50 | 51 | message(CMAKE_GENERATOR_PLATFORM="${CMAKE_GENERATOR_PLATFORM}") 52 | 53 | if(CMAKE_GENERATOR_PLATFORM STREQUAL "Win32") 54 | set(LIB_AAA_VER "lib32") 55 | else() 56 | set(LIB_AAA_VER "lib64") 57 | endif() 58 | 59 | target_link_libraries(FileTest PRIVATE kernel32.lib shell32.lib Comctl32.lib 60 | Comdlg32.lib Version.lib ${CMAKE_SOURCE_DIR}/${LIB_AAA_ROOT}/${LIB_AAA_VER}/ntdll.lib 61 | ${CMAKE_SOURCE_DIR}/${LIB_AAA_ROOT}/${LIB_AAA_VER}/UtilsRUS.lib 62 | ) 63 | 64 | project(FileTest) 65 | -------------------------------------------------------------------------------- /doc/ReadMe.txt: -------------------------------------------------------------------------------- 1 | 2 | Utility: FileTest V1.1 3 | Author: Ladislav Zezula 4 | Email: ladik@zezula.net 5 | 6 | This ZIP archive includes the sources (and executable) for the FileTest 7 | utility, written by Ladislav Zezula. 8 | 9 | The archive also includes the source of a general purpose "Utils" lib 10 | which contains some generally useful functions and is also necessary 11 | to build the executable. 12 | 13 | The project and library are made for MS Visual C 6.0 and Visual Studio 7.0. 14 | All necessary headers should be included (you will not need to include 15 | NT DDK or IFS headers). 16 | 17 | 18 | From the author: 19 | ================ 20 | If anyone has some criticisms, comments, suggestions, bugs, or anything else, 21 | please mail me, I will try to help. 22 | 23 | You may use the tool and the source code freely, whatever you need it for, 24 | regardles if it is for personal or commercial use. The program is nothing 25 | special, everyone could write it, if (s)he has time for it. 26 | 27 | Building FileTest 28 | ================= 29 | 30 | 1) Unpack the whole archive as-is to an empty directory 31 | 2) Open the workspace "Utils\Utils.dsw 32 | 3) In MSVC 6.0, select "Build\Batch Build" and rebuild all versions 33 | 4) Open the workspace "FileTest\FileTest.dsw" 34 | 5) Choose debug or release version and do "Rebuild all" 35 | 6) The result executable is in "Debug\FileTest.exe" or 36 | "Release\FileTest.exe" 37 | 38 | 39 | Warranty and Limitation of Liability: 40 | ===================================== 41 | This program is provided as a service to the Windows system software development community 42 | via OSR Online (www.osronline.com). OSR Open Systems Resources, Inc not contributed to, 43 | reviewed, or approved this program or any of the contents of this ZIP archive (except this file). 44 | 45 | OSR Open Systems Resources, Inc. (OSR) expressly disclaims any warranty. THIS SOFTWARE IS PROVIDED 46 | "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, THE 47 | IMPLIED WARRANTIES OF MECHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK ARISING 48 | FROM THE USE OF THIS SOFTWARE REMAINS WITH YOU. OSR's entire liability and your exclusive remedy shall not 49 | exceed the price paid for this material. In no event shall OSR or its suppliers be liable for 50 | any damages whatsoever (including, without limitation, damages for loss of business profit, 51 | business interruption, loss of business information, or any other pecuniary loss) arising 52 | out of the use or inability to use this software, even if OSR has been advised of the possibility 53 | of such damages. Because some states/jurisdictions do not allow the exclusion or limitation 54 | of liability for consequential or incidental damages, the above limitation may not apply to you. 55 | -------------------------------------------------------------------------------- /TDataEditor.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* TDataEditor.h Copyright (c) Ladislav Zezula 2014 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Description : */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 18.03.14 1.00 Lad The first version of TDataEditor.h */ 9 | /*****************************************************************************/ 10 | 11 | #ifndef __TDATAEDITOR_H__ 12 | #define __TDATAEDITOR_H__ 13 | 14 | //----------------------------------------------------------------------------- 15 | // Defines 16 | 17 | #define DATAEDIT_COLOR_NORMAL_FG RGB(0, 0, 0) 18 | #define DATAEDIT_COLOR_NORMAL_BG RGB(255, 255, 255) 19 | 20 | #define DATAEDIT_COLOR_SELECTION_FG RGB(255, 255, 255) 21 | #define DATAEDIT_COLOR_SELECTION_BG RGB(49, 106, 197) 22 | 23 | #define DATAEDIT_TEXT_INDENT 2 // Number of pixels before the first character 24 | 25 | // Data Editor styles 26 | #define DES_HSCROLL 0x00000010 27 | #define DES_VSCROLL 0x00000020 28 | 29 | enum TPointerFormat 30 | { 31 | PtrPlatformSpecific = 0, 32 | PtrPointer32Bit, 33 | PtrPointer64Bit 34 | }; 35 | 36 | //----------------------------------------------------------------------------- 37 | // Messages for data editor (via WM_NOTIFY) 38 | 39 | #define DEN_EXCEPTION (WM_USER + 0x1000) 40 | 41 | typedef struct _DTE_EXCEPTION_DATA 42 | { 43 | NMHDR hdr; // Common header 44 | PVOID ExceptionAddress; // Address where the exception happened 45 | ULONG ExceptionCode; 46 | BOOL WriteOperation; 47 | } DTE_EXCEPTION_DATA, *PDTE_EXCEPTION_DATA; 48 | 49 | #define DEN_PASTE (WM_USER + 0x1001) 50 | 51 | typedef struct _DTE_PASTE_DATA 52 | { 53 | NMHDR hdr; // Common header 54 | LPCSTR szPasteText; // Pointer to the text to be pasted 55 | SIZE_T PasteOffset; // Offset in the data corresponding to the current cursor position 56 | SIZE_T PasteLength; // Length of the text being pasted 57 | BOOL bHandled; // If someone sets this to TRUE, then data editor will not process it fuhrter 58 | 59 | } DTE_PASTE_DATA, *PDTE_PASTE_DATA; 60 | 61 | //----------------------------------------------------------------------------- 62 | // Class name of the data editor 63 | 64 | extern const LPTSTR szDataEditClassName; 65 | 66 | //----------------------------------------------------------------------------- 67 | // Data Editor interface 68 | 69 | // Registers the data editor 70 | int RegisterDataEditor(HINSTANCE hInst); 71 | 72 | // Applies the new data 73 | int DataEditor_SetData(HWND hWndDataEdit, ULONGLONG BaseAddress, LPVOID pvData, SIZE_T cbData); 74 | 75 | // Sets the pointer format 76 | int DataEditor_SetDataFormat(HWND hWndDataEdit, TPointerFormat PtrFormat, SIZE_T cbBytesPerLine); 77 | 78 | #endif // __TDATAEDITOR_H__ 79 | -------------------------------------------------------------------------------- /ReparseDataHsm.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* ReparseDataHsm.h Copyright (c) Ladislav Zezula 2018 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Interface of the HSM reparse data structures */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 06.09.18 1.00 Lad The first version of ReparseDataHsm.h */ 9 | /*****************************************************************************/ 10 | 11 | #ifndef __REPARSE_DATA_HSM_H__ 12 | #define __REPARSE_DATA_HSM_H__ 13 | 14 | //----------------------------------------------------------------------------- 15 | // Defines 16 | 17 | #define HSM_BITMAP_MAGIC 0x70527442 // 'BtRp' 18 | #define HSM_BITMAP_ELEMENTS 0x05 // Fixed number of elements for HSM bitmap 19 | #define HSM_FILE_MAGIC 0x70526546 // 'FeRp' 20 | #define HSM_FILE_ELEMENTS 0x09 // Fixed number of elements for HSM reparse data 21 | 22 | #define HSM_DATA_HAVE_CRC 0x02 // If set, then the data has CRC 23 | 24 | #define HSM_XXX_DATA_SIZE 0x10 25 | #define HSM_MIN_DATA_SIZE(elements) (HSM_XXX_DATA_SIZE + (elements * sizeof(HSM_ELEMENT_INFO))) 26 | 27 | #define HSM_ELEMENT_TYPE_NONE 0x00 28 | #define HSM_ELEMENT_TYPE_UINT64 0x06 29 | #define HSM_ELEMENT_TYPE_BYTE 0x07 30 | #define HSM_ELEMENT_TYPE_UINT32 0x0A 31 | #define HSM_ELEMENT_TYPE_BITMAP 0x11 32 | #define HSM_ELEMENT_TYPE_MAX 0x12 33 | 34 | //----------------------------------------------------------------------------- 35 | // Data structures for HSM reparse data 36 | 37 | typedef struct _HSM_ELEMENT_INFO 38 | { 39 | USHORT Type; // Type of the element (?). One of HSM_ELEMENT_TYPE_XXX 40 | USHORT Length; // Length of the element data in bytes 41 | ULONG Offset; // Offset of the element data, relative to begin of HSM_DATA. Aligned to 4 bytes 42 | } HSM_ELEMENT_INFO, *PHSM_ELEMENT_INFO; 43 | 44 | typedef struct _HSM_DATA 45 | { 46 | ULONG Magic; // 0x70527442 ('pRtB') for bitmap data, 0x70526546 ('FeRp') for file data 47 | ULONG Crc32; // CRC32 of the following data (calculated by RtlComputeCrc32) 48 | ULONG Length; // Length of the entire HSM_DATA in bytes 49 | USHORT Flags; // HSM_DATA_XXXX 50 | USHORT NumberOfElements; // Number of elements 51 | HSM_ELEMENT_INFO ElementInfos[1]; // Array of element infos. There is fixed maximal items for bitmap and reparse data 52 | } HSM_DATA, *PHSM_DATA; 53 | 54 | typedef struct _HSM_REPARSE_DATA 55 | { 56 | USHORT Flags; // Lower 8 bits is revision (must be 1 as of Windows 10 16299) 57 | // Flags: 0x8000 = Data needs to be decompressed by RtlCompressBuffer 58 | USHORT Length; // Length of the HSM_REPARSE_DATA structure (including "Flags" and "Length") 59 | 60 | HSM_DATA FileData; // HSM data 61 | } HSM_REPARSE_DATA, *PHSM_REPARSE_DATA; 62 | 63 | //----------------------------------------------------------------------------- 64 | // Helper functions 65 | 66 | LPBYTE HsmGetElementData(PHSM_DATA HsmData, ULONG ElementIndex); 67 | NTSTATUS HsmUncompressData(PREPARSE_DATA_BUFFER RawReparseData, ULONG RawDataLength, PREPARSE_DATA_BUFFER * OutReparseData); 68 | NTSTATUS HsmValidateReparseData(PREPARSE_DATA_BUFFER ReparseData); 69 | 70 | #endif // __REPARSE_DATA_HSM_H__ 71 | -------------------------------------------------------------------------------- /AceCondition.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* AceCondition.h Copyright (c) Ladislav Zezula 2023 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Interface to the ACE condition converter */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 26.10.23 1.00 Lad Created */ 9 | /*****************************************************************************/ 10 | 11 | #ifndef __ACE_CONDITION_H__ 12 | #define __ACE_CONDITION_H__ 13 | 14 | #define MAX_OPERAND_STACK 0xFF 15 | #define MAX_SID_LENGTH 0x44 16 | 17 | // Defines related to conditional ACE tokens 18 | typedef enum _ACE_CONDITION_TOKEN 19 | { 20 | CTOKEN_PAD = 0x00, 21 | CTOKEN_INT8 = 0x01, // Has data 22 | CTOKEN_INT16 = 0x02, // Has data 23 | CTOKEN_INT32 = 0x03, // Has data 24 | CTOKEN_INT64 = 0x04, // Has data 25 | CTOKEN_UNICODE_STRING = 0x10, // Has data 26 | CTOKEN_OCTET_STRING = 0x18, // Has data 27 | CTOKEN_COMPOSITE = 0x50, // Has data 28 | CTOKEN_SID = 0x51, // Has data 29 | CTOKEN_EQUAL = 0x80, 30 | CTOKEN_NOT_EQUAL = 0x81, 31 | CTOKEN_LESS_THAN = 0x82, 32 | CTOKEN_LESS_THAN_OR_EQUAL = 0x83, 33 | CTOKEN_GREATER_THAN = 0x84, 34 | CTOKEN_GREATER_THAN_OR_EQUAL = 0x85, 35 | CTOKEN_CONTAINS = 0x86, 36 | CTOKEN_EXISTS = 0x87, 37 | CTOKEN_ANY_OF = 0x88, 38 | CTOKEN_MEMBER_OF = 0x89, 39 | CTOKEN_DEVICE_MEMBER_OF = 0x8a, 40 | CTOKEN_MEMBER_OF_ANY = 0x8b, 41 | CTOKEN_DEVICE_MEMBER_OF_ANY = 0x8c, 42 | CTOKEN_NOT_EXISTS = 0x8d, 43 | CTOKEN_NOT_CONTAINS = 0x8e, 44 | CTOKEN_NOT_ANY_OF = 0x8f, 45 | CTOKEN_NOT_MEMBER_OF = 0x90, 46 | CTOKEN_NOT_DEVICE_MEMBER_OF = 0x91, 47 | CTOKEN_NOT_MEMBER_OF_ANY = 0x92, 48 | CTOKEN_NOT_DEVICE_MEMBER_OF_ANY = 0x93, 49 | CTOKEN_AND = 0xa0, 50 | CTOKEN_OR = 0xa1, 51 | CTOKEN_NOT = 0xa2, 52 | CTOKEN_BIT_AND = 0xa3, 53 | CTOKEN_LOCAL_ATTRIBUTE = 0xf8, // Has data 54 | CTOKEN_USER_ATTRIBUTE = 0xf9, // Has data 55 | CTOKEN_RESOURCE_ATTRIBUTE = 0xfa, // Has data 56 | CTOKEN_DEVICE_ATTRIBUTE = 0xfb, // Has data 57 | CTOKEN_TOKEN_ATTRIBUTE = 0xfc, // Has data 58 | } ACE_CONDITION_TOKEN, *PACE_CONDITION_TOKEN; 59 | 60 | 61 | typedef enum _STRSD_SID_TYPE 62 | { 63 | ST_DOMAIN_RELATIVE = 0, 64 | ST_WORLD, 65 | ST_LOCALSY, 66 | ST_LOCAL, 67 | ST_CREATOR, 68 | ST_NTAUTH, 69 | ST_BUILTIN, 70 | ST_ROOT_DOMAIN_RELATIVE, 71 | ST_LABEL, 72 | ST_APP_PACKAGE, 73 | ST_USER_MODE_DRIVER, 74 | ST_AUTHENTICATION_AUTHORITY, 75 | } STRSD_SID_TYPE, *PSTRSD_SID_TYPE; 76 | 77 | 78 | typedef struct _STRSD_SID_LOOKUP 79 | { 80 | bool Valid; 81 | USHORT Key[4]; 82 | ULONG KeyLen; 83 | void * Sid; 84 | void * Rid; 85 | STRSD_SID_TYPE SidType; 86 | ULONG SidBuff[18]; 87 | } STRSD_SID_LOOKUP, *PSTRSD_SID_LOOKUP; 88 | 89 | 90 | typedef struct _CONDITION_OPERATOR 91 | { 92 | LPCWSTR Op; 93 | ACE_CONDITION_TOKEN TokenCode; 94 | DWORD Precedence; 95 | bool Unary; 96 | bool FollowedByAttribute; 97 | bool PrecededByAttribute; 98 | bool Operational; 99 | bool RequiresDelimiter; 100 | } CONDITION_OPERATOR, *PCONDITION_OPERATOR; 101 | 102 | 103 | // Prototype of the LocalGetStringForCondition inside aclui.dll 104 | typedef DWORD(WINAPI * LGSFC)( 105 | LPBYTE Condition, 106 | DWORD ConditionSize, 107 | LPWSTR * ConditionStr, 108 | DWORD * pdwReferencedTokenTypes, 109 | void * RootDomainSid, 110 | void * DomainSid, 111 | PSTRSD_SID_LOOKUP tSidLookupDomOrRootDomRelativeTable, 112 | bool DefaultToDomain); 113 | 114 | extern LPCTSTR HexaAlphabetLower; 115 | 116 | // advapi32.dll!_LocalpGetStringForCondition@32 117 | // (also aclui.dll!_LocalpGetStringForCondition@32) 118 | DWORD LocalGetStringForCondition( 119 | LPBYTE Condition, 120 | DWORD ConditionSize, 121 | LPWSTR * ConditionStr, 122 | DWORD * pdwReferencedTokenTypes, 123 | void * RootDomainSid, 124 | void * DomainSid, 125 | PSTRSD_SID_LOOKUP tSidLookupDomOrRootDomRelativeTable, 126 | bool DefaultToDomain 127 | ); 128 | 129 | #endif // __ACE_CONDITION_H__ 130 | -------------------------------------------------------------------------------- /make-msvc.bat: -------------------------------------------------------------------------------- 1 | :: Build file for Visual Studio 2008 and 2017 2 | @echo off 3 | 4 | :: Save the values of INCLUDE, LIB and PATH 5 | set PROJECT_DIR=%~dp0 6 | set SAVE_INCLUDE=%INCLUDE% 7 | set SAVE_PATH=%PATH% 8 | set SAVE_LIB=%LIB% 9 | set PROJECT_NAME=FileTest 10 | set PROJECT_ZIP_NAME=filetest 11 | 12 | :: Remember whether we shall publish the project 13 | if "x%1" == "x/web" set PUBLISH_PROJECT=1 14 | 15 | :: Determine where the program files are, both for 64-bit and 32-bit Windows 16 | if exist "%ProgramW6432%" set PROGRAM_FILES_X64=%ProgramW6432% 17 | if exist "%ProgramFiles%" set PROGRAM_FILES_DIR=%ProgramFiles% 18 | if exist "%ProgramFiles(x86)%" set PROGRAM_FILES_DIR=%ProgramFiles(x86)% 19 | 20 | :: Determine the installed version of Visual Studio (Prioritize Enterprise over Professional) 21 | if exist "%PROGRAM_FILES_DIR%\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" set VCVARS_2008=%PROGRAM_FILES_DIR%\Microsoft Visual Studio 9.0\VC\vcvarsall.bat 22 | if exist "%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" set VCVARS_20xx=%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat 23 | if exist "%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2017\Professional\VC\Auxiliary\Build\vcvarsall.bat" set VCVARS_20xx=%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2017\Professional\VC\Auxiliary\Build\vcvarsall.bat 24 | if exist "%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" set VCVARS_20xx=%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat 25 | if exist "%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" set VCVARS_20xx=%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat 26 | if exist "%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvarsall.bat" set VCVARS_20xx=%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvarsall.bat 27 | if exist "%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" set VCVARS_20xx=%PROGRAM_FILES_DIR%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat 28 | if exist "%PROGRAM_FILES_X64%\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" set VCVARS_20xx=%PROGRAM_FILES_X64%\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat 29 | if exist "%PROGRAM_FILES_X64%\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvarsall.bat" set VCVARS_20xx=%PROGRAM_FILES_X64%\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvarsall.bat 30 | if exist "%PROGRAM_FILES_X64%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" set VCVARS_20xx=%PROGRAM_FILES_X64%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat 31 | 32 | :: Build the project using Visual Studio 2008 and 2017+ 33 | rem if not "x%VCVARS_2008%" == "x" call :BuildProject "%VCVARS_2008%" %PROJECT_NAME%_vs08.sln En en x86 Win32 34 | rem if not "x%VCVARS_2008%" == "x" call :BuildProject "%VCVARS_2008%" %PROJECT_NAME%_vs08.sln En en x64 x64 35 | if not "x%VCVARS_20xx%" == "x" call :BuildProject "%VCVARS_20xx%" %PROJECT_NAME%.sln En en x86 Win32 36 | if not "x%VCVARS_20xx%" == "x" call :BuildProject "%VCVARS_20xx%" %PROJECT_NAME%.sln En en x64 x64 37 | echo [*] Build complete. 38 | 39 | :: Update web pages 40 | if not "x%PUBLISH_PROJECT%" == "x1" goto:eof 41 | echo [*] Updating web pages ... 42 | pushd ..\..\WWW 43 | MakeWeb.exe /nologo 44 | popd 45 | goto:eof 46 | 47 | ::----------------------------------------------------------------------------- 48 | :: Build the project 49 | :: 50 | :: Parameters: 51 | :: 52 | :: %1 Full path to the VCVARS.BAT file 53 | :: %2 Plain name of the .sln solution file 54 | :: %3 Language version (Cn, En, Ko, Pl, Ru) 55 | :: %4 Language version lowercase (cn, en, ko, pl, ru) 56 | :: %5 x86, x64, amd64_arm64 57 | :: %6 Win32, x64, ARM64 58 | :: 59 | 60 | :BuildProject 61 | echo [*] Building %PROJECT_NAME% (%3, %6) ... 62 | call %1 %5 >nul 63 | devenv.com %2 /project "%PROJECT_NAME%" /rebuild "Release|%6" >nul 64 | ::if "%5" == "x64" PostBuild.exe %PROJECT_NAME%.rc /nologo 65 | 66 | :PublishProject 67 | if not "x%PUBLISH_PROJECT%" == "x1" goto RestoreEnvironment 68 | if not exist .\bin\%6\Release\%PROJECT_NAME%.exe goto RestoreEnvironment 69 | echo [*] Updating %PROJECT_NAME% in ZIP ... 70 | pushd .\bin 71 | copy .\%6\Release\%PROJECT_NAME%.exe .\%6\%PROJECT_NAME%.exe >nul 72 | zip.exe -u9 ..\..\..\WWW\web\download\%PROJECT_ZIP_NAME%.zip .\%6\%PROJECT_NAME%.exe >nul 73 | zip.exe -ju9 ..\..\..\WWW\web\download\%PROJECT_ZIP_NAME%.zip ..\doc\History.txt >nul 74 | zip.exe -ju9 ..\..\..\WWW\web\download\%PROJECT_ZIP_NAME%.zip ..\doc\ReadMe.txt >nul 75 | del .\%6\%PROJECT_NAME%.exe 76 | popd 77 | 78 | :: Restore environment variables to the old level 79 | :RestoreEnvironment 80 | set INCLUDE=%SAVE_INCLUDE% 81 | set PATH=%SAVE_PATH% 82 | set LIB=%SAVE_LIB% 83 | 84 | :: Delete environment variables that are set by Visual Studio 85 | set __VSCMD_PREINIT_PATH= 86 | set EXTERNAL_INCLUDE= 87 | set VSINSTALLDIR= 88 | set VCINSTALLDIR= 89 | set DevEnvDir= 90 | set LIBPATH= 91 | 92 | -------------------------------------------------------------------------------- /DlgDataEditor.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* DlgDataEditor.cpp Copyright (c) Ladislav Zezula 2014 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Description: Common module for a few simple dialogs */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 19.03.14 1.00 Lad Created */ 9 | /*****************************************************************************/ 10 | 11 | #include "FileTest.h" 12 | #include "resource.h" 13 | 14 | //----------------------------------------------------------------------------- 15 | // Local structures 16 | 17 | struct TDialogData 18 | { 19 | TAnchors * pAnchors; 20 | ULONGLONG BaseAddress; 21 | LPBYTE pbFileData; 22 | size_t cbFileData; 23 | HWND hDlg; 24 | }; 25 | 26 | //----------------------------------------------------------------------------- 27 | // Message handlers 28 | 29 | static void OnInitDialog(HWND hDlg, LPARAM lParam) 30 | { 31 | TDialogData * pData = (TDialogData *)lParam; 32 | TAnchors * pAnchors; 33 | HWND hWndChild; 34 | 35 | // Initialize dialog data 36 | SetDialogIcon(hDlg, IDI_FILE_TEST); 37 | SetDialogData(hDlg, pData); 38 | pData->hDlg = hDlg; 39 | 40 | // Center the dialog to parent 41 | CenterWindowToParent(hDlg); 42 | 43 | // Configure the anchors 44 | pData->pAnchors = pAnchors = new TAnchors(hDlg); 45 | if(pAnchors != NULL) 46 | { 47 | pAnchors->AddAnchor(hDlg, IDC_FILE_DATA, akAll); 48 | pAnchors->AddAnchor(hDlg, IDC_INFORMATION, akLeft | akRight | akBottom); 49 | pAnchors->AddAnchor(hDlg, IDOK, akRight | akBottom); 50 | } 51 | 52 | // Configure the data viewer 53 | hWndChild = GetDlgItem(hDlg, IDC_FILE_DATA); 54 | if(hWndChild != NULL) 55 | { 56 | DataEditor_SetDataFormat(hWndChild, PtrPlatformSpecific, 0x10); 57 | DataEditor_SetData(hWndChild, (ULONGLONG)pData->BaseAddress, pData->pbFileData, pData->cbFileData); 58 | } 59 | } 60 | 61 | static void OnNotify(HWND hDlg, NMHDR * pNMHDR) 62 | { 63 | if(pNMHDR->code == DEN_EXCEPTION) 64 | { 65 | PDTE_EXCEPTION_DATA pExceptionData = (PDTE_EXCEPTION_DATA)pNMHDR; 66 | HWND hWndChild = GetDlgItem(hDlg, IDC_INFORMATION); 67 | 68 | if(hWndChild != NULL) 69 | { 70 | SetWindowTextRc(hWndChild, IDS_DATA_EXCEPTION, 71 | pExceptionData->WriteOperation ? _T("writing") : _T("reading"), 72 | pExceptionData->ExceptionAddress); 73 | } 74 | } 75 | } 76 | 77 | static void OnDestroy(HWND hDlg) 78 | { 79 | TDialogData * pData = ((TDialogData *)GetWindowLongPtr(hDlg, DWLP_USER)); 80 | 81 | if(pData != NULL) 82 | { 83 | if(pData->pAnchors != NULL) 84 | delete pData->pAnchors; 85 | pData->pAnchors = NULL; 86 | } 87 | } 88 | 89 | static int OnFlushViewOfFileClick(HWND hDlg) 90 | { 91 | TDialogData* pData = ((TDialogData*)GetWindowLongPtr(hDlg, DWLP_USER)); 92 | 93 | FlushViewOfFile(pData->pbFileData, pData->cbFileData); 94 | 95 | return TRUE; 96 | } 97 | 98 | static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 99 | { 100 | TDialogData * pData; 101 | UINT nIDCtrl; 102 | UINT nIDNotify; 103 | 104 | // Dialog initialization 105 | switch(uMsg) 106 | { 107 | case WM_INITDIALOG: 108 | OnInitDialog(hDlg, lParam); 109 | return TRUE; 110 | 111 | case WM_SIZE: 112 | case WM_GETMINMAXINFO: 113 | if((pData = ((TDialogData *)GetWindowLongPtr(hDlg, DWLP_USER))) != NULL) 114 | pData->pAnchors->OnMessage(uMsg, wParam, lParam); 115 | break; 116 | 117 | case WM_NOTIFY: 118 | OnNotify(hDlg, (NMHDR *)lParam); 119 | break; 120 | 121 | case WM_COMMAND: 122 | nIDNotify = HIWORD(wParam); 123 | nIDCtrl = LOWORD(wParam); 124 | 125 | if (nIDNotify == BN_CLICKED) 126 | { 127 | switch (nIDCtrl) 128 | { 129 | case IDC_FLUSH_VIEW: 130 | OnFlushViewOfFileClick(hDlg); 131 | break; 132 | 133 | default: 134 | EndDialog(hDlg, nIDCtrl); 135 | } 136 | } 137 | break; 138 | 139 | case WM_DESTROY: 140 | OnDestroy(hDlg); 141 | break; 142 | } 143 | 144 | return FALSE; 145 | } 146 | 147 | //----------------------------------------------------------------------------- 148 | // Dialog functions 149 | 150 | INT_PTR DataEditorDialog(HWND hParent, LPVOID BaseAddress, size_t ViewSize) 151 | { 152 | TDialogData Data; 153 | 154 | ZeroMemory(&Data, sizeof(TDialogData)); 155 | Data.BaseAddress = (ULONGLONG)BaseAddress; 156 | Data.pbFileData = (LPBYTE)BaseAddress; 157 | Data.cbFileData = ViewSize; 158 | return DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_DATA_EDITOR), hParent, DialogProc, (LPARAM)&Data); 159 | } 160 | -------------------------------------------------------------------------------- /TFlagString.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* TFlagString.h Copyright (c) Ladislav Zezula 2021 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Convertor of flags to string lists */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 22.04.21 1.00 Lad Created */ 9 | /*****************************************************************************/ 10 | 11 | #ifndef __TFLAGSTRING_H__ 12 | #define __TFLAGSTRING_H__ 13 | 14 | //----------------------------------------------------------------------------- 15 | // Helper functions 16 | 17 | inline const char * GetBitSeparator() 18 | { 19 | return " | "; 20 | } 21 | 22 | inline const char * GetBitSeparatorNewLine() 23 | { 24 | return " |\r\n"; 25 | } 26 | 27 | inline const char * GetNewLineSeparator() 28 | { 29 | return "\r\n"; 30 | } 31 | 32 | //----------------------------------------------------------------------------- 33 | // Structure describing the flag information - name, value, mask 34 | 35 | #define FLAGINFO_ALLSET 0xFFFFFFFF 36 | #define FLAGINFO_BITV(value) { #value, value, value } 37 | #define FLAGINFO_NUMV(value) { #value, value, FLAGINFO_ALLSET } 38 | #define FLAGINFO_MASK(mask,value) { #value, value, mask } 39 | #define FLAGINFO_SEPARATOR() { (LPCSTR)1, 0, 0 } 40 | #define FLAGINFO_END() { (LPCSTR)0, 0, 0 } 41 | 42 | struct TFlagInfo 43 | { 44 | bool IsValuePresent(ULONG64 dwBitMask) 45 | { 46 | return (IsSeparator() == false) && ((dwBitMask & dwMask) == (dwValue & dwMask)); 47 | } 48 | 49 | bool IsSeparator() 50 | { 51 | return (szFlagText == (LPCSTR)1); 52 | } 53 | 54 | bool IsTerminator() 55 | { 56 | return (szFlagText == NULL); 57 | } 58 | 59 | const char * szFlagText; 60 | unsigned int dwValue; 61 | unsigned int dwMask; 62 | }; 63 | 64 | //----------------------------------------------------------------------------- 65 | // Extended version of TFlagInfo for dialogs 66 | 67 | struct TDlgFlagInfo : public TFlagInfo 68 | { 69 | TDlgFlagInfo(const char * text, unsigned int value, unsigned int mask, unsigned int btn) 70 | { 71 | szFlagText = text; 72 | dwValue = value; 73 | dwMask = mask; 74 | dwButtonType = btn; 75 | } 76 | 77 | unsigned int dwButtonType; 78 | }; 79 | 80 | //----------------------------------------------------------------------------- 81 | // The TFlagString class 82 | 83 | class TFlagString : public TFastString 84 | { 85 | public: 86 | 87 | TFlagString(TFlagInfo * pFlags, ULONG64 dwBitMask, const char * szNextSep = NULL) : TFastString() 88 | { 89 | // Reset the number of flags that were converted to text 90 | dwFlagsConverted = 0; 91 | 92 | // Only if we have some flags given 93 | if(pFlags != NULL) 94 | { 95 | // Configure separators 96 | const char * szNextSeparator = (szNextSep != NULL) ? szNextSep : GetBitSeparator(); 97 | const char * szSeparator = ""; 98 | 99 | // Parse all flags and add them to the buffer 100 | for(size_t i = 0; !pFlags->IsTerminator(); i++, pFlags++) 101 | { 102 | if(pFlags->IsValuePresent(dwBitMask)) 103 | { 104 | ULONG64 dwMask64 = pFlags->dwMask; 105 | 106 | AppendSeparatorAndText(szSeparator, pFlags->szFlagText); 107 | szSeparator = szNextSeparator; 108 | dwBitMask = dwBitMask & ~dwMask64; 109 | dwFlagsConverted++; 110 | } 111 | } 112 | 113 | // Is there a nonzero value left? 114 | if(dwBitMask != 0) 115 | { 116 | char szLeftOver[0x20]; 117 | 118 | StringCchPrintfA(szLeftOver, _countof(szLeftOver), "0x%08x", dwBitMask); 119 | AppendSeparatorAndText(szSeparator, szLeftOver); 120 | } 121 | } 122 | 123 | // Nothing appended? 124 | if(IsEmpty()) 125 | { 126 | AppendString(_T("0")); 127 | } 128 | } 129 | 130 | ULONG GetConvertedFlagsCount() 131 | { 132 | return dwFlagsConverted; 133 | } 134 | 135 | protected: 136 | 137 | void AppendSeparatorAndText(const char * szSeparator, const char * szFlagText) 138 | { 139 | size_t nLength1 = strlen(szSeparator); 140 | size_t nLength2 = strlen(szFlagText); 141 | 142 | // Append separator, if needed 143 | if(EnsureSpace(Length() + nLength1 + nLength2)) 144 | { 145 | #ifdef _UNICODE 146 | MultiByteToWideChar(CP_ACP, 0, szSeparator, -1, m_pBufferPtr, (int)nLength1); 147 | MultiByteToWideChar(CP_ACP, 0, szFlagText, -1, m_pBufferPtr+nLength1, (int)nLength2); 148 | #else 149 | memcpy(m_pBufferPtr, szSeparator, nLength1); 150 | memcpy(m_pBufferPtr+nLength1, szFlagText, nLength2); 151 | #endif 152 | m_pBufferPtr += (nLength1 + nLength2); 153 | } 154 | } 155 | 156 | ULONG dwFlagsConverted; // Number of flags that was converted to string 157 | }; 158 | 159 | #endif // __TFLAGSTRING_H__ 160 | -------------------------------------------------------------------------------- /DlgSimple.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* DlgSimple.cpp Copyright (c) Ladislav Zezula 2014 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Description: Common module for a few simple dialogs */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 18.03.14 1.00 Lad Created */ 9 | /*****************************************************************************/ 10 | 11 | #include "FileTest.h" 12 | #include "resource.h" 13 | 14 | //----------------------------------------------------------------------------- 15 | // Local functions 16 | 17 | static void SetWindowTextModuleVersion(HWND hWndChild, HMODULE hMod) 18 | { 19 | ULARGE_INTEGER Version; 20 | TCHAR szModName[MAX_PATH + 1]; 21 | TCHAR szFormat[255]; 22 | TCHAR szText[255]; 23 | 24 | if(GetModuleFileName(hMod, szModName, MAX_PATH)) 25 | { 26 | // Is such window really there ? 27 | if(hWndChild != NULL) 28 | { 29 | GetWindowText(hWndChild, szFormat, _countof(szFormat)); 30 | GetModuleVersion(szModName, &Version); 31 | StringCchPrintf(szText, _countof(szText), szFormat, 32 | HIWORD(Version.HighPart), 33 | LOWORD(Version.HighPart), 34 | HIWORD(Version.LowPart), 35 | LOWORD(Version.LowPart)); 36 | SetWindowText(hWndChild, szText); 37 | } 38 | } 39 | } 40 | 41 | static void SetWindowTextFileTime(HWND hWndChild, LARGE_INTEGER & FileTime) 42 | { 43 | TCHAR szText[0x80] = {0}; 44 | 45 | if(FileTimeToText(szText, &szText[_countof(szText) - 1], (PFILETIME)(&FileTime), FALSE)) 46 | { 47 | SetWindowText(hWndChild, szText); 48 | } 49 | } 50 | 51 | static void SetWindowTextFileAttributes(HWND hWndChild, DWORD dwAttributes) 52 | { 53 | TFlagString fs(FileAttributesValues, dwAttributes, GetNewLineSeparator()); 54 | 55 | SetWindowText(hWndChild, fs); 56 | } 57 | 58 | //----------------------------------------------------------------------------- 59 | // Event handlers 60 | 61 | static int OnInitDialog(HWND hDlg, LPARAM lParam) 62 | { 63 | PFILE_BASIC_INFORMATION pBasicInfo = (PFILE_BASIC_INFORMATION)lParam; 64 | HWND hWndChild; 65 | 66 | // Set the dialog icon 67 | SetDialogIcon(hDlg, IDI_FILE_TEST); 68 | 69 | // Parse all child windows 70 | // If there is IDC_VERSION static text, supply the 4-digit version from resources 71 | hWndChild = GetDlgItem(hDlg, IDC_FILETEST_WEB); 72 | if(hWndChild != NULL) 73 | InitURLButton(hDlg, IDC_FILETEST_WEB, FALSE); 74 | 75 | // If there is IDC_VERSION static text, supply the 4-digit version from resources 76 | hWndChild = GetDlgItem(hDlg, IDC_VERSION); 77 | if(hWndChild != NULL) 78 | SetWindowTextModuleVersion(hWndChild, NULL); 79 | 80 | // Last write time 81 | if(pBasicInfo != NULL) 82 | { 83 | if((hWndChild = GetDlgItem(hDlg, IDC_CREATION_TIME)) != NULL) 84 | SetWindowTextFileTime(hWndChild, pBasicInfo->CreationTime); 85 | if((hWndChild = GetDlgItem(hDlg, IDC_LAST_ACCESS_TIME)) != NULL) 86 | SetWindowTextFileTime(hWndChild, pBasicInfo->LastAccessTime); 87 | if((hWndChild = GetDlgItem(hDlg, IDC_LAST_WRITE_TIME)) != NULL) 88 | SetWindowTextFileTime(hWndChild, pBasicInfo->LastWriteTime); 89 | if((hWndChild = GetDlgItem(hDlg, IDC_CHANGE_TIME)) != NULL) 90 | SetWindowTextFileTime(hWndChild, pBasicInfo->ChangeTime); 91 | if((hWndChild = GetDlgItem(hDlg, IDC_FILE_ATTRIBUTES)) != NULL) 92 | SetWindowTextFileAttributes(hWndChild, pBasicInfo->FileAttributes); 93 | } 94 | 95 | return TRUE; 96 | } 97 | 98 | static BOOL OnCommand(HWND hDlg, HWND hWndFrom, UINT nNotifyCode, UINT nCtrlID) 99 | { 100 | if(nNotifyCode == BN_CLICKED) 101 | { 102 | // An URL button leads to opening its WWW page 103 | if(IsURLButton(hWndFrom)) 104 | { 105 | ClickURLButton(hWndFrom); 106 | return TRUE; 107 | } 108 | 109 | // Any other button closes the dialog 110 | EndDialog(hDlg, nCtrlID); 111 | return TRUE; 112 | } 113 | return FALSE; 114 | } 115 | 116 | //----------------------------------------------------------------------------- 117 | // Message handler 118 | 119 | static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 120 | { 121 | switch(uMsg) 122 | { 123 | case WM_INITDIALOG: 124 | return OnInitDialog(hDlg, lParam); 125 | 126 | case WM_DRAWITEM: 127 | DrawURLButton(hDlg, (LPDRAWITEMSTRUCT)lParam); 128 | return FALSE; 129 | 130 | case WM_COMMAND: 131 | return OnCommand(hDlg, (HWND)lParam, HIWORD(wParam), LOWORD(wParam)); 132 | } 133 | 134 | return FALSE; 135 | } 136 | 137 | //----------------------------------------------------------------------------- 138 | // Dialog functions 139 | 140 | INT_PTR HelpAboutDialog(HWND hWndParent) 141 | { 142 | return DialogBox(g_hInst, MAKEINTRESOURCE(IDD_HELP_ABOUT), hWndParent, DialogProc); 143 | } 144 | 145 | INT_PTR HelpCommandLineDialog(HWND hWndParent) 146 | { 147 | return DialogBox(g_hInst, MAKEINTRESOURCE(IDD_HELP_COMMAND_LINE), hWndParent, DialogProc); 148 | } 149 | 150 | INT_PTR ObjectIDActionDialog(HWND hWndParent) 151 | { 152 | return DialogBox(g_hInst, MAKEINTRESOURCE(IDD_OBJECT_ID_MORE), hWndParent, DialogProc); 153 | } 154 | 155 | INT_PTR ObjectGuidHelpDialog(HWND hWndParent) 156 | { 157 | return DialogBox(g_hInst, MAKEINTRESOURCE(IDD_OBJECT_GUID_HELP), hWndParent, DialogProc); 158 | } 159 | 160 | INT_PTR FileAttributesDialog(HWND hWndParent, PFILE_BASIC_INFORMATION pBasicInfo) 161 | { 162 | return DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_FILE_ATTRIBUTES), hWndParent, DialogProc, (LPARAM)(pBasicInfo)); 163 | } 164 | 165 | INT_PTR NtAttributesDialog(HWND hWndParent, PFILE_BASIC_INFORMATION pBasicInfo) 166 | { 167 | return DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_NT_ATTRIBUTES), hWndParent, DialogProc, (LPARAM)(pBasicInfo)); 168 | } 169 | -------------------------------------------------------------------------------- /TToolTip.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* TToolTip.cpp Copyright (c) Ladislav Zezula 2014 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Implementation of TTooltip class */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 16.03.14 1.00 Lad The first version of TToolTip.cpp */ 9 | /*****************************************************************************/ 10 | 11 | #include "FileTest.h" 12 | 13 | //----------------------------------------------------------------------------- 14 | // Tooltip implementation 15 | 16 | TToolTip::TToolTip() 17 | { 18 | hWndToolTip = NULL; 19 | szToolTipText = NULL; 20 | cchTooltipText = 0x400; 21 | }; 22 | 23 | TToolTip::~TToolTip() 24 | { 25 | Destroy(); 26 | } 27 | 28 | BOOL TToolTip::Initialize(HINSTANCE hInst, HWND hWndParent) 29 | { 30 | // Sanity check 31 | assert(hWndToolTip == NULL); 32 | 33 | // Allocate buffer for constructing tooltip test 34 | szToolTipText = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, cchTooltipText * sizeof(TCHAR)); 35 | if(szToolTipText == NULL) 36 | return FALSE; 37 | 38 | // Create the tooltip window 39 | hWndToolTip = CreateWindowEx(NULL, 40 | TOOLTIPS_CLASS, 41 | NULL, 42 | WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, 43 | CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 44 | hWndParent, 45 | NULL, 46 | hInst, 47 | NULL); 48 | if(hWndToolTip == NULL) 49 | return FALSE; 50 | 51 | // Initialize the tooltip window 52 | SetWindowPos(hWndToolTip, HWND_TOPMOST,0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 53 | SendMessage(hWndToolTip, TTM_SETMAXTIPWIDTH, 0, 300); 54 | SendMessage(hWndToolTip, TTM_ACTIVATE, TRUE, 0); 55 | return TRUE; 56 | } 57 | 58 | void TToolTip::Destroy() 59 | { 60 | if(hWndToolTip != NULL) 61 | DestroyWindow(hWndToolTip); 62 | hWndToolTip = NULL; 63 | 64 | if(szToolTipText != NULL) 65 | HeapFree(GetProcessHeap(), 0, szToolTipText); 66 | szToolTipText = NULL; 67 | } 68 | 69 | //----------------------------------------------------------------------------- 70 | // Adds a tooltip that will display user-friendly flags 71 | 72 | BOOL TToolTip::AddToolTip(HWND hDlg, UINT nIDChild, TFlagInfo * pFlags) 73 | { 74 | return AddToolTipInternal(hDlg, nIDChild, LPSTR_TEXTCALLBACK, pFlags); 75 | } 76 | 77 | BOOL TToolTip::AddToolTip(HWND hDlg, UINT nIDChild, UINT nIDTip) 78 | { 79 | return AddToolTipInternal(hDlg, nIDChild, MAKEINTRESOURCE(nIDTip), NULL); 80 | } 81 | 82 | //----------------------------------------------------------------------------- 83 | // Message handler 84 | 85 | LRESULT TToolTip::HandleMessages(HWND /* hDlg */, UINT uMsg, WPARAM /* wParam */, LPARAM lParam, BOOL * pbHandled) 86 | { 87 | LPNMTTDISPINFO pTTDispInfo; 88 | BOOL bHandled = FALSE; 89 | 90 | if(uMsg == WM_NOTIFY) 91 | { 92 | // The message must be TTN_GETDISPINFO and the 'idFrom' must be a window handle 93 | pTTDispInfo = (LPNMTTDISPINFO)lParam; 94 | if(pTTDispInfo->hdr.code == TTN_GETDISPINFO && (pTTDispInfo->uFlags & TTF_IDISHWND) && pTTDispInfo->lParam != 0) 95 | { 96 | // Call the tooltip handler 97 | OnGetTooltipText(pTTDispInfo); 98 | bHandled = TRUE; 99 | } 100 | } 101 | 102 | if(pbHandled != NULL) 103 | *pbHandled = FALSE; 104 | return 0; 105 | } 106 | 107 | //----------------------------------------------------------------------------- 108 | // Protected functions 109 | 110 | BOOL TToolTip::AddToolTipInternal(HWND hDlg, UINT nIDCtrl, LPCTSTR szTip, TFlagInfo * pFlags) 111 | { 112 | TTTOOLINFO ti; 113 | TCHAR szClassName[0x80]; 114 | DWORD dwStyle; 115 | HWND hWndChild; 116 | BOOL bResult = FALSE; 117 | 118 | // Only if we actually have a tooltip 119 | if(hWndToolTip != NULL) 120 | { 121 | // If the child window is not valid, do nothing 122 | hWndChild = GetDlgItem(hDlg, nIDCtrl); 123 | if(hWndChild != NULL) 124 | { 125 | // If the child window is a static text without SS_NOTIFY, 126 | // the tooltip would not activate. We need to set the SS_NOTIFY flag 127 | GetClassName(hWndChild, szClassName, _countof(szClassName)); 128 | if(!_tcsicmp(szClassName, WC_STATIC)) 129 | { 130 | dwStyle = GetWindowLong(hWndChild, GWL_STYLE); 131 | if((dwStyle & SS_NOTIFY) == 0) 132 | SetWindowLong(hWndChild, GWL_STYLE, dwStyle | SS_NOTIFY); 133 | } 134 | 135 | // Note: Make sure we put the size for COMCTL32.dll version 4.70 136 | ZeroMemory(&ti, sizeof(TTTOOLINFO)); 137 | ti.cbSize = CCSIZEOF_STRUCT(TTTOOLINFO, lParam); 138 | ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS; 139 | ti.hwnd = hDlg; 140 | ti.uId = (UINT_PTR)hWndChild; 141 | ti.hinst = g_hInst; 142 | ti.lpszText = (LPTSTR)szTip; 143 | ti.lParam = (LPARAM)pFlags; 144 | bResult = (BOOL)SendMessage(hWndToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti); 145 | } 146 | } 147 | 148 | return bResult; 149 | } 150 | 151 | void TToolTip::OnGetTooltipText(LPNMTTDISPINFO pTTDispInfo) 152 | { 153 | TFlagInfo * pFlags = (TFlagInfo *)pTTDispInfo->lParam; 154 | TCHAR szWindowText[0x80]; 155 | DWORD dwValue32 = 0; 156 | HWND hWndChild = (HWND)pTTDispInfo->hdr.idFrom; 157 | 158 | // Only if the text buffer has been allocated 159 | if(pFlags && szToolTipText) 160 | { 161 | // Reset the tooltip info to an empty string 162 | szToolTipText[0] = 0; 163 | 164 | // Retrieve the window text and convert it to 32-bit hexa value 165 | GetWindowText(hWndChild, szWindowText, _countof(szWindowText)); 166 | if(Text2Hex32(szWindowText, &dwValue32) == ERROR_SUCCESS) 167 | { 168 | // Convert the flags to string 169 | FlagsToString(pFlags, szToolTipText, cchTooltipText, dwValue32, true); 170 | 171 | // Supply the text to the tooltip 172 | pTTDispInfo->lpszText = szToolTipText; 173 | pTTDispInfo->szText[0] = 0; 174 | } 175 | else 176 | { 177 | StringCchPrintf(pTTDispInfo->szText, _countof(pTTDispInfo->szText), _T("Error converting \"%s\" to 32-bit integer"), szWindowText); 178 | } 179 | } 180 | } 181 | 182 | -------------------------------------------------------------------------------- /FileTest.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | {97fa0adf-94c2-490e-a30b-3fec2e2bb059} 18 | 19 | 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | Source Files 56 | 57 | 58 | Source Files 59 | 60 | 61 | Source Files 62 | 63 | 64 | Source Files 65 | 66 | 67 | Source Files 68 | 69 | 70 | Source Files 71 | 72 | 73 | Source Files 74 | 75 | 76 | Source Files 77 | 78 | 79 | Source Files 80 | 81 | 82 | Source Files 83 | 84 | 85 | Source Files 86 | 87 | 88 | Source Files 89 | 90 | 91 | Source Files 92 | 93 | 94 | Source Files 95 | 96 | 97 | Source Files 98 | 99 | 100 | Source Files 101 | 102 | 103 | Source Files 104 | 105 | 106 | Source Files 107 | 108 | 109 | Source Files 110 | 111 | 112 | Source Files 113 | 114 | 115 | Source Files 116 | 117 | 118 | 119 | 120 | Source Files 121 | 122 | 123 | 124 | 125 | Header Files 126 | 127 | 128 | Header Files 129 | 130 | 131 | Header Files 132 | 133 | 134 | Header Files 135 | 136 | 137 | Header Files 138 | 139 | 140 | Header Files 141 | 142 | 143 | Header Files 144 | 145 | 146 | Header Files 147 | 148 | 149 | Header Files 150 | 151 | 152 | Header Files 153 | 154 | 155 | Header Files 156 | 157 | 158 | Header Files 159 | 160 | 161 | 162 | 163 | Resource Files 164 | 165 | 166 | 167 | 168 | Resource Files 169 | 170 | 171 | Resource Files 172 | 173 | 174 | Resource Files 175 | 176 | 177 | Resource Files 178 | 179 | 180 | Resource Files 181 | 182 | 183 | Resource Files 184 | 185 | 186 | 187 | 188 | Resource Files 189 | 190 | 191 | Resource Files 192 | 193 | 194 | 195 | 196 | Doc Files 197 | 198 | 199 | -------------------------------------------------------------------------------- /AceResource.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* AceResource.h Copyright (c) Ladislav Zezula 2023 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Helpers for SYSTEM_RESOURCE_ATTRIBUTE_ACE */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 23.11.23 1.00 Lad Created */ 9 | /*****************************************************************************/ 10 | 11 | #ifndef __ACE_RESOURCE_H__ 12 | #define __ACE_RESOURCE_H__ 13 | 14 | //----------------------------------------------------------------------------- 15 | // Not defined in older SDKs 16 | 17 | #ifndef CLAIM_SECURITY_ATTRIBUTE_TYPE_INVALID 18 | 19 | #define CLAIM_SECURITY_ATTRIBUTE_TYPE_INVALID 0x00 20 | 21 | #define CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64 0x01 22 | #define CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64 0x02 23 | 24 | // 25 | // Case insensitive attribute value string by default. 26 | // Unless the flag CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE 27 | // is set indicating otherwise. 28 | // 29 | 30 | #define CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING 0x03 // Zero terminated UTF-16 string 31 | #define CLAIM_SECURITY_ATTRIBUTE_TYPE_FQBN 0x04 // Refused by Windows up to 11 32 | #define CLAIM_SECURITY_ATTRIBUTE_TYPE_SID 0x05 // 4 bytes of length, followed by the SID 33 | #define CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN 0x06 // Each item has 8 bytes, upper 4 bytes must be zero 34 | #define CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING 0x10 // 4 bytes of length, followed by array of BYTEs 35 | 36 | // 37 | // Attribute Flags 38 | // 39 | 40 | // 41 | // Attribute must not be inherited across process spawns. 42 | // 43 | 44 | #define CLAIM_SECURITY_ATTRIBUTE_NON_INHERITABLE 0x0001 45 | 46 | 47 | // 48 | // Attribute value is compared in a case sensitive way. It is valid with string value 49 | // or composite type containing string value. For other types of value, this flag 50 | // will be ignored. Currently, it is valid with the two types: 51 | // CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING and CLAIM_SECURITY_ATTRIBUTE_TYPE_FQBN. 52 | // 53 | #define CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE 0x0002 54 | 55 | // 56 | // Attribute is considered only for Deny Aces. 57 | // 58 | 59 | #define CLAIM_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY 0x0004 60 | 61 | // 62 | // Attribute is disabled by default. 63 | // 64 | 65 | #define CLAIM_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT 0x0008 66 | 67 | // 68 | // Attribute is disabled. 69 | // 70 | 71 | #define CLAIM_SECURITY_ATTRIBUTE_DISABLED 0x0010 72 | 73 | // 74 | // Attribute is mandatory. 75 | // 76 | 77 | #define CLAIM_SECURITY_ATTRIBUTE_MANDATORY 0x0020 78 | 79 | 80 | #define CLAIM_SECURITY_ATTRIBUTE_VALID_FLAGS ( \ 81 | CLAIM_SECURITY_ATTRIBUTE_NON_INHERITABLE | \ 82 | CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE | \ 83 | CLAIM_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY | \ 84 | CLAIM_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT | \ 85 | CLAIM_SECURITY_ATTRIBUTE_DISABLED | \ 86 | CLAIM_SECURITY_ATTRIBUTE_MANDATORY ) 87 | 88 | 89 | // 90 | // Reserve upper 16 bits for custom flags. These should be preserved but not 91 | // validated as they do not affect security in any way. 92 | // 93 | #define CLAIM_SECURITY_ATTRIBUTE_CUSTOM_FLAGS 0xFFFF0000 94 | 95 | typedef struct _CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 96 | { 97 | DWORD Name; // Name of the attribute. Offset from beginning of structure. 98 | WORD ValueType; // Data type of attribute. 99 | WORD Reserved; // Must be 0 100 | DWORD Flags; // Attribute Flags 101 | DWORD ValueCount; // Number of values. 102 | 103 | // The actual value itself. 104 | union 105 | { 106 | DWORD pInt64[ANYSIZE_ARRAY]; 107 | DWORD pUint64[ANYSIZE_ARRAY]; 108 | DWORD ppString[ANYSIZE_ARRAY]; 109 | DWORD pFqbn[ANYSIZE_ARRAY]; 110 | DWORD pOctetString[ANYSIZE_ARRAY]; 111 | } Values; 112 | } CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1, *PCLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1; 113 | 114 | #endif 115 | 116 | //----------------------------------------------------------------------------- 117 | // Octet string structure 118 | 119 | typedef struct _ACE_OCTET_STRING 120 | { 121 | ULONG cbData; 122 | BYTE pbData[1]; 123 | } ACE_OCTET_STRING, *PACE_OCTET_STRING; 124 | 125 | inline ULONG OctetStringSize(PACE_OCTET_STRING pOctetString) 126 | { 127 | return sizeof(ULONG) + pOctetString->cbData; 128 | } 129 | 130 | //----------------------------------------------------------------------------- 131 | // Helpers 132 | 133 | struct ACE_CSA_OBJECT 134 | { 135 | ACE_CSA_OBJECT(); 136 | ~ACE_CSA_OBJECT(); 137 | 138 | LPBYTE ImportData(LPBYTE pbStructure, LPBYTE pbEnd, size_t Offset, size_t Length); 139 | LPBYTE ImportOctet(PACE_OCTET_STRING pOctetString); 140 | void Clear(); 141 | 142 | virtual size_t ExportSize(size_t cbAlignSize = 1) const; 143 | virtual LPBYTE Export(LPBYTE pbPtr, LPBYTE pbEnd) const; 144 | virtual LPBYTE Default(LPBYTE pbPtr, LPBYTE pbEnd, DWORD dwIndexHint) const; 145 | virtual LPBYTE Import(LPCVOID lpObject); 146 | 147 | void * lpData; 148 | size_t cbData; 149 | }; 150 | 151 | struct ACE_CSA_DWORD64 : public ACE_CSA_OBJECT 152 | { 153 | LPBYTE Default(LPBYTE pbPtr, LPBYTE pbEnd, DWORD dwIndexHint) const; 154 | LPBYTE Import(LPCVOID lpObject); 155 | }; 156 | 157 | struct ACE_CSA_LPWSTR : public ACE_CSA_OBJECT 158 | { 159 | LPBYTE Default(LPBYTE pbPtr, LPBYTE pbEnd, DWORD dwIndexHint) const; 160 | LPBYTE Import(LPCVOID lpObject); 161 | size_t StringLength(LPCVOID lpObject) const; 162 | }; 163 | 164 | struct ACE_CSA_SID : public ACE_CSA_OBJECT 165 | { 166 | LPBYTE Default(LPBYTE pbPtr, LPBYTE pbEnd, DWORD dwIndexHint) const; 167 | LPBYTE Import(LPCVOID lpObject); 168 | }; 169 | 170 | struct ACE_CSA_BOOLEAN : public ACE_CSA_OBJECT 171 | { 172 | size_t ExportSize(size_t cbAlignSize = 1) const; 173 | LPBYTE Default(LPBYTE pbPtr, LPBYTE pbEnd, DWORD dwIndexHint) const; 174 | LPBYTE Import(LPCVOID lpObject); 175 | }; 176 | 177 | struct ACE_CSA_OCTET_STRING : public ACE_CSA_OBJECT 178 | { 179 | LPBYTE Default(LPBYTE pbPtr, LPBYTE pbEnd, DWORD dwIndexHint) const; 180 | LPBYTE Import(LPCVOID lpObject); 181 | }; 182 | 183 | struct ACE_CSA_HELPER 184 | { 185 | ACE_CSA_HELPER(LPCWSTR szName, WORD ValueType, DWORD ValueCount = 3); 186 | ACE_CSA_HELPER(); 187 | ~ACE_CSA_HELPER(); 188 | void InitialReset(); 189 | void Clear(); 190 | 191 | NTSTATUS SetValueName(LPCWSTR szName); 192 | NTSTATUS SetValueType(WORD wValueType, DWORD dwValueCount); 193 | NTSTATUS SetValueData(LPCVOID lpObject, ULONG nIndex); 194 | NTSTATUS AllocateElements(); 195 | 196 | NTSTATUS Import(LPBYTE pbAttrRel, LPBYTE pbAttrEnd, PULONG pcbMoveBy = NULL); 197 | 198 | PCLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 Export(PULONG pcbLength = NULL) const; 199 | ULONG GetSizeAlignedToMax(LPBYTE pbPtr, LPBYTE pbEnd, ULONG cbLength); 200 | 201 | ACE_CSA_LPWSTR Name; 202 | WORD ValueType; 203 | WORD Reserved; 204 | DWORD Flags; 205 | DWORD ValueCount; 206 | 207 | ACE_CSA_OBJECT * ppObjects; 208 | }; 209 | 210 | NTSTATUS CopyDataAway(LPBYTE pbPtr, LPBYTE pbEnd, LPCVOID lpData, ULONG cbData, PULONG pcbMoveBy = NULL); 211 | 212 | #endif // __ACE_RESOURCE_H__ 213 | -------------------------------------------------------------------------------- /Page08Ea.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* Page08Ea.cpp Copyright (c) Ladislav Zezula 2005 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Description : */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 15.08.05 1.00 Lad The first version of Page08Ea.cpp */ 9 | /*****************************************************************************/ 10 | 11 | #include "FileTest.h" 12 | #include "resource.h" 13 | 14 | //----------------------------------------------------------------------------- 15 | // Message handlers 16 | 17 | static TAnchors * pAnchors = NULL; 18 | 19 | static int OnInitDialog(HWND hDlg, LPARAM lParam) 20 | { 21 | PROPSHEETPAGE * pPage = (PROPSHEETPAGE *)lParam; 22 | TFileTestData * pData = (TFileTestData *)pPage->lParam; 23 | 24 | UNREFERENCED_PARAMETER(lParam); 25 | UNREFERENCED_PARAMETER(hDlg); 26 | 27 | // Done by shared code 28 | SetDialogData(hDlg, pPage->lParam); 29 | 30 | // Configure dialog resizing 31 | if(pData->bEnableResizing) 32 | { 33 | pAnchors = new TAnchors(hDlg); 34 | pAnchors->AddAnchor(hDlg, IDC_EA_TITLE, akLeft | akTop | akRight); 35 | pAnchors->AddAnchor(hDlg, IDC_EA_LIST, akAll); 36 | pAnchors->AddAnchor(hDlg, IDC_MOVE_UP, akLeft | akBottom); 37 | pAnchors->AddAnchor(hDlg, IDC_MOVE_DOWN, akLeft | akBottom); 38 | pAnchors->AddAnchor(hDlg, IDC_QUERY_EA, akLeft | akBottom); 39 | pAnchors->AddAnchor(hDlg, IDC_INSERT, akLeftCenter | akBottom); 40 | pAnchors->AddAnchor(hDlg, IDC_EDIT, akRight | akBottom); 41 | pAnchors->AddAnchor(hDlg, IDC_DELETE, akRight | akBottom); 42 | pAnchors->AddAnchor(hDlg, IDC_SET_EA, akRight | akBottom); 43 | pAnchors->AddAnchor(hDlg, IDC_RESULT_FRAME, akLeft | akRight | akBottom); 44 | pAnchors->AddAnchor(hDlg, IDC_ERROR_CODE_TITLE, akLeft | akBottom); 45 | pAnchors->AddAnchor(hDlg, IDC_ERROR_CODE, akLeft | akRight | akBottom); 46 | pAnchors->AddAnchor(hDlg, IDC_INFORMATION_TITLE, akLeft | akBottom); 47 | pAnchors->AddAnchor(hDlg, IDC_INFORMATION, akLeft | akRight | akBottom); 48 | } 49 | 50 | return TRUE; 51 | } 52 | 53 | static int OnSetActive(HWND hDlg) 54 | { 55 | TFileTestData * pData = GetDialogData(hDlg); 56 | BOOL bEnable = FALSE; 57 | 58 | if(IsHandleValid(pData->hFile)) 59 | bEnable = TRUE; 60 | EnableDlgItems(hDlg, bEnable, IDC_QUERY_EA, IDC_SET_EA, 0); 61 | return TRUE; 62 | } 63 | 64 | static int OnQueryEa(HWND hDlg) 65 | { 66 | PFILE_FULL_EA_INFORMATION NewEaBuffer = NULL; 67 | PFILE_FULL_EA_INFORMATION EaBuffer = NULL; 68 | TFileTestData * pData = GetDialogData(hDlg); 69 | IO_STATUS_BLOCK IoStatus = {0}; 70 | NTSTATUS Status = STATUS_SUCCESS; 71 | ULONG EaBufferSize = 0x400; 72 | 73 | // Allocate the buffer for extended attributes 74 | EaBuffer = (PFILE_FULL_EA_INFORMATION)HeapAlloc(g_hHeap, 0, EaBufferSize); 75 | if(EaBuffer != NULL) 76 | { 77 | __TryQueryEA: 78 | 79 | // Try to query the extended attributes 80 | memset(EaBuffer, 0, EaBufferSize); 81 | Status = NtQueryEaFile(pData->hFile, &IoStatus, EaBuffer, EaBufferSize, FALSE, NULL, 0, NULL, TRUE); 82 | switch(Status) 83 | { 84 | // If not enough memory, then reallocate buffer 85 | case STATUS_BUFFER_OVERFLOW: 86 | case STATUS_BUFFER_TOO_SMALL: 87 | 88 | // Allocate new buffer. If succeeded, we try to query again 89 | EaBufferSize = EaBufferSize << 1; 90 | NewEaBuffer = (PFILE_FULL_EA_INFORMATION)HeapReAlloc(g_hHeap, 0, EaBuffer, EaBufferSize); 91 | if(NewEaBuffer != NULL) 92 | { 93 | EaBuffer = NewEaBuffer; 94 | goto __TryQueryEA; 95 | } 96 | 97 | // Failed to reallocate - free the buffer and stop 98 | Status = STATUS_INSUFFICIENT_RESOURCES; 99 | break; 100 | 101 | // If OK, format the list view with extended attributes 102 | case STATUS_SUCCESS: 103 | ExtendedAttributesToListView(hDlg, EaBuffer); 104 | break; 105 | } 106 | 107 | // Free the buffer for extended attributes 108 | HeapFree(g_hHeap, 0, EaBuffer); 109 | } 110 | else 111 | { 112 | Status = STATUS_INSUFFICIENT_RESOURCES; 113 | } 114 | 115 | // Set the result to the dialog 116 | SetResultInfo(hDlg, RSI_NTSTATUS | RSI_INFORMATION, Status, &IoStatus); 117 | return TRUE; 118 | } 119 | 120 | static int OnSetEa(HWND hDlg) 121 | { 122 | TFileTestData * pData = GetDialogData(hDlg); 123 | IO_STATUS_BLOCK IoStatus = {0}; 124 | TOpenPacket OpenFile; 125 | NTSTATUS Status = STATUS_SUCCESS; 126 | 127 | // Get the EA buffer and size 128 | if(ListViewToExtendedAttributes(hDlg, OpenFile) == ERROR_SUCCESS) 129 | { 130 | // Set the extended attributes to the file 131 | Status = NtSetEaFile(pData->hFile, 132 | &IoStatus, 133 | OpenFile.pvFileEa, 134 | OpenFile.cbFileEa); 135 | 136 | // Set the result to the dialog 137 | SetResultInfo(hDlg, RSI_NTSTATUS | RSI_INFORMATION, Status, &IoStatus); 138 | OpenFile.Free(); 139 | } 140 | return TRUE; 141 | } 142 | 143 | static int OnCommand(HWND hDlg, UINT nNotify, UINT nIDCtrl) 144 | { 145 | if(nNotify == BN_CLICKED) 146 | { 147 | switch(nIDCtrl) 148 | { 149 | case IDC_QUERY_EA: 150 | return OnQueryEa(hDlg); 151 | 152 | case IDC_SET_EA: 153 | return OnSetEa(hDlg); 154 | } 155 | } 156 | 157 | return FALSE; 158 | } 159 | 160 | static int OnNotify(HWND hDlg, NMHDR * pNMHDR) 161 | { 162 | switch(pNMHDR->code) 163 | { 164 | case PSN_SETACTIVE: 165 | return OnSetActive(hDlg); 166 | } 167 | return FALSE; 168 | } 169 | 170 | //----------------------------------------------------------------------------- 171 | // Public functions 172 | 173 | INT_PTR CALLBACK PageProc08(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 174 | { 175 | // WM_INITDIALOG is special case, we need to call both init routines 176 | if(uMsg == WM_INITDIALOG) 177 | { 178 | ExtendedAttributesEditorProc(hDlg, uMsg, wParam, 0); 179 | OnInitDialog(hDlg, lParam); 180 | return TRUE; 181 | } 182 | 183 | // Call the shared part of EA editor 184 | if(ExtendedAttributesEditorProc(hDlg, uMsg, wParam, lParam)) 185 | return TRUE; 186 | 187 | // Handlers specific to our dialog 188 | switch(uMsg) 189 | { 190 | case WM_SIZE: 191 | case WM_GETMINMAXINFO: 192 | return pAnchors->OnMessage(uMsg, wParam, lParam); 193 | 194 | case WM_COMMAND: 195 | return OnCommand(hDlg, HIWORD(wParam), LOWORD(wParam)); 196 | 197 | case WM_NOTIFY: 198 | return OnNotify(hDlg, (NMHDR *)lParam); 199 | 200 | case WM_DESTROY: 201 | if(pAnchors != NULL) 202 | delete pAnchors; 203 | pAnchors = NULL; 204 | return FALSE; 205 | } 206 | return FALSE; 207 | } 208 | -------------------------------------------------------------------------------- /Page00Transaction.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* Page00Transaction.cpp Copyright (c) Ladislav Zezula 2006 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Description: */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 02.05.06 1.00 Lad The first version of Page00Transaction.cpp */ 9 | /*****************************************************************************/ 10 | 11 | #include "FileTest.h" 12 | #include "resource.h" 13 | 14 | static void UpdateDialog(HWND hDlg, DWORD dwErrCode) 15 | { 16 | TFileTestData * pData = GetDialogData(hDlg); 17 | BOOL bEnable; 18 | 19 | if(pfnCreateTransaction != NULL) 20 | { 21 | // CreateTransaction is allowed when no transaction is created 22 | bEnable = (BOOL)(IsHandleInvalid(pData->hTransaction)); 23 | EnableDlgItems(hDlg, bEnable, IDC_CREATE_TRANSACTION, IDC_CREATE_TRANSACTION_HINT, 0); 24 | 25 | // CommitTransaction and RollbackTransaction are allowed when a transaction is assigned 26 | bEnable = (BOOL)(IsHandleValid(pData->hTransaction)); 27 | EnableDlgItems(hDlg, bEnable, IDC_COMMIT_TRANSACTION, IDC_COMMIT_TRANSACTION_HINT, 28 | IDC_ROLLBACK_TRANSACTION, IDC_ROLLBACK_TRANSACTION_HINT, 29 | 0); 30 | 31 | SetResultInfo(hDlg, RSI_LAST_ERROR | RSI_HANDLE, dwErrCode, pData->hTransaction); 32 | } 33 | else 34 | { 35 | EnableDlgItems(hDlg, FALSE, IDC_CREATE_TRANSACTION, IDC_CREATE_TRANSACTION_HINT, 36 | IDC_COMMIT_TRANSACTION, IDC_COMMIT_TRANSACTION_HINT, 37 | IDC_ROLLBACK_TRANSACTION, IDC_ROLLBACK_TRANSACTION_HINT, 38 | IDC_CLOSE_HANDLE, IDC_CLOSE_HANDLE_HINT, 39 | 0); 40 | } 41 | } 42 | 43 | //----------------------------------------------------------------------------- 44 | // Message handlers 45 | 46 | static TAnchors * pAnchors = NULL; 47 | 48 | static int OnInitDialog(HWND hDlg, LPARAM lParam) 49 | { 50 | PROPSHEETPAGE * pPage = (PROPSHEETPAGE *)lParam; 51 | TFileTestData * pData = (TFileTestData *)pPage->lParam; 52 | 53 | // Load the transaction APIs, as they are only supported in Vista and later 54 | SetDialogData(hDlg, pPage->lParam); 55 | pData->hTransaction = INVALID_HANDLE_VALUE; 56 | 57 | // Configure dialog resizing 58 | if(pData->bEnableResizing) 59 | { 60 | pAnchors = new TAnchors(hDlg); 61 | pAnchors->AddAnchor(hDlg, IDC_MAIN_FRAME, akLeft | akTop | akRight); 62 | pAnchors->AddAnchor(hDlg, IDC_CREATE_TRANSACTION, akLeft | akTop | akRight); 63 | pAnchors->AddAnchor(hDlg, IDC_CREATE_TRANSACTION_HINT, akLeft | akTop | akRight); 64 | pAnchors->AddAnchor(hDlg, IDC_COMMIT_TRANSACTION, akLeft | akTop | akRight); 65 | pAnchors->AddAnchor(hDlg, IDC_COMMIT_TRANSACTION_HINT, akLeft | akTop | akRight); 66 | pAnchors->AddAnchor(hDlg, IDC_ROLLBACK_TRANSACTION, akLeft | akTop | akRight); 67 | pAnchors->AddAnchor(hDlg, IDC_ROLLBACK_TRANSACTION_HINT, akLeft | akTop | akRight); 68 | pAnchors->AddAnchor(hDlg, IDC_CLOSE_HANDLE, akLeft | akTop | akRight); 69 | pAnchors->AddAnchor(hDlg, IDC_CLOSE_HANDLE_HINT, akLeft | akTop | akRight); 70 | pAnchors->AddAnchor(hDlg, IDC_RESULT_FRAME, akLeft | akRight | akBottom); 71 | pAnchors->AddAnchor(hDlg, IDC_ERROR_CODE_TITLE, akLeft | akBottom); 72 | pAnchors->AddAnchor(hDlg, IDC_ERROR_CODE, akLeft | akRight | akBottom); 73 | pAnchors->AddAnchor(hDlg, IDC_HANDLE_TITLE, akLeft | akBottom); 74 | pAnchors->AddAnchor(hDlg, IDC_HANDLE, akLeft | akRight | akBottom); 75 | } 76 | 77 | return TRUE; 78 | } 79 | 80 | static int OnCreateTransaction(HWND hDlg) 81 | { 82 | TFileTestData * pData = GetDialogData(hDlg); 83 | int dwErrCode = ERROR_SUCCESS; 84 | 85 | // Create new transaction 86 | if(dwErrCode == ERROR_SUCCESS && pfnCreateTransaction != NULL) 87 | { 88 | pData->hTransaction = pfnCreateTransaction(NULL, 89 | NULL, 90 | 0, 91 | 0, 92 | 0, 93 | NULL, 94 | _T("Transaction for FileTest")); 95 | if(IsHandleValid(pData->hTransaction)) 96 | pData->bTransactionActive = TRUE; 97 | else 98 | dwErrCode = GetLastError(); 99 | } 100 | 101 | UpdateDialog(hDlg, dwErrCode); 102 | return TRUE; 103 | } 104 | 105 | static int OnCommitTransaction(HWND hDlg) 106 | { 107 | TFileTestData * pData = GetDialogData(hDlg); 108 | DWORD dwErrCode = ERROR_SUCCESS; 109 | 110 | // Commit the transaction 111 | if(IsHandleValid(pData->hTransaction)) 112 | { 113 | if(!pfnCommitTransaction(pData->hTransaction)) 114 | dwErrCode = GetLastError(); 115 | 116 | pData->bTransactionActive = FALSE; 117 | pData->bUseTransaction = FALSE; 118 | UpdateDialog(hDlg, dwErrCode); 119 | } 120 | return TRUE; 121 | } 122 | 123 | static int OnRollbackTransaction(HWND hDlg) 124 | { 125 | TFileTestData * pData = GetDialogData(hDlg); 126 | DWORD dwErrCode = ERROR_SUCCESS; 127 | 128 | // Rollback the transaction 129 | if(IsHandleValid(pData->hTransaction)) 130 | { 131 | if(!pfnRollbackTransaction(pData->hTransaction)) 132 | dwErrCode = GetLastError(); 133 | 134 | pData->bTransactionActive = FALSE; 135 | pData->bUseTransaction = FALSE; 136 | UpdateDialog(hDlg, dwErrCode); 137 | } 138 | return TRUE; 139 | } 140 | 141 | static int OnCloseTransaction(HWND hDlg) 142 | { 143 | TFileTestData * pData = GetDialogData(hDlg); 144 | DWORD dwErrCode = ERROR_SUCCESS; 145 | 146 | // Assign the transaction to the current thread 147 | if(IsHandleValid(pData->hTransaction)) 148 | CloseHandle(pData->hTransaction); 149 | 150 | // Clear information about transaction 151 | pData->hTransaction = INVALID_HANDLE_VALUE; 152 | UpdateDialog(hDlg, dwErrCode); 153 | return TRUE; 154 | } 155 | 156 | static int OnCommand(HWND hDlg, UINT nNotify, UINT nIDCtrl) 157 | { 158 | if(nNotify == BN_CLICKED) 159 | { 160 | switch(nIDCtrl) 161 | { 162 | case IDC_CREATE_TRANSACTION: 163 | OnCreateTransaction(hDlg); 164 | return TRUE; 165 | 166 | case IDC_COMMIT_TRANSACTION: 167 | OnCommitTransaction(hDlg); 168 | return TRUE; 169 | 170 | case IDC_ROLLBACK_TRANSACTION: 171 | OnRollbackTransaction(hDlg); 172 | return TRUE; 173 | 174 | case IDC_CLOSE_HANDLE: 175 | OnCloseTransaction(hDlg); 176 | return TRUE; 177 | } 178 | } 179 | 180 | return FALSE; 181 | } 182 | 183 | //----------------------------------------------------------------------------- 184 | // Public page callback 185 | 186 | INT_PTR CALLBACK PageProc00(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 187 | { 188 | switch(uMsg) 189 | { 190 | case WM_INITDIALOG: 191 | return OnInitDialog(hDlg, lParam); 192 | 193 | case WM_SIZE: 194 | return pAnchors->OnMessage(uMsg, wParam, lParam); 195 | 196 | case WM_COMMAND: 197 | return OnCommand(hDlg, HIWORD(wParam), LOWORD(wParam)); 198 | 199 | case WM_DESTROY: 200 | if(pAnchors != NULL) 201 | delete pAnchors; 202 | pAnchors = NULL; 203 | return FALSE; 204 | } 205 | return FALSE; 206 | } 207 | -------------------------------------------------------------------------------- /doc/History.txt: -------------------------------------------------------------------------------- 1 | 2 | FileTest history 3 | ================ 4 | 5 | Version 2.6.1.637 6 | 7 | - ACE editor now supports new ACEs 8 | 9 | Version 2.6.1.601 10 | 11 | - Fixed crash when querying image name on System PID (4) 12 | - Improved flag dialogs 13 | 14 | Version 2.6.1.563 15 | 16 | - DebugBreak() replaced by the inline version 17 | 18 | Version 2.6.1.561 19 | 20 | - Added support of Ctrl+C into all tree views. 21 | 22 | Version 2.6.1.559 23 | 24 | - Added support for IO_REPARSE_TAG_APPEXECLINK 25 | 26 | Version 2.6.1.556 27 | 28 | - Added support for CreateHardLink 29 | - Deleting directory tree improved: Now uses Win10's FILE_DISPOSITION_INFORMATION_EX if necessary. 30 | 31 | Version 2.6.1.555 32 | 33 | - Added new FILE_INFORMATION_CLASSes for newer Win10 34 | - The user can now enter some structure flags by flag (i.e. FILE_ATTRIBUTE_READONLY) 35 | 36 | Version 2.6.1.553 37 | 38 | - The user can now specify a search mask for NtQueryDirectoryFile 39 | - DPI awareness 40 | 41 | Version 2.6.1.546 42 | 43 | - Double-click on stream name creates proper full path 44 | 45 | Version 2.6.1.529 46 | 47 | - Improved editor of the security descriptor 48 | - Improved editor of the reparse point 49 | 50 | Version 2.6.0.524 51 | 52 | - Fixed dialog cleanup 53 | 54 | Version 2.6.0.523 55 | 56 | - Byte counts are space separated in copy dialog 57 | - Date/Time fields can now accept 64-bit hexa value without separators 58 | 59 | Version 2.6.0.520 60 | 61 | - Improved the "Copy File" command. Now can copy volumes, too. 62 | - Fixed invalid determining whether running under restricted token. 63 | - Sources backported to VS 2005 64 | 65 | Version 2.6.0.506 66 | 67 | - Improved the "Delete Dir" command. Now can delete folders even with reparse points. 68 | - Improved work with reparse points 69 | 70 | Version 2.6.0.503 71 | 72 | - Changed old unsafe str* and sprintf functions to StringCch* versions 73 | - Fixed importing streams when there is no EAs 74 | 75 | Version 2.6.0.481 76 | 77 | - Fixed missing entries in combobox in "Links" page 78 | 79 | Version 2.6.0.474 80 | 81 | - Added support for oplocks break acknowledgement 82 | - Asynchronous operations that returned pending status no longer block FileTest's UI 83 | 84 | Version 2.6.0.468 85 | 86 | - Added support for oplocks 87 | - Added context menu to NtCreate page for quick selection of create options 88 | - Added "About" dialog 89 | - Added generic support for asynchronous, long-to-complete requests 90 | 91 | Version 2.5.0.466 92 | 93 | - Fixed displaying on low screen resolutions 94 | - Fixed background color of the "Relative File" link button on the "NtCreate" page 95 | 96 | Version 2.5.0.458 97 | 98 | - Bugfixes in the data editor 99 | 100 | Version 2.5.0.455 101 | 102 | - Data viewer is now editable (Nt)WriteFile 103 | - Added tab page for file mappings 104 | - Possibility to edit mapped data 105 | - Combo boxes with info class names are now searchable by typing text into the edit field 106 | - Several read-only fields are now editable. ShareAccess = 0xDEADBABE? No problem. 107 | 108 | Version 2.1.0.441 109 | 110 | - Added custom data viewer for (Nt)WriteFile 111 | 112 | Version 2.1.0.417 113 | 114 | - Improved auto-conversion between Win32 and NT names 115 | 116 | Version 1.9.0.214 117 | 118 | - Fixed showing data loaded from file 119 | - When user makes a mistake in entering date/time, list of supported date/time formats is displayed 120 | 121 | Version 1.9.0.208 122 | 123 | - Support for NtReadFile and NtWriteFile 124 | - Support for asynchronour file read and write 125 | - Support for Symbolic Links 126 | - Support for Hardlinks 127 | - Support for reparse points 128 | - Data view after ReadFile 129 | - WriteFile can reuse data loaded by ReadFile, even if the data are from another file 130 | 131 | Version 1.9.0.188 132 | 133 | - Removed most of the error popups, operation result is now shown 134 | in a non-invasive way in the bottom part of tabs. 135 | - Date/Time is now displayed and possible to enter in human-readable form 136 | - Fixed a few bugs from prev release 137 | - Unified look of results on tabs 138 | 139 | Version 1.9.0.186 140 | 141 | - Added tab page for file security 142 | - Added dialog for setting/clearing FileTest's privileges and integrity level 143 | - FileTest dialog is now resizeable 144 | - Subdialogs are now centered to parent, rather than to screen 145 | 146 | Version 1.8.2.171 147 | 148 | - Possibility to turn file virtualization on/on on Vista and under restricted accounts 149 | 150 | Version 1.8.2.170 151 | 152 | - Possibility to specify extended attributes on call to NtCreateFile 153 | 154 | Version 1.8.1.168 155 | 156 | - Possibility to stop on breakpoint right before call 157 | to CreateFile/CreateFileTransacted/NtCreateFile 158 | 159 | Version 1.8.1.166 160 | 161 | - Improved file mapping functions 162 | 163 | Version 1.8.0.164 164 | 165 | - Added support for FileLinkInformation 166 | - Added support for Vista file info classes 167 | - Added support for NtQueryVolumeInformationFile 168 | - Added support for NtSetVolumeInformationFile 169 | 170 | Version 1.7.0.157 171 | 172 | - Added support for FileHardLinkInformation 173 | 174 | Version 1.7.0.153 175 | 176 | - When mapping a file, it is now possible to control access to the pages 177 | 178 | Version 1.7.0.150 179 | 180 | - Fixed issue with file mapping when starting offset was nonzero 181 | - Spin controls in "File operations" tab work now :-) 182 | 183 | Version 1.7.0.148 184 | 185 | - Support for FileRenameInformation 186 | 187 | Version 1.7.0.145 188 | 189 | - In Vista, FileTest shows if running under elevated or restricted user. 190 | 191 | Version 1.7.0.137 192 | 193 | - Changed "Directory" in page for NtCreateFile to "Relative File" 194 | 195 | Version 1.7.0.128 196 | 197 | - Support for CreateFileTransacted and NtCreateFile under active transaction 198 | 199 | Version 1.7.0.94 200 | 201 | - Status/Last error controls are now edit boxes instead or static texts 202 | 203 | Version 1.7.0.92 204 | 205 | - Added support for transactions in Vista 206 | - Browse for file dialog now accepts not existing files 207 | 208 | 209 | Version 1.5.0.78 210 | 211 | - Full support for NtSetInformationFile and NtQueryDirectoryFile 212 | - Command line arguments have been changed to [file1] [file2] [dir] 213 | - Default flags for NtCreateFile have been changed to be able 214 | to call ReadFile/WriteFile on the opened file 215 | 216 | Version 1.5.0.72 217 | 218 | - Added the "SetInfo" page, supporting "NtSetInformationFile". 219 | (Only FILE_DISPOSITION_INFORMATION supported yet, more to come) 220 | 221 | Version 1.4.0.71 222 | 223 | - Added the "FlushFileBuffers" support. Thank you, Rod Widdowson ! 224 | 225 | Version 1.2.0.69 226 | 227 | - Added Extended Attributes editor 228 | 229 | Version 1.2.0.66 230 | 231 | - FileTest no longer statically links Ntdll.lib 232 | - Support for AMD64 target 233 | - If a not-existing file has been deleted, FileTest reported no error 234 | 235 | Version 1.1.1.37 236 | 237 | - Removed the check if a handle is a Win32 or not. 238 | - Changed the font to "MS Shell Dlg", so now the GUI shows correct UNICODE 239 | file names. 240 | - Added GetFileAttributes 241 | - The "File operations" contains "Use CopyFile() API" instead of "Don't use CopyFile" 242 | - Added the "NtQueryInfo" page with possibility to call NtQueryInformationFile 243 | 244 | 245 | Version 1.1.1.24 246 | 247 | - Completed open flags for the CreateFile "Flags & attributes" 248 | - Reworked the DlgFlags dialog 249 | 250 | 251 | Version 1.1.1.20 252 | 253 | - Added possibility to get file name using NtQueryInformationFile 254 | - Added possibility to set the file size using Win32 API 255 | - Added possibility to get file ID using native API 256 | - Added possibility to open the file by ID using NtCreateFile 257 | - Various create parameters are now better carried between 258 | CreateFile and NtCreateFile pages when changed 259 | - Fixed bug when converting lowercase hexa numbers to Int32 or Int64 260 | - The MSVC7 solution configuration has been updated 261 | - Several minor changes, like added version info, removed 262 | some commented code junk etc. 263 | -------------------------------------------------------------------------------- /TAceHelper.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* TAceHelper.h Copyright (c) Ladislav Zezula 2016 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Interface for the ACE helper class */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 26.03.16 1.00 Lad The first version of TAceHelper.h */ 9 | /*****************************************************************************/ 10 | 11 | #ifndef __TACEHELPER_H__ 12 | #define __TACEHELPER_H__ 13 | 14 | //----------------------------------------------------------------------------- 15 | // Definitions 16 | 17 | // Flags for fields included 18 | #define ACE_FIELD_HTYPE 0x00000001 // ACE_HEADER::AceType (always included) 19 | #define ACE_FIELD_HFLAGS 0x00000002 // ACE_HEADER::AceFlags for all ACEs except SYSTEM_ACCESS_FILTER_ACE 20 | #define ACE_FIELD_HFLAGS2 0x00000004 // ACE_HEADER::AceFlags for SYSTEM_ACCESS_FILTER_ACE 21 | #define ACE_FIELD_HSIZE 0x00000008 // ACE_HEADER::AceSize (always included) 22 | #define ACE_FIELD_ACCESS_MASK 0x00000010 // ACE::Mask 23 | #define ACE_FIELD_ADS_ACCESS_MASK 0x00000020 // ACE::Mask for ADS ACEs 24 | #define ACE_FIELD_MANDATORY_MASK 0x00000040 // SYSTEM_MANDATORY_LABEL_ACE::Mask 25 | #define ACE_FIELD_GUID_FLAGS 0x00000080 // Flags for ObjectType and InheritedObjectType 26 | #define ACE_FIELD_COMPOUND_TYPE 0x00000100 // COMPOUND_ACCESS_ALLOWED_ACE::CompoundAceType 27 | #define ACE_FIELD_COMPOUND_RSVD 0x00000200 // COMPOUND_ACCESS_ALLOWED_ACE::Reserved 28 | #define ACE_FIELD_OBJECT_TYPE1 0x00000400 // XXX_YYY_OBJECT_ACE::ObjectType 29 | #define ACE_FIELD_OBJECT_TYPE2 0x00000800 // XXX_YYY_OBJECT_ACE::InheritedObjectType 30 | #define ACE_FIELD_SID 0x00001000 // ACE::SidStart contains a (server) SID 31 | #define ACE_FIELD_MANDATORY_SID 0x00002000 // ACE::SidStart contains a mandatory label SID 32 | #define ACE_FIELD_POLICY_SID 0x00004000 // ACE::SidStart contains a Policy ID SID 33 | #define ACE_FIELD_TRUST_SID 0x00008000 // ACE::SidStart contains a trust SID 34 | #define ACE_FIELD_CLIENT_SID 0x00010000 // ACE::SidStart contains a client SID 35 | #define ACE_FIELD_CSA_V1 0x00020000 // Contains the CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 structure 36 | #define ACE_FIELD_CONDITION 0x00040000 // Contains the ACE condition 37 | 38 | #define ACE_FIELD_PRIMARY_SID_MASK (ACE_FIELD_SID|ACE_FIELD_MANDATORY_SID|ACE_FIELD_POLICY_SID|ACE_FIELD_TRUST_SID) 39 | 40 | // Multi flags that are always together 41 | #define ACE_FIELD_HEADER (ACE_FIELD_HTYPE|ACE_FIELD_HFLAGS|ACE_FIELD_HSIZE) 42 | 43 | // Flags for free fields 44 | #define ACE_HELPER_NEED_FREE_SID0 0x00000001 // The ACE_HELPER::Sid[0] needs to be freed using Sid_Free 45 | #define ACE_HELPER_NEED_FREE_SID1 0x00000002 // The ACE_HELPER::Sid[1] needs to be freed using Sid_Free 46 | 47 | // Unknown ACE layout (ACCESS_ALLOWED_COMPOUND_ACE) 48 | #define ACE_LAYOUT_UNKNOWN (0) 49 | 50 | // Flag combinations for {Header-Mask-SidStart} ACEs 51 | #define ACE_LAYOUT_SIMPLE (ACE_FIELD_HEADER | ACE_FIELD_ACCESS_MASK | ACE_FIELD_SID) 52 | 53 | // 54 | #define ACE_LAYOUT_COMPOUND (ACE_FIELD_HEADER | ACE_FIELD_ACCESS_MASK | ACE_FIELD_COMPOUND_TYPE | ACE_FIELD_COMPOUND_RSVD | ACE_FIELD_SID | ACE_FIELD_CLIENT_SID) 55 | 56 | // ACE layout for {Header-AdsMask-Flags-ObjectType-InheritedObjectType-SidStart} 57 | #define ACE_LAYOUT_OBJECT (ACE_FIELD_HEADER | ACE_FIELD_ADS_ACCESS_MASK | ACE_FIELD_GUID_FLAGS | ACE_FIELD_OBJECT_TYPE1 | ACE_FIELD_OBJECT_TYPE2 | ACE_FIELD_SID) 58 | 59 | // Flag combinations for {Header-Mask-SidStart-Condition} ACEs 60 | #define ACE_LAYOUT_CONDITION (ACE_FIELD_HEADER | ACE_FIELD_ACCESS_MASK | ACE_FIELD_SID | ACE_FIELD_CONDITION) 61 | 62 | // Flag combinations for {Header-Mask-Flags-ObjectType-InheritedObjectType-SidStart-Condition} ACEs 63 | #define ACE_LAYOUT_OBJECT_CONDITION (ACE_FIELD_HEADER | ACE_FIELD_ADS_ACCESS_MASK | ACE_FIELD_GUID_FLAGS | ACE_FIELD_OBJECT_TYPE1 | ACE_FIELD_OBJECT_TYPE2 | ACE_FIELD_SID | ACE_FIELD_CONDITION) 64 | 65 | // ACE Layout for SYSTEM_MANDATORY_LABEL_ACE_TYPE 66 | #define ACE_LAYOUT_MANDATORY (ACE_FIELD_HEADER | ACE_FIELD_MANDATORY_MASK | ACE_FIELD_MANDATORY_SID) 67 | 68 | // ACE layout for SYSTEM_RESOURCE_ATTRIBUTE_ACE 69 | #define ACE_LAYOUT_RESOURCE (ACE_FIELD_HEADER | ACE_FIELD_ACCESS_MASK | ACE_FIELD_SID | ACE_FIELD_CSA_V1) 70 | 71 | // ACE layout for SYSTEM_SCOPED_POLICY_ID_ACE_TYPE 72 | #define ACE_LAYOUT_POLICY_ID (ACE_FIELD_HEADER | ACE_FIELD_ACCESS_MASK | ACE_FIELD_POLICY_SID) 73 | 74 | // ACE layout for SYSTEM_PROCESS_TRUST_LABEL_ACE 75 | #define ACE_LAYOUT_TRUST_ID (ACE_FIELD_HEADER | ACE_FIELD_ACCESS_MASK | ACE_FIELD_TRUST_SID) 76 | 77 | // ACE layout for SYSTEM_ACCESS_FILTER_ACE 78 | #define ACE_LAYOUT_TRUST_ID_CONDITION (ACE_FIELD_HTYPE | ACE_FIELD_HFLAGS2 | ACE_FIELD_HSIZE | ACE_FIELD_ACCESS_MASK | ACE_FIELD_TRUST_SID | ACE_FIELD_CONDITION) 79 | 80 | // An invalid ACCESS_MASK 81 | #define INVALID_ACCESS_MASK 0xFFFFFFFF 82 | 83 | //----------------------------------------------------------------------------- 84 | // Common structure of an ACE with GUID flags 85 | 86 | typedef struct _ACE 87 | { 88 | ACE_HEADER Header; 89 | ACCESS_MASK Mask; 90 | DWORD Flags; 91 | // Followed by more fields, depending on the ACE type 92 | } ACE, *PACE; 93 | 94 | //----------------------------------------------------------------------------- 95 | // External variables 96 | 97 | extern const BYTE SidEveryone[0x0C]; 98 | extern const BYTE SidLocUsers[0x10]; 99 | extern const BYTE SidLocAdmins[0x10]; 100 | extern const BYTE SidLabelMedium[0x0C]; 101 | extern const BYTE SidSystemAce17[0x0C]; 102 | extern const BYTE SidSystemAce19[0x10]; 103 | 104 | //----------------------------------------------------------------------------- 105 | // Interface for the ACE_HELPER class 106 | 107 | struct ACE_HELPER 108 | { 109 | // Constructors and destructors 110 | ACE_HELPER(DWORD dwAceType = ACCESS_ALLOWED_ACE_TYPE, PSID pSid = NULL); 111 | ACE_HELPER(DWORD dwAceType, ACCESS_MASK AccessMask, PSID pSid = NULL); 112 | ACE_HELPER(const ACE_CSA_HELPER & CsaHelper, PSID pSid = NULL); 113 | ~ACE_HELPER(); 114 | 115 | void Init(DWORD dwAceType, ACCESS_MASK AccessMask, PSID pSid1, PSID pSid2); 116 | 117 | bool SetAceType(DWORD dwAceType); // Sets a new ACE type 118 | bool SetAce(PACE_HEADER pAceHeader); // Stores an ACE 119 | PSID SetSid(LPCVOID lpSid, size_t nSidIndex); // Stores a SID that needs to be freed 120 | bool SetResource(LPCVOID lpAttrRel, size_t cbAttrRel); 121 | bool SetResource(const ACE_CSA_HELPER & CsaHelper); 122 | bool SetCondition(LPCVOID lpAttrRel, size_t cbAttrRel); 123 | 124 | bool SetDummyResource(); 125 | 126 | PACE_HEADER Export(LPBYTE pbBuffer, size_t cbBuffer); 127 | PACE_HEADER AddToAcl(PACL pAcl); 128 | 129 | LPBYTE PutAceValue(LPBYTE PtrAclData, LPBYTE PtrAclEnd, PVOID PtrValue, DWORD dwLayoutMask, DWORD ValueSize); 130 | LPBYTE PutAceValueSid(LPBYTE PtrAclData, LPBYTE PtrAclEnd, PSID pSourceSid); 131 | LPBYTE PutAceValueBinary(LPBYTE PtrAclData, LPBYTE PtrAclEnd, LPVOID lpData, size_t cbData); 132 | 133 | LPBYTE CaptureExtraStructure(LPBYTE pbPtr, LPBYTE pbEnd, size_t * pcbMoveBy = NULL); 134 | 135 | // Helper for creating a SID belonging to a certain ACE type 136 | static PSID GetDefaultSid(DWORD dwAceType = ACCESS_ALLOWED_ACE_TYPE, DWORD dwAceFlags = 0); 137 | 138 | // Field mask for fields that are valid 139 | DWORD AceLayout; // See ACE_FIELD_XXX 140 | 141 | // Variables 142 | BYTE AceType; // ACE_HEADER::AceType 143 | BYTE AceFlags; // ACE_HEADER::AceFlags 144 | WORD AceSize; // ACE_HEADER::AceSize 145 | ACCESS_MASK Mask; // Mask (Allowed Ace, Denied Ace, Audit Ace, Alarm Ace, Mandatory Label Ace) 146 | DWORD Flags; 147 | USHORT CompoundAceType; 148 | USHORT CompoundReserved; 149 | GUID ObjectType; 150 | GUID InheritedObjectType; 151 | PSID Sid[2]; // Pointer to the first SID (need to be freed using FreeSid) 152 | LPBYTE Condition; // ACE condition 153 | size_t ConditionLength; // Length of the ACE condition 154 | LPBYTE AttrRel; // Relative security attribute 155 | size_t AttrRelLength; // Length of the ACE condition 156 | }; 157 | 158 | #endif // __TACEHELPER_H__ 159 | -------------------------------------------------------------------------------- /TestCode.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* Page09Security.cpp Copyright (c) Ladislav Zezula 2005 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Description : */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 15.08.05 1.00 Lad The first version of Page09Security.cpp */ 9 | /*****************************************************************************/ 10 | 11 | #include "FileTest.h" 12 | #include "resource.h" 13 | 14 | #ifdef __TEST_MODE__ 15 | 16 | /* 17 | static PSID GetUserSid(LPCTSTR szUserName, LPDWORD pcbSid) 18 | { 19 | SID_NAME_USE SidNameUse; 20 | PSID pSid = NULL; 21 | DWORD cbSid = 0; 22 | DWORD cbDomain = 128; 23 | TCHAR szDomain[128]; 24 | 25 | LookupAccountName(NULL, szUserName, pSid, &cbSid, szDomain, &cbDomain, &SidNameUse); 26 | if(cbSid != 0) 27 | { 28 | if((pSid = LocalAlloc(LPTR, cbSid)) != NULL) 29 | { 30 | if(LookupAccountName(NULL, szUserName, pSid, &cbSid, szDomain, &cbDomain, &SidNameUse)) 31 | { 32 | pcbSid[0] = cbSid; 33 | return pSid; 34 | } 35 | LocalFree(pSid); 36 | } 37 | } 38 | return NULL; 39 | } 40 | */ 41 | 42 | PACL CreateEmptyDacl() 43 | { 44 | PACL pAcl; 45 | 46 | if((pAcl = (PACL)LocalAlloc(LPTR, sizeof(ACL))) != NULL) 47 | { 48 | if(RtlCreateAcl(pAcl, sizeof(ACL), ACL_REVISION_DS) != STATUS_SUCCESS) 49 | { 50 | LocalFree(pAcl); 51 | pAcl = NULL; 52 | } 53 | } 54 | return pAcl; 55 | } 56 | 57 | PACL CreateCustomAcl() 58 | { 59 | PACL pAcl; 60 | NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; 61 | 62 | // Allocate space for ACL 63 | if((pAcl = (PACL)LocalAlloc(LPTR, MAX_ACL_LENGTH)) != NULL) 64 | { 65 | if((Status = RtlCreateAcl(pAcl, MAX_ACL_LENGTH, ACL_REVISION_DS)) == STATUS_SUCCESS) 66 | { 67 | PACE_HEADER pAceHeader; 68 | WORD cbAclSize = sizeof(ACL); 69 | 70 | if((pAceHeader = ACE_HELPER(ACCESS_ALLOWED_ACE_TYPE).AddToAcl(pAcl)) != NULL) 71 | cbAclSize = cbAclSize + pAceHeader->AceSize; 72 | /* 73 | if((pAceHeader = ACE_HELPER(ACCESS_DENIED_ACE_TYPE, FILE_EXECUTE).AddToAcl(pAcl)) != NULL) 74 | cbAclSize = cbAclSize + pAceHeader->AceSize; 75 | 76 | if((pAceHeader = ACE_HELPER(SYSTEM_AUDIT_ACE_TYPE, FILE_EXECUTE).AddToAcl(pAcl)) != NULL) 77 | cbAclSize = cbAclSize + pAceHeader->AceSize; 78 | 79 | if((pAceHeader = ACE_HELPER(SYSTEM_ALARM_ACE_TYPE, FILE_EXECUTE).AddToAcl(pAcl)) != NULL) 80 | cbAclSize = cbAclSize + pAceHeader->AceSize; 81 | 82 | if((pAceHeader = ACE_HELPER(ACCESS_ALLOWED_COMPOUND_ACE_TYPE).AddToAcl(pAcl)) != NULL) 83 | cbAclSize = cbAclSize + pAceHeader->AceSize; 84 | 85 | if((pAceHeader = ACE_HELPER(ACCESS_ALLOWED_OBJECT_ACE_TYPE).AddToAcl(pAcl)) != NULL) 86 | cbAclSize = cbAclSize + pAceHeader->AceSize; 87 | 88 | if((pAceHeader = ACE_HELPER(ACCESS_DENIED_OBJECT_ACE_TYPE, FILE_EXECUTE).AddToAcl(pAcl)) != NULL) 89 | cbAclSize = cbAclSize + pAceHeader->AceSize; 90 | 91 | if((pAceHeader = ACE_HELPER(SYSTEM_AUDIT_OBJECT_ACE_TYPE).AddToAcl(pAcl)) != NULL) 92 | cbAclSize = cbAclSize + pAceHeader->AceSize; 93 | 94 | if((pAceHeader = ACE_HELPER(SYSTEM_ALARM_OBJECT_ACE_TYPE).AddToAcl(pAcl)) != NULL) 95 | cbAclSize = cbAclSize + pAceHeader->AceSize; 96 | 97 | if((pAceHeader = ACE_HELPER(ACCESS_ALLOWED_CALLBACK_ACE_TYPE).AddToAcl(pAcl)) != NULL) 98 | cbAclSize = cbAclSize + pAceHeader->AceSize; 99 | 100 | if((pAceHeader = ACE_HELPER(ACCESS_DENIED_CALLBACK_ACE_TYPE, FILE_EXECUTE).AddToAcl(pAcl)) != NULL) 101 | cbAclSize = cbAclSize + pAceHeader->AceSize; 102 | 103 | if((pAceHeader = ACE_HELPER(ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE).AddToAcl(pAcl)) != NULL) 104 | cbAclSize = cbAclSize + pAceHeader->AceSize; 105 | 106 | if((pAceHeader = ACE_HELPER(ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE, FILE_EXECUTE).AddToAcl(pAcl)) != NULL) 107 | cbAclSize = cbAclSize + pAceHeader->AceSize; 108 | 109 | if((pAceHeader = ACE_HELPER(SYSTEM_AUDIT_CALLBACK_ACE_TYPE).AddToAcl(pAcl)) != NULL) 110 | cbAclSize = cbAclSize + pAceHeader->AceSize; 111 | 112 | if((pAceHeader = ACE_HELPER(SYSTEM_ALARM_CALLBACK_ACE_TYPE).AddToAcl(pAcl)) != NULL) 113 | cbAclSize = cbAclSize + pAceHeader->AceSize; 114 | 115 | if((pAceHeader = ACE_HELPER(SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE).AddToAcl(pAcl)) != NULL) 116 | cbAclSize = cbAclSize + pAceHeader->AceSize; 117 | 118 | if((pAceHeader = ACE_HELPER(SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE).AddToAcl(pAcl)) != NULL) 119 | cbAclSize = cbAclSize + pAceHeader->AceSize; 120 | 121 | if((pAceHeader = ACE_HELPER(SYSTEM_MANDATORY_LABEL_ACE_TYPE).AddToAcl(pAcl)) != NULL) 122 | cbAclSize = cbAclSize + pAceHeader->AceSize; 123 | 124 | if((pAceHeader = ACE_HELPER(ACE_CSA_HELPER(L"RESOURCE_ITEM_I64_VALUES", CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64)).AddToAcl(pAcl)) != NULL) 125 | cbAclSize = cbAclSize + pAceHeader->AceSize; 126 | 127 | if((pAceHeader = ACE_HELPER(ACE_CSA_HELPER(L"RESOURCE_ITEM_U64_VALUES", CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64)).AddToAcl(pAcl)) != NULL) 128 | cbAclSize = cbAclSize + pAceHeader->AceSize; 129 | */ 130 | if((pAceHeader = ACE_HELPER(ACE_CSA_HELPER(L"RESOURCE_ITEM_STRINGS", CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING, 5)).AddToAcl(pAcl)) != NULL) 131 | cbAclSize = cbAclSize + pAceHeader->AceSize; 132 | /* 133 | if((pAceHeader = ACE_HELPER(ACE_CSA_HELPER(L"RESOURCE_ITEM_SIDS", CLAIM_SECURITY_ATTRIBUTE_TYPE_SID)).AddToAcl(pAcl)) != NULL) 134 | cbAclSize = cbAclSize + pAceHeader->AceSize; 135 | 136 | if((pAceHeader = ACE_HELPER(ACE_CSA_HELPER(L"RESOURCE_ITEM_BOOLEANS", CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN, 4)).AddToAcl(pAcl)) != NULL) 137 | cbAclSize = cbAclSize + pAceHeader->AceSize; 138 | 139 | if((pAceHeader = ACE_HELPER(ACE_CSA_HELPER(L"RESOURCE_ITEM_OCTET_STRINGS", CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING)).AddToAcl(pAcl)) != NULL) 140 | cbAclSize = cbAclSize + pAceHeader->AceSize; 141 | 142 | if((pAceHeader = ACE_HELPER(SYSTEM_SCOPED_POLICY_ID_ACE_TYPE).AddToAcl(pAcl)) != NULL) 143 | cbAclSize = cbAclSize + pAceHeader->AceSize; 144 | 145 | if((pAceHeader = ACE_HELPER(SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE).AddToAcl(pAcl)) != NULL) 146 | cbAclSize = cbAclSize + pAceHeader->AceSize; 147 | 148 | if((pAceHeader = ACE_HELPER(SYSTEM_ACCESS_FILTER_ACE_TYPE).AddToAcl(pAcl)) != NULL) 149 | cbAclSize = cbAclSize + pAceHeader->AceSize; 150 | */ 151 | pAcl->AclSize = cbAclSize; 152 | } 153 | } 154 | return pAcl; 155 | } 156 | 157 | static DWORD SetCustomSecurityDescriptor(HANDLE hObject) 158 | { 159 | SECURITY_DESCRIPTOR sd; 160 | NTSTATUS Status = STATUS_SUCCESS; 161 | PACL pAcl = NULL; 162 | 163 | UNREFERENCED_PARAMETER(hObject); 164 | 165 | // Initialize the blank security descriptor 166 | Status = RtlCreateSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); 167 | if(NT_SUCCESS(Status)) 168 | { 169 | // Create custom ACL 170 | if((pAcl = CreateCustomAcl()) != NULL) 171 | { 172 | // Set the ACL to the security descriptor 173 | Status = RtlSetDaclSecurityDescriptor(&sd, TRUE, pAcl, FALSE); 174 | if(NT_SUCCESS(Status)) 175 | { 176 | // Set the security descriptor to the object 177 | Status = NtSetSecurityObject(hObject, DACL_SECURITY_INFORMATION, &sd); 178 | } 179 | LocalFree(pAcl); 180 | } 181 | else 182 | { 183 | Status = STATUS_NO_MEMORY; 184 | } 185 | } 186 | return Status; 187 | } 188 | 189 | void SetCustomSecurityDescriptor(LPCTSTR szPath) 190 | { 191 | HANDLE hFolder; 192 | 193 | // Make sure that the folder exists 194 | ForcePathExist(szPath, TRUE); 195 | 196 | // Open the folder and set security descriptor 197 | hFolder = CreateFile(szPath, READ_CONTROL | WRITE_DAC | WRITE_OWNER, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); 198 | if(hFolder != INVALID_HANDLE_VALUE) 199 | { 200 | SetCustomSecurityDescriptor(hFolder); 201 | CloseHandle(hFolder); 202 | } 203 | } 204 | 205 | void DebugCode_SecurityDescriptor(LPCTSTR /* szPath */) 206 | { 207 | //SetCustomSecurityDescriptor(_T("c:\\VMWARE\\TestValidAcl")); 208 | } 209 | #endif 210 | 211 | -------------------------------------------------------------------------------- /ReparseDataHsm.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* ReparseDataHsm.cpp Copyright (c) Ladislav Zezula 2018 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Description: Implementation of HSM reparse data functions */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 18.03.14 1.00 Lad The first version of ReparseDataHsm.cpp */ 9 | /*****************************************************************************/ 10 | 11 | #include "FileTest.h" 12 | #include "ReparseDataHsm.h" 13 | #include "resource.h" 14 | 15 | //----------------------------------------------------------------------------- 16 | // Local functions 17 | 18 | static bool HsmpCheckElement(PHSM_DATA HsmData, ULONG ElementIndex) 19 | { 20 | PHSM_ELEMENT_INFO pElementInfo = &HsmData->ElementInfos[ElementIndex]; 21 | ULONG ElementCount = HsmData->NumberOfElements; 22 | 23 | if(pElementInfo->Type >= HSM_ELEMENT_TYPE_MAX) 24 | return false; 25 | if(pElementInfo->Offset != 0 && pElementInfo->Offset < HSM_MIN_DATA_SIZE(ElementCount)) 26 | return false; 27 | if(pElementInfo->Offset > HsmData->Length) 28 | return false; 29 | if(pElementInfo->Length > HsmData->Length) 30 | return false; 31 | if((pElementInfo->Offset + pElementInfo->Length) > HsmData->Length) 32 | return false; 33 | 34 | return true; 35 | } 36 | 37 | static NTSTATUS HsmValidateCommonData(PHSM_DATA HsmData, ULONG Magic, ULONG ElementCount, ULONG RemainingLength) 38 | { 39 | ULONG FirstElementOffset; 40 | ULONG NumberOfElements; 41 | ULONG CheckPhase = 0; 42 | 43 | // The remaining data must be at least HSM_FILE_DATA_MINSIZE bytes 44 | if(RemainingLength < HSM_MIN_DATA_SIZE(1)) 45 | return STATUS_CLOUD_FILE_METADATA_CORRUPT; 46 | CheckPhase = 1; 47 | 48 | if(HsmData->Magic != Magic) 49 | return STATUS_CLOUD_FILE_METADATA_CORRUPT; 50 | CheckPhase = 2; 51 | 52 | // Check CRC, if present 53 | if((HsmData->Flags & HSM_DATA_HAVE_CRC) && RtlComputeCrc32(0, &HsmData->Length, RemainingLength - 8) != HsmData->Crc32) 54 | return STATUS_CLOUD_FILE_METADATA_CORRUPT; 55 | CheckPhase = 3; 56 | 57 | // Check the remaining size 58 | if(HsmData->Length != RemainingLength) 59 | return STATUS_CLOUD_FILE_METADATA_CORRUPT; 60 | CheckPhase = 4; 61 | 62 | // Check the zero field 63 | if((NumberOfElements = HsmData->NumberOfElements) == 0) 64 | return STATUS_CLOUD_FILE_METADATA_CORRUPT; 65 | CheckPhase = 5; 66 | 67 | // Check the offset of the first element 68 | if((FirstElementOffset = HSM_MIN_DATA_SIZE(NumberOfElements)) > RemainingLength) 69 | return STATUS_CLOUD_FILE_METADATA_CORRUPT; 70 | CheckPhase = 0x10000; 71 | 72 | // Check the elements 73 | for (ULONG i = 0; i < min(NumberOfElements, ElementCount); i++) 74 | { 75 | if(!HsmpCheckElement(HsmData, i)) 76 | return STATUS_CLOUD_FILE_METADATA_CORRUPT; 77 | CheckPhase++; 78 | } 79 | 80 | CheckPhase = 0x20000; 81 | 82 | // Check element[0] (version?) 83 | if(NumberOfElements == 0 || RemainingLength < HSM_MIN_DATA_SIZE(1)) 84 | return STATUS_CLOUD_FILE_METADATA_CORRUPT; 85 | if(!HsmpCheckElement(HsmData, 0)) 86 | return STATUS_CLOUD_FILE_METADATA_CORRUPT; 87 | if(HsmData->ElementInfos[0].Type != HSM_ELEMENT_TYPE_BYTE || HsmData->ElementInfos[0].Length != sizeof(BYTE)) 88 | return STATUS_CLOUD_FILE_METADATA_CORRUPT; 89 | if(*HsmGetElementData(HsmData, 0) != 1) 90 | return STATUS_CLOUD_FILE_METADATA_CORRUPT; 91 | 92 | CheckPhase = 0x20001; 93 | return STATUS_SUCCESS; 94 | } 95 | 96 | //----------------------------------------------------------------------------- 97 | // Uncompresses the HSM reparse data buffer. Note that the buffer may be already 98 | // uncompressed (if the flag 0x8000 is not set). 99 | 100 | LPBYTE HsmGetElementData(PHSM_DATA HsmData, ULONG ElementIndex) 101 | { 102 | return ((LPBYTE)HsmData) + HsmData->ElementInfos[ElementIndex].Offset; 103 | } 104 | 105 | NTSTATUS HsmUncompressData(PREPARSE_DATA_BUFFER RawReparseData, ULONG RawReparseDataLength, PREPARSE_DATA_BUFFER * OutReparseData) 106 | { 107 | PREPARSE_DATA_BUFFER HsmReparseData = NULL; 108 | NTSTATUS Status = STATUS_SUCCESS; 109 | ULONG HsmReparseDataLength; 110 | ULONG UncompressedSize = 0; 111 | 112 | // Is the cloud buffer compressed? 113 | if(RawReparseData->HsmReparseBufferRaw.Flags & 0x8000) 114 | { 115 | HsmReparseDataLength = sizeof(ULONG) + sizeof(USHORT) + sizeof(USHORT) + RawReparseData->HsmReparseBufferRaw.Length; 116 | HsmReparseData = (PREPARSE_DATA_BUFFER)HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, HsmReparseDataLength); 117 | if(HsmReparseData != NULL) 118 | { 119 | // Copy the data that don't belong in the compressed area 120 | memcpy(HsmReparseData, RawReparseData, FIELD_OFFSET(REPARSE_DATA_BUFFER, HsmReparseBufferRaw.RawData)); 121 | Status = RtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, 122 | HsmReparseData->HsmReparseBufferRaw.RawData, 123 | HsmReparseDataLength - FIELD_OFFSET(REPARSE_DATA_BUFFER, HsmReparseBufferRaw.RawData), 124 | RawReparseData->HsmReparseBufferRaw.RawData, 125 | RawReparseDataLength - FIELD_OFFSET(REPARSE_DATA_BUFFER, HsmReparseBufferRaw.RawData), 126 | &UncompressedSize); 127 | if(NT_SUCCESS(Status)) 128 | { 129 | HsmReparseData->ReparseDataLength = RawReparseData->HsmReparseBufferRaw.Length; 130 | OutReparseData[0] = HsmReparseData; 131 | return STATUS_SUCCESS; 132 | } 133 | 134 | // Free the allocated buffer 135 | HeapFree(g_hHeap, 0, HsmReparseData); 136 | HsmReparseData = NULL; 137 | } 138 | return STATUS_INSUFFICIENT_RESOURCES; 139 | } 140 | else 141 | { 142 | OutReparseData[0] = RawReparseData; 143 | return STATUS_SUCCESS; 144 | } 145 | } 146 | 147 | //----------------------------------------------------------------------------- 148 | // Validates the HSM reparse point. Basically the same implementation like 149 | // cldflt.sys!HsmpRpValidateBuffer: 150 | // NTSTATUS HsmpRpValidateBuffer(PHSM_REPARSE_DATA pHsmReparseData, ULONG ReparseDataSize) 151 | 152 | NTSTATUS HsmpBitmapIsReparseBufferSupported(PHSM_DATA HsmData, ULONG RemainingLength) 153 | { 154 | NTSTATUS Status; 155 | ULONG NumberOfElements; 156 | BYTE Element1; 157 | BYTE Element2; 158 | 159 | // Perform common data validation 160 | Status = HsmValidateCommonData(HsmData, HSM_BITMAP_MAGIC, HSM_BITMAP_ELEMENTS, RemainingLength); 161 | if(!NT_SUCCESS(Status)) 162 | return Status; 163 | NumberOfElements = HsmData->NumberOfElements; 164 | 165 | // Check element[2] 166 | if(NumberOfElements < 2 || RemainingLength < HSM_MIN_DATA_SIZE(2)) 167 | return STATUS_NOT_FOUND; 168 | if(!HsmpCheckElement(HsmData, 2)) 169 | return STATUS_NOT_FOUND; 170 | if(HsmData->ElementInfos[2].Type != HSM_ELEMENT_TYPE_BYTE || HsmData->ElementInfos[2].Length != sizeof(BYTE)) 171 | return STATUS_NOT_FOUND; 172 | Element2 = *HsmGetElementData(HsmData, 2); 173 | 174 | if(Element2 != 0) 175 | { 176 | if(NumberOfElements < 4 || HsmData->ElementInfos[4].Offset == 0) 177 | return STATUS_CLOUD_FILE_METADATA_CORRUPT; 178 | if(HsmData->ElementInfos[4].Length > 0x1000) 179 | return STATUS_CLOUD_FILE_METADATA_CORRUPT; 180 | } 181 | 182 | if(Element2 > 1) 183 | STATUS_CLOUD_FILE_METADATA_CORRUPT; 184 | if(NumberOfElements < 1 || RemainingLength < HSM_MIN_DATA_SIZE(1)) 185 | return STATUS_CLOUD_FILE_METADATA_CORRUPT; 186 | if(!HsmpCheckElement(HsmData, 1)) 187 | return STATUS_CLOUD_FILE_METADATA_CORRUPT; 188 | if(HsmData->ElementInfos[1].Type != HSM_ELEMENT_TYPE_BYTE || HsmData->ElementInfos[1].Length != sizeof(BYTE)) 189 | return STATUS_NOT_FOUND; 190 | Element1 = *HsmGetElementData(HsmData, 1); 191 | 192 | if(Element1 <= 0 || Element1 > 0x14) 193 | STATUS_CLOUD_FILE_METADATA_CORRUPT; 194 | 195 | return STATUS_SUCCESS; 196 | } 197 | 198 | NTSTATUS HsmpCheckBitmapElement(PHSM_DATA HsmData, ULONG ElementIndex) 199 | { 200 | PHSM_DATA pBitmap = NULL; 201 | NTSTATUS Status = STATUS_SUCCESS; 202 | ULONG RemainingLength = HsmData->Length; 203 | ULONG BitmapLength = 0; 204 | 205 | __try 206 | { 207 | if(HsmData->NumberOfElements < ElementIndex || RemainingLength < HSM_MIN_DATA_SIZE(ElementIndex)) 208 | { 209 | Status = STATUS_NOT_FOUND; 210 | __leave; 211 | } 212 | 213 | if(!HsmpCheckElement(HsmData, ElementIndex)) 214 | { 215 | Status = STATUS_NOT_FOUND; 216 | __leave; 217 | } 218 | 219 | if(HsmData->ElementInfos[ElementIndex].Type != HSM_ELEMENT_TYPE_BITMAP) 220 | { 221 | Status = STATUS_NOT_FOUND; 222 | __leave; 223 | } 224 | 225 | if(HsmData->ElementInfos[ElementIndex].Offset && HsmData->ElementInfos[ElementIndex].Length) 226 | { 227 | pBitmap = (PHSM_DATA)HsmGetElementData(HsmData, ElementIndex); 228 | BitmapLength = HsmData->ElementInfos[ElementIndex].Length; 229 | } 230 | 231 | Status = HsmpBitmapIsReparseBufferSupported(pBitmap, BitmapLength); 232 | } 233 | __finally 234 | { 235 | Status = (Status == STATUS_NOT_FOUND) ? STATUS_SUCCESS : Status; 236 | } 237 | 238 | return Status; 239 | } 240 | 241 | NTSTATUS HsmValidateReparseData(PREPARSE_DATA_BUFFER ReparseData) 242 | { 243 | PHSM_REPARSE_DATA HsmReparseData = (PHSM_REPARSE_DATA)(&ReparseData->HsmReparseBufferRaw); 244 | PHSM_DATA HsmData; 245 | NTSTATUS Status; 246 | ULONG NumberOfElements; 247 | ULONG RemainingLength; 248 | ULONG ElementFlags; 249 | 250 | // Check the length 251 | if(HsmReparseData->Length != ReparseData->ReparseDataLength) 252 | return STATUS_INVALID_BLOCK_LENGTH; 253 | 254 | // Check the revision 255 | if((HsmReparseData->Flags & 0x0F) > 1) 256 | return STATUS_UNKNOWN_REVISION; 257 | if((HsmReparseData->Flags & 0x0F) < 1) 258 | return STATUS_REVISION_MISMATCH; 259 | 260 | // Get the HSM data and the remaining length 261 | HsmData = (PHSM_DATA)&HsmReparseData->FileData; 262 | RemainingLength = HsmReparseData->Length - FIELD_OFFSET(HSM_REPARSE_DATA, FileData); 263 | 264 | // Check the common part of the data 265 | Status = HsmValidateCommonData(HsmData, HSM_FILE_MAGIC, HSM_FILE_ELEMENTS, RemainingLength); 266 | if(!NT_SUCCESS(Status)) 267 | return Status; 268 | NumberOfElements = HsmData->NumberOfElements; 269 | 270 | // Check element[1] (flags?) 271 | if(NumberOfElements < 1 || RemainingLength < HSM_MIN_DATA_SIZE(2)) 272 | return STATUS_NOT_FOUND; 273 | if(!HsmpCheckElement(HsmData, 1)) 274 | return STATUS_NOT_FOUND; 275 | if(HsmData->ElementInfos[1].Type != HSM_ELEMENT_TYPE_UINT32 || HsmData->ElementInfos[1].Length != sizeof(DWORD)) 276 | return STATUS_NOT_FOUND; 277 | ElementFlags = *(PULONG)HsmGetElementData(HsmData, 1); 278 | if(ElementFlags & 0x10) 279 | return STATUS_SUCCESS; 280 | 281 | // Check element[2] (stream size) 282 | if(NumberOfElements < 2 || RemainingLength < HSM_MIN_DATA_SIZE(3)) 283 | return STATUS_NOT_FOUND; 284 | if(!HsmpCheckElement(HsmData, 2)) 285 | return STATUS_NOT_FOUND; 286 | if(HsmData->ElementInfos[2].Type != HSM_ELEMENT_TYPE_UINT64 || HsmData->ElementInfos[2].Length != sizeof(ULONGLONG)) 287 | return STATUS_NOT_FOUND; 288 | 289 | // Check element[4] (HSM_BITMAP) 290 | Status = HsmpCheckBitmapElement(HsmData, 4); 291 | if(!NT_SUCCESS(Status)) 292 | return Status; 293 | 294 | // Check element[5] (HSM_BITMAP) 295 | Status = HsmpCheckBitmapElement(HsmData, 5); 296 | if(!NT_SUCCESS(Status)) 297 | return Status; 298 | 299 | // Check element[6] (HSM_BITMAP) 300 | Status = HsmpCheckBitmapElement(HsmData, 6); 301 | return Status; 302 | } 303 | -------------------------------------------------------------------------------- /DlgEaEditor.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* DlgEaEditor.cpp Copyright (c) Ladislav Zezula 2005 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Description : */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 16.08.05 1.00 Lad Created */ 9 | /*****************************************************************************/ 10 | 11 | #include "FileTest.h" 12 | #include "resource.h" 13 | 14 | //----------------------------------------------------------------------------- 15 | // Local functions 16 | 17 | static int nChangingEdit = 0; 18 | 19 | static DWORD TwoDigitsToBinValue(LPCTSTR szBinValue) 20 | { 21 | TCHAR chDigit1; 22 | TCHAR chDigit2; 23 | 24 | // Verify the digits 25 | if(!isxdigit(szBinValue[0]) || !isxdigit(szBinValue[1])) 26 | return (DWORD)0x100; 27 | 28 | chDigit2 = (TCHAR)(UINT_PTR)CharUpper((LPTSTR)szBinValue[0]); 29 | chDigit1 = (TCHAR)(UINT_PTR)CharUpper((LPTSTR)szBinValue[1]); 30 | if(chDigit1 > '9') 31 | chDigit1 -= 'A' - '9' - 1; 32 | if(chDigit2 > '9') 33 | chDigit2 -= 'A' - '9' - 1; 34 | 35 | return ((chDigit2 - '0') << 0x04) | (chDigit1 - '0'); 36 | } 37 | 38 | static int CTextToBinArray(LPTSTR szTextValue, LPBYTE pbBinValue) 39 | { 40 | DWORD dwBinValue; 41 | int nLength = 0; 42 | 43 | while(*szTextValue != 0) 44 | { 45 | if(*szTextValue == _T('\\')) 46 | { 47 | szTextValue++; 48 | switch(*szTextValue) 49 | { 50 | case _T('\\'): 51 | *pbBinValue = '\\'; 52 | break; 53 | 54 | case _T('x'): 55 | case _T('X'): 56 | szTextValue++; 57 | dwBinValue = TwoDigitsToBinValue(szTextValue); 58 | if(dwBinValue == 0x0100) 59 | return -1; 60 | 61 | *pbBinValue = (BYTE)dwBinValue; 62 | szTextValue++; 63 | break; 64 | } 65 | } 66 | else 67 | *pbBinValue = (BYTE)(*szTextValue); 68 | 69 | szTextValue++; 70 | pbBinValue++; 71 | nLength++; 72 | } 73 | 74 | return nLength; 75 | } 76 | 77 | static int BinTextToBinArray(LPTSTR szBinValue, LPBYTE pbBinValue) 78 | { 79 | DWORD dwBinValue; 80 | int nLength = 0; 81 | 82 | while(*szBinValue != 0) 83 | { 84 | // Skip spaces 85 | while(0 < *szBinValue && *szBinValue <= 0x20) 86 | szBinValue++; 87 | 88 | dwBinValue = TwoDigitsToBinValue(szBinValue); 89 | if(dwBinValue == 0x0100) 90 | return -1; 91 | 92 | *pbBinValue++ = (BYTE)dwBinValue; 93 | szBinValue += 2; 94 | nLength++; 95 | 96 | // Must be a space there 97 | if(*szBinValue > 0x20) 98 | return -1; 99 | 100 | // Skip spaces 101 | while(0 < *szBinValue && *szBinValue <= 0x20) 102 | szBinValue++; 103 | } 104 | 105 | return nLength; 106 | } 107 | 108 | static int BinArrayToBinText(LPBYTE pbBinValue, int nBinLength, LPTSTR szBinValue, size_t cchBinValue) 109 | { 110 | LPTSTR szBinValueEnd = szBinValue + cchBinValue; 111 | 112 | for(int i = 0; i < nBinLength; i++, pbBinValue++) 113 | { 114 | StringCchPrintf(szBinValue, (szBinValueEnd - szBinValue), _T("%02lX "), (*pbBinValue & 0x000000FF)); 115 | szBinValue += 3; 116 | } 117 | 118 | *szBinValue = 0; 119 | return nBinLength; 120 | } 121 | 122 | static int BinArrayToCText(LPBYTE pbBinValue, int nBinLength, LPTSTR szTextValue, size_t cchTextLength) 123 | { 124 | LPTSTR szTextEnd = szTextValue + cchTextLength; 125 | 126 | for(int i = 0; i < nBinLength; i++, pbBinValue++) 127 | { 128 | if(0x20 <= *pbBinValue && *pbBinValue < 0x80) 129 | { 130 | *szTextValue++ = (TCHAR)*pbBinValue; 131 | } 132 | else 133 | { 134 | StringCchPrintf(szTextValue, (szTextEnd - szTextValue), _T("\\x%02lX"), (*pbBinValue & 0x000000FF)); 135 | szTextValue += 4; 136 | } 137 | } 138 | 139 | *szTextValue = 0; 140 | return nBinLength; 141 | } 142 | 143 | 144 | static void UpdateDialog(HWND hDlg) 145 | { 146 | BOOL bEnable; 147 | 148 | nChangingEdit++; 149 | 150 | bEnable = (IsDlgButtonChecked(hDlg, IDC_RADIO1) == BST_CHECKED); 151 | EnableWindow(GetDlgItem(hDlg, IDC_DATA_VALUE_TEXT), bEnable); 152 | 153 | bEnable = (IsDlgButtonChecked(hDlg, IDC_RADIO2) == BST_CHECKED); 154 | EnableWindow(GetDlgItem(hDlg, IDC_DATA_VALUE_BIN), bEnable); 155 | 156 | nChangingEdit--; 157 | } 158 | 159 | 160 | static void SetDlgItemCText(HWND hDlg, UINT nIDCtrl, LPBYTE pbData, int nLength) 161 | { 162 | LPTSTR szBinText; 163 | size_t cchLength = nLength * 4 + 1; 164 | 165 | szBinText = new TCHAR[cchLength]; 166 | if(szBinText != NULL) 167 | { 168 | BinArrayToCText(pbData, nLength, szBinText, cchLength); 169 | SetDlgItemText(hDlg, nIDCtrl, szBinText); 170 | delete [] szBinText; 171 | } 172 | } 173 | 174 | 175 | static void SetDlgItemBin(HWND hDlg, UINT nIDCtrl, LPBYTE pbData, int nLength) 176 | { 177 | LPTSTR szBinText; 178 | size_t cchLength = nLength * 4 + 1; 179 | 180 | szBinText = new TCHAR[cchLength]; 181 | if(szBinText != NULL) 182 | { 183 | BinArrayToBinText(pbData, nLength, szBinText, cchLength); 184 | SetDlgItemText(hDlg, nIDCtrl, szBinText); 185 | delete [] szBinText; 186 | } 187 | } 188 | 189 | // Text value has changed 190 | static int UpdateEaValueBin(HWND hDlg) 191 | { 192 | LPTSTR szTextValue; 193 | LPTSTR szBinValue; 194 | LPBYTE pbBinValue; 195 | HWND hSrcEdit = GetDlgItem(hDlg, IDC_DATA_VALUE_TEXT); 196 | HWND hTrgEdit = GetDlgItem(hDlg, IDC_DATA_VALUE_BIN); 197 | int nTextLength = GetWindowTextLength(hSrcEdit); 198 | int cchTextLength = nTextLength * 3 + 1; 199 | int nBinLength; 200 | 201 | szTextValue = new TCHAR[nTextLength + 1]; 202 | szBinValue = new TCHAR[cchTextLength]; 203 | pbBinValue = new BYTE[nTextLength + 1]; 204 | GetWindowText(hSrcEdit, szTextValue, nTextLength + 1); 205 | 206 | // Process the binary buffer and convert it to the binary data 207 | nChangingEdit++; 208 | nBinLength = CTextToBinArray(szTextValue, pbBinValue); 209 | if(nBinLength != -1) 210 | { 211 | BinArrayToBinText(pbBinValue, nBinLength, szBinValue, cchTextLength); 212 | SetWindowText(hTrgEdit, szBinValue); 213 | } 214 | else 215 | SetWindowTextRc(hTrgEdit, IDS_CONVERSION_ERROR); 216 | nChangingEdit--; 217 | 218 | delete [] pbBinValue; 219 | delete [] szBinValue; 220 | delete [] szTextValue; 221 | return TRUE; 222 | } 223 | 224 | // Binary value has changed 225 | static int UpdateEaValueText(HWND hDlg) 226 | { 227 | LPTSTR szTextValue; 228 | LPTSTR szBinValue; 229 | LPBYTE pbBinValue; 230 | HWND hSrcEdit = GetDlgItem(hDlg, IDC_DATA_VALUE_BIN); 231 | HWND hTrgEdit = GetDlgItem(hDlg, IDC_DATA_VALUE_TEXT); 232 | int nTextLength = GetWindowTextLength(hSrcEdit); 233 | int cchTextLength = nTextLength * 4 + 1; 234 | int nBinLength; 235 | 236 | szTextValue = new TCHAR[cchTextLength]; 237 | szBinValue = new TCHAR[nTextLength + 1]; 238 | pbBinValue = new BYTE[nTextLength + 1]; 239 | GetWindowText(hSrcEdit, szBinValue, nTextLength + 1); 240 | CharUpper(szBinValue); 241 | 242 | // Process the binary buffer and convert it to the binary data 243 | nChangingEdit++; 244 | nBinLength = BinTextToBinArray(szBinValue, pbBinValue); 245 | if(nBinLength != -1) 246 | { 247 | BinArrayToCText(pbBinValue, nBinLength, szTextValue, cchTextLength); 248 | SetWindowText(hTrgEdit, szTextValue); 249 | } 250 | else 251 | SetWindowTextRc(hTrgEdit, IDS_CONVERSION_ERROR); 252 | nChangingEdit--; 253 | 254 | delete [] pbBinValue; 255 | delete [] szBinValue; 256 | delete [] szTextValue; 257 | return TRUE; 258 | } 259 | 260 | //----------------------------------------------------------------------------- 261 | // Dialog handlers 262 | 263 | static int OnInitDialog(HWND hDlg, LPARAM lParam) 264 | { 265 | PFILE_FULL_EA_INFORMATION * ppEaItem = (PFILE_FULL_EA_INFORMATION *)lParam; 266 | PFILE_FULL_EA_INFORMATION pEaItem = *ppEaItem; 267 | HWND hWndChild; 268 | 269 | // Configure the dialog 270 | SetWindowLongPtr(hDlg, DWLP_USER, lParam); 271 | SetDialogIcon(hDlg, IDI_FILE_TEST); 272 | CenterWindowToParent(hDlg); 273 | 274 | // Set the dialog title to "Insert" or to "Edit" 275 | SetWindowTextRc(hDlg, pEaItem ? IDS_EDIT_EA_TITLE : IDS_INSERT_EA_TITLE); 276 | 277 | // Set the name and value limit 278 | hWndChild = GetDlgItem(hDlg, IDC_DATA_NAME); 279 | if(hWndChild != NULL) 280 | Edit_LimitText(hWndChild, (BYTE)-1); 281 | 282 | // Fill the dialog 283 | nChangingEdit++; 284 | CheckDlgButton(hDlg, IDC_RADIO1, BST_CHECKED); 285 | if(pEaItem != NULL) 286 | { 287 | if(hWndChild != NULL) 288 | SetWindowTextA(hWndChild, pEaItem->EaName); 289 | 290 | SetDlgItemCText(hDlg, 291 | IDC_DATA_VALUE_TEXT, 292 | (LPBYTE)pEaItem->EaName + pEaItem->EaNameLength + 1, 293 | pEaItem->EaValueLength); 294 | 295 | SetDlgItemBin(hDlg, 296 | IDC_DATA_VALUE_BIN, 297 | (LPBYTE)pEaItem->EaName + pEaItem->EaNameLength + 1, 298 | pEaItem->EaValueLength); 299 | } 300 | UpdateDialog(hDlg); 301 | nChangingEdit--; 302 | 303 | return TRUE; 304 | } 305 | 306 | static BOOL OnSaveDialog(HWND hDlg) 307 | { 308 | PFILE_FULL_EA_INFORMATION * PtrReturnEa = (PFILE_FULL_EA_INFORMATION *)GetWindowLongPtr(hDlg, DWLP_USER); 309 | PFILE_FULL_EA_INFORMATION NewEaItem = NULL; 310 | PFILE_FULL_EA_INFORMATION OldEaItem = PtrReturnEa[0]; 311 | LPTSTR szBinBuffer = NULL; 312 | HWND hWndName = GetDlgItem(hDlg, IDC_DATA_NAME); 313 | HWND hWndValue = GetDlgItem(hDlg, IDC_DATA_VALUE_BIN); 314 | int nTotalLength; 315 | int nValueLength = GetWindowTextLength(hWndValue); 316 | int nNameLength = 0; 317 | 318 | if(hWndName != NULL) 319 | { 320 | // Retrieve the name length 321 | nNameLength = GetWindowTextLength(hWndName); 322 | if(nNameLength == 0) 323 | { 324 | // Don't accept empty name 325 | MessageBoxRc(hDlg, IDS_ERROR, IDS_NO_EA_NAME); 326 | SetFocus(hWndName); 327 | return FALSE; 328 | } 329 | 330 | // Make sure that the name length is not bigger than 255 331 | if(nNameLength > 255) 332 | nNameLength = 255; 333 | } 334 | 335 | // Create new EA entry 336 | nTotalLength = sizeof(FILE_FULL_EA_INFORMATION) + nNameLength + nValueLength + 2; 337 | szBinBuffer = new TCHAR[nValueLength + 1]; 338 | NewEaItem = (PFILE_FULL_EA_INFORMATION)(new char[nTotalLength]); 339 | 340 | // Initialize the EA entry 341 | ZeroMemory(NewEaItem, nTotalLength); 342 | 343 | // Fill the name and value 344 | if(hWndName != NULL) 345 | GetWindowTextA(hWndName, NewEaItem->EaName, nNameLength + 1); 346 | NewEaItem->EaNameLength = (UCHAR)nNameLength; 347 | 348 | GetWindowText(hWndValue, szBinBuffer, nValueLength + 1); 349 | NewEaItem->EaValueLength = (USHORT)BinTextToBinArray(szBinBuffer, 350 | (LPBYTE)NewEaItem->EaName + NewEaItem->EaNameLength + 1); 351 | if(NewEaItem->EaValueLength == (USHORT)-1) 352 | { 353 | MessageBoxRc(hDlg, IDS_ERROR, IDS_CONVERSION_ERROR_MSG); 354 | delete [] szBinBuffer; 355 | delete [] NewEaItem; 356 | return FALSE; 357 | } 358 | 359 | // Set the correct length of the EA item 360 | NewEaItem->NextEntryOffset = GetEaEntrySize(NewEaItem); 361 | 362 | // Replace the item 363 | if(OldEaItem != NULL) 364 | delete OldEaItem; 365 | PtrReturnEa[0] = NewEaItem; 366 | delete [] szBinBuffer; 367 | return TRUE; 368 | } 369 | 370 | static int OnCommand(HWND hDlg, UINT nNotify, UINT nIDCtrl) 371 | { 372 | if(nNotify == BN_CLICKED) 373 | { 374 | switch(nIDCtrl) 375 | { 376 | case IDC_RADIO1: 377 | UpdateDialog(hDlg); 378 | SetFocus(GetDlgItem(hDlg, IDC_DATA_VALUE_TEXT)); 379 | return TRUE; 380 | 381 | case IDC_RADIO2: 382 | UpdateDialog(hDlg); 383 | SetFocus(GetDlgItem(hDlg, IDC_DATA_VALUE_BIN)); 384 | return TRUE; 385 | 386 | case IDOK: 387 | if(OnSaveDialog(hDlg) == FALSE) 388 | return TRUE; 389 | // No break here !! 390 | 391 | case IDCANCEL: 392 | EndDialog(hDlg, nIDCtrl); 393 | break; 394 | } 395 | } 396 | 397 | if(nNotify == EN_CHANGE && nChangingEdit == 0) 398 | { 399 | switch(nIDCtrl) 400 | { 401 | case IDC_DATA_VALUE_BIN: 402 | return UpdateEaValueText(hDlg); 403 | 404 | case IDC_DATA_VALUE_TEXT: 405 | return UpdateEaValueBin(hDlg); 406 | } 407 | } 408 | 409 | return FALSE; 410 | } 411 | 412 | static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 413 | { 414 | // Dialog initialization 415 | if(uMsg == WM_INITDIALOG) 416 | return OnInitDialog(hDlg, lParam); 417 | 418 | if(uMsg == WM_COMMAND) 419 | return OnCommand(hDlg, HIWORD(wParam), LOWORD(wParam)); 420 | 421 | return FALSE; 422 | } 423 | 424 | INT_PTR EaEditorDialog(HWND hParent, PFILE_FULL_EA_INFORMATION * ppEaItem) 425 | { 426 | return DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_EA_EDITOR), hParent, DialogProc, (LPARAM)ppEaItem); 427 | } 428 | -------------------------------------------------------------------------------- /FileTest.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | FileTest 23 | {73D582FC-D08A-4322-AFDB-C244E9716CB4} 24 | FileTest 25 | Win32Proj 26 | 10.0 27 | false 28 | 29 | 30 | 31 | Application 32 | v143 33 | Unicode 34 | true 35 | 36 | 37 | Application 38 | v143 39 | Unicode 40 | 41 | 42 | Application 43 | v143 44 | Unicode 45 | true 46 | 47 | 48 | Application 49 | v143 50 | Unicode 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | <_ProjectFileVersion>14.0.23107.0 70 | 71 | 72 | .\bin\$(Platform)\$(Configuration)\ 73 | .\bin\$(Platform)\$(Configuration)\ 74 | true 75 | false 76 | $(ProjectName) 77 | 78 | 79 | .\bin\$(Platform)\$(Configuration)\ 80 | .\bin\$(Platform)\$(Configuration)\ 81 | true 82 | false 83 | $(ProjectName) 84 | $(VC_IncludePath);$(WindowsSDK_IncludePath); 85 | 86 | 87 | .\bin\$(Platform)\$(Configuration)\ 88 | .\bin\$(Platform)\$(Configuration)\ 89 | false 90 | false 91 | $(ProjectName) 92 | 93 | 94 | .\bin\$(Platform)\$(Configuration)\ 95 | .\bin\$(Platform)\$(Configuration)\ 96 | false 97 | false 98 | $(ProjectName) 99 | $(VC_IncludePath);$(WindowsSDK_IncludePath); 100 | 101 | 102 | 103 | Disabled 104 | ../aaa/inc;%(AdditionalIncludeDirectories) 105 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 106 | EnableFastChecks 107 | MultiThreadedDebug 108 | Use 109 | FileTest.h 110 | Level4 111 | EditAndContinue 112 | 113 | 114 | ../aaa/lib32;%(AdditionalLibraryDirectories) 115 | true 116 | Windows 117 | true 118 | true 119 | MachineX86 120 | false 121 | /PDBALTPATH:%_PDB% /Brepro %(AdditionalOptions) 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | X64 130 | 131 | 132 | Disabled 133 | ../aaa/inc;%(AdditionalIncludeDirectories) 134 | WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 135 | Sync 136 | Default 137 | MultiThreadedDebug 138 | Use 139 | FileTest.h 140 | Level4 141 | ProgramDatabase 142 | 143 | 144 | ../aaa/lib64;%(AdditionalLibraryDirectories) 145 | true 146 | Windows 147 | true 148 | true 149 | MachineX64 150 | false 151 | /PDBALTPATH:%_PDB% /Brepro %(AdditionalOptions) 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | ../aaa/inc;%(AdditionalIncludeDirectories) 160 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 161 | MultiThreaded 162 | Use 163 | FileTest.h 164 | Level4 165 | ProgramDatabase 166 | 167 | 168 | ../aaa/lib32;%(AdditionalLibraryDirectories) 169 | true 170 | Windows 171 | true 172 | true 173 | true 174 | true 175 | MachineX86 176 | /PDBALTPATH:%_PDB% /Brepro %(AdditionalOptions) 177 | 178 | 179 | Postbuild.exe $(TargetPath) FileTest.rc /subsystem4 180 | 181 | 182 | 183 | 184 | X64 185 | 186 | 187 | ../aaa/inc;%(AdditionalIncludeDirectories) 188 | WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 189 | Sync 190 | MultiThreaded 191 | Use 192 | FileTest.h 193 | Level4 194 | ProgramDatabase 195 | 196 | 197 | ../aaa/lib64;%(AdditionalLibraryDirectories) 198 | true 199 | Windows 200 | true 201 | true 202 | true 203 | true 204 | MachineX64 205 | /PDBALTPATH:%_PDB% /Brepro %(AdditionalOptions) 206 | 207 | 208 | Postbuild.exe $(TargetPath) FileTest.rc /subsystem4 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | Use 219 | Use 220 | Use 221 | Use 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | Create 250 | Create 251 | Create 252 | Create 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | -------------------------------------------------------------------------------- /WinMain.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* WinMain.cpp Copyright (c) Ladislav Zezula 2003 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* A file that simulates access on a file */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 14.07.03 1.00 Lad The first version of WinMain.cpp */ 9 | /*****************************************************************************/ 10 | 11 | #include "FileTest.h" 12 | #include "resource.h" 13 | 14 | #pragma comment(lib, "Comctl32.lib") 15 | 16 | //----------------------------------------------------------------------------- 17 | // Global variables 18 | 19 | TContextMenu g_ContextMenus[MAX_CONTEXT_MENUS]; 20 | TToolTip g_Tooltip; 21 | DWORD g_dwWinVer; 22 | DWORD g_dwWinBuild; 23 | TCHAR g_szInitialDirectory[MAX_PATH]; 24 | DWORD g_dwMenuCount = 0; 25 | 26 | //----------------------------------------------------------------------------- 27 | // Local functions 28 | 29 | static LPCTSTR IsCommandSwitch(LPCTSTR szArg, LPCTSTR szSwitch) 30 | { 31 | size_t nLength; 32 | 33 | // It must be valid 34 | if(szArg && szArg[0] && szSwitch && szSwitch[0]) 35 | { 36 | // It has to start with '/' or '-' 37 | if(szArg[0] == _T('/') || szArg[0] == _T('-')) 38 | { 39 | // Get length and the inner switch 40 | nLength = _tcslen(szSwitch); 41 | szArg++; 42 | 43 | if(!_tcsnicmp(szArg, szSwitch, nLength)) 44 | { 45 | return szArg + nLength; 46 | } 47 | } 48 | } 49 | return NULL; 50 | } 51 | 52 | static bool CheckForCommandSwitch(LPCTSTR szArg, LPCTSTR szSwitch, LPDWORD PtrValue, bool bIsSingleSwitch = false) 53 | { 54 | LPCTSTR szArgValue; 55 | LPCTSTR szIntValue; 56 | LPTSTR szEndValue; 57 | int nRadix; 58 | 59 | if((szArgValue = IsCommandSwitch(szArg, szSwitch)) != NULL) 60 | { 61 | // Pre-fill the value with zero 62 | PtrValue[0] = 0; 63 | 64 | // Variant #1: /Argument:IntValue 65 | if(szArgValue[0] == _T(':') && bIsSingleSwitch == false) 66 | { 67 | szArgValue = szArgValue + 1; 68 | szIntValue = SkipHexaPrefix(szArgValue); 69 | nRadix = (szIntValue > szArgValue) ? 16 : 10; 70 | PtrValue[0] = StrToInt(szIntValue, &szEndValue, nRadix); 71 | return (szEndValue[0] == 0); 72 | } 73 | 74 | // Variant #2: /Argument 75 | if(szArgValue[0] == 0 && bIsSingleSwitch) 76 | { 77 | PtrValue[0] = TRUE; 78 | return true; 79 | } 80 | } 81 | return false; 82 | } 83 | 84 | static void SetTokenObjectIntegrityLevel(DWORD dwIntegrityLevel) 85 | { 86 | SID_IDENTIFIER_AUTHORITY Sia = SECURITY_MANDATORY_LABEL_AUTHORITY; 87 | SECURITY_DESCRIPTOR sd; 88 | HANDLE hToken; 89 | DWORD dwLength; 90 | PACL pAcl; 91 | PSID pSid; 92 | 93 | // Do nothing on OSes where mandatory ACEs are not supported 94 | if(pfnAddMandatoryAce == NULL) 95 | return; 96 | 97 | // Initialize blank security descriptor 98 | if(!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) 99 | return; 100 | 101 | // Allocate mandatory label SID 102 | if(!AllocateAndInitializeSid(&Sia, 1, dwIntegrityLevel, 0, 0, 0, 0, 0, 0, 0, &pSid)) 103 | return; 104 | 105 | // Open current token 106 | if(!OpenThreadToken(GetCurrentThread(), WRITE_OWNER, TRUE, &hToken)) 107 | { 108 | if(GetLastError() == ERROR_NO_TOKEN) 109 | OpenProcessToken(GetCurrentProcess(), WRITE_OWNER, &hToken); 110 | } 111 | 112 | // If succeeded, set the integrity level 113 | if(hToken != NULL) 114 | { 115 | // Create ACL 116 | dwLength = sizeof(ACL) + sizeof(SYSTEM_MANDATORY_LABEL_ACE) - sizeof(DWORD) + GetLengthSid(pSid); 117 | pAcl = (PACL)HeapAlloc(g_hHeap, 0, dwLength); 118 | if(pAcl != NULL) 119 | { 120 | if(InitializeAcl(pAcl, dwLength, ACL_REVISION)) 121 | { 122 | if(pfnAddMandatoryAce(pAcl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, pSid)) 123 | { 124 | NtSetSecurityObject(hToken, LABEL_SECURITY_INFORMATION, &sd); 125 | } 126 | } 127 | 128 | HeapFree(g_hHeap, 0, pAcl); 129 | } 130 | } 131 | 132 | FreeSid(pSid); 133 | } 134 | 135 | BOOL CALLBACK EnumMenusProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR /* lParam */) 136 | { 137 | // Only take menus 138 | if(lpszType == RT_MENU) 139 | { 140 | // Debug code check 141 | assert(g_dwMenuCount < MAX_CONTEXT_MENUS); 142 | 143 | // Check if the number of context menus is in range 144 | if(g_dwMenuCount < MAX_CONTEXT_MENUS) 145 | { 146 | // Insert the menu entry 147 | g_ContextMenus[g_dwMenuCount].szMenuName = lpszName; 148 | g_ContextMenus[g_dwMenuCount].hMenu = LoadMenu(hModule, lpszName); 149 | 150 | // Increment the menu count 151 | g_dwMenuCount++; 152 | } 153 | } 154 | 155 | // Keep enumerating 156 | return TRUE; 157 | } 158 | 159 | static HANDLE InitialOpenFile(TFileTestData * pData) 160 | { 161 | OBJECT_ATTRIBUTES ObjAttr; 162 | IO_STATUS_BLOCK IoStatus = {0}; 163 | UNICODE_STRING FileName; 164 | HANDLE hFile = NULL; 165 | 166 | if(pData->szFileName1 && pData->szFileName1[0]) 167 | { 168 | if(IsNativeName(pData->szFileName1)) 169 | { 170 | InitializeObjectAttributes(&ObjAttr, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL); 171 | RtlInitUnicodeString(&FileName, pData->szFileName1); 172 | NtCreateFile(&hFile, 173 | pData->OpenFile.dwDesiredAccess, 174 | &ObjAttr, 175 | &IoStatus, 176 | &pData->OpenFile.AllocationSize, 177 | pData->OpenFile.dwFlagsAndAttributes, 178 | pData->OpenFile.dwShareAccess, 179 | pData->OpenFile.dwCreateDisposition2, 180 | pData->OpenFile.dwCreateOptions, 181 | pData->OpenFile.pvFileEa, 182 | pData->OpenFile.cbFileEa); 183 | } 184 | else 185 | { 186 | hFile = CreateFile(pData->szFileName1, 187 | pData->OpenFile.dwDesiredAccess, 188 | pData->OpenFile.dwShareAccess, 189 | NULL, 190 | pData->OpenFile.dwCreateDisposition1, 191 | pData->OpenFile.dwFlagsAndAttributes, 192 | NULL); 193 | } 194 | } 195 | return hFile; 196 | } 197 | 198 | //----------------------------------------------------------------------------- 199 | // WinMain 200 | 201 | int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int) 202 | { 203 | TFileTestData * pData; 204 | DWORD bAsynchronousOpen = 0; 205 | DWORD bOpenFile = 0; 206 | DWORD bShowHelp = 0; 207 | int nFileNameIndex = 0; 208 | 209 | // Initialize the instance 210 | InitInstance(hInstance); 211 | InitCommonControls(); 212 | 213 | // Get the Windows version 214 | g_dwWinVer = GetWindowsVersion(); 215 | 216 | // Allocate and fill our working structure with command line parameters 217 | if((pData = new TFileTestData) != NULL) 218 | { 219 | // Initialize the TFileTestData structure 220 | memset(pData, 0, sizeof(TFileTestData)); 221 | pData->MagicHeader = FILETEST_DATA_MAGIC; 222 | pData->szDirName = pData->szBuffer1; 223 | pData->szFileName1 = pData->szBuffer2; 224 | pData->szFileName2 = pData->szBuffer3; 225 | pData->szTemplate = pData->szBuffer4; 226 | pData->szSectionName = pData->szBuffer5; 227 | pData->RelaFile.szId = "RelativeFile"; 228 | pData->OpenFile.szId = "MainFile"; 229 | pData->pOP = &pData->OpenFile; 230 | 231 | // Set default values for CreateFile and NtCreateFile 232 | pData->OpenFile.dwOA_Attributes = OBJ_CASE_INSENSITIVE; 233 | pData->OpenFile.dwCreateDisposition1 = OPEN_ALWAYS; 234 | pData->OpenFile.dwCreateDisposition2 = FILE_OPEN_IF; 235 | pData->OpenFile.dwDesiredAccess = GENERIC_READ; 236 | pData->OpenFile.dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; 237 | pData->OpenFile.dwShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; 238 | pData->OpenFile.dwCreateOptions = 0; 239 | pData->dwOplockLevel = OPLOCK_LEVEL_CACHE_READ | OPLOCK_LEVEL_CACHE_WRITE; 240 | pData->dwCopyFileFlags = 0; 241 | pData->dwMoveFileFlags = 0; 242 | 243 | // Set default values for opening relative file by NtCreateFile 244 | pData->RelaFile.dwOA_Attributes = OBJ_CASE_INSENSITIVE; 245 | pData->RelaFile.dwCreateDisposition1 = OPEN_EXISTING; 246 | pData->RelaFile.dwCreateDisposition2 = FILE_OPEN; 247 | pData->RelaFile.dwDesiredAccess = FILE_READ_DATA; 248 | pData->RelaFile.dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; 249 | pData->RelaFile.dwShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; 250 | 251 | // Set default values for NtCreateSection/NtOpenSection 252 | pData->dwSectDesiredAccess = SECTION_ALL_ACCESS; 253 | pData->dwSectPageProtection = PAGE_READONLY; 254 | pData->dwSectAllocAttributes = SEC_COMMIT; 255 | pData->dwSectWin32Protect = PAGE_READONLY; 256 | 257 | // Set the default values for NtQuerySecurityObject 258 | pData->SecurityInformation = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; 259 | pData->InitialPage = INVALID_PAGE_INDEX; 260 | 261 | // Parse command line arguments 262 | for(int i = 1; i < __argc; i++) 263 | { 264 | LPCTSTR szPrivilegeName; 265 | 266 | if(CheckForCommandSwitch(__targv[i], _T("DesiredAccess"), &pData->OpenFile.dwDesiredAccess)) 267 | continue; 268 | if(CheckForCommandSwitch(__targv[i], _T("ShareAccess"), &pData->OpenFile.dwShareAccess)) 269 | continue; 270 | if(CheckForCommandSwitch(__targv[i], _T("CreateOptions"), &pData->OpenFile.dwCreateOptions)) 271 | continue; 272 | if(CheckForCommandSwitch(__targv[i], _T("CopyFileFlags"), &pData->dwCopyFileFlags)) 273 | continue; 274 | if(CheckForCommandSwitch(__targv[i], _T("MoveFileFlags"), &pData->dwMoveFileFlags)) 275 | continue; 276 | if(CheckForCommandSwitch(__targv[i], _T("SecurityInformation"), &pData->SecurityInformation)) 277 | continue; 278 | if(CheckForCommandSwitch(__targv[i], _T("InitialPage"), &pData->InitialPage)) 279 | continue; 280 | if(CheckForCommandSwitch(__targv[i], _T("AsyncOpen"), &bAsynchronousOpen, true)) 281 | continue; 282 | if(CheckForCommandSwitch(__targv[i], _T("OpenFile"), &bOpenFile, true)) 283 | continue; 284 | if(CheckForCommandSwitch(__targv[i], _T("Help"), &bShowHelp, true)) 285 | continue; 286 | if(CheckForCommandSwitch(__targv[i], _T("?"), &bShowHelp, true)) 287 | continue; 288 | 289 | // Check for privileges to enable 290 | if((szPrivilegeName = IsCommandSwitch(__targv[i], _T("EnablePrivilege"))) != NULL) 291 | { 292 | EnablePrivilege(szPrivilegeName + 1); 293 | continue; 294 | } 295 | 296 | // We assume that the argument is a file name 297 | switch(nFileNameIndex) 298 | { 299 | case 0: // The first file name argument 300 | ExpandEnvironmentStrings(__targv[i], pData->szFileName1, MAX_NT_PATH); 301 | nFileNameIndex++; 302 | break; 303 | 304 | case 1: // The second file name argument 305 | ExpandEnvironmentStrings(__targv[i], pData->szFileName2, MAX_NT_PATH); 306 | nFileNameIndex++; 307 | break; 308 | 309 | case 2: // The directory file name argument 310 | ExpandEnvironmentStrings(__targv[i], pData->szDirName, MAX_NT_PATH); 311 | nFileNameIndex++; 312 | break; 313 | } 314 | } 315 | 316 | // Set default file name 317 | if(pData->szFileName1[0] == 0) 318 | { 319 | StringCchCopy(pData->szFileName1, MAX_NT_PATH, _T("C:\\TestFile.bin")); 320 | pData->IsDefaultFileName1 = TRUE; 321 | } 322 | 323 | // 324 | // DEVELOPMENT CODE: Build the NT status table from the NTSTATUS.h 325 | // 326 | 327 | // BuildNtStatusTableFromNTSTATUS_H(); 328 | // VerifyNtStatusTable(); 329 | 330 | // 331 | // Resolve the dynamic loaded APIs 332 | // 333 | 334 | ResolveDynamicLoadedAPIs(); 335 | 336 | // 337 | // On Vista or newer, set the required integrity level of our token object 338 | // to lowest possible value. This will allow us to open our token even if the user 339 | // lowers the integrity level. 340 | // 341 | 342 | SetTokenObjectIntegrityLevel(SECURITY_MANDATORY_UNTRUSTED_RID); 343 | 344 | // 345 | // Save the application initial directory 346 | // 347 | 348 | GetCurrentDirectory(_countof(g_szInitialDirectory), g_szInitialDirectory); 349 | 350 | // 351 | // Register the data editor window 352 | // 353 | 354 | RegisterDataEditor(hInstance); 355 | 356 | // 357 | // To make handles obtained by NtCreateFile usable for calling ReadFile and WriteFile, 358 | // we have to set the FILE_SYNCHRONOUS_IO_NONALERT into CreateOptions 359 | // and SYNCHRONIZE into DesiredAccess. 360 | // 361 | 362 | // Pre-load menus so they don't generate any FS requests when loaded 363 | memset(g_ContextMenus, 0, sizeof(g_ContextMenus)); 364 | EnumResourceNames(g_hInst, RT_MENU, EnumMenusProc, NULL); 365 | 366 | // Modify for synchronous open, if required 367 | if(bAsynchronousOpen == false) 368 | { 369 | pData->OpenFile.dwCreateOptions |= FILE_SYNCHRONOUS_IO_NONALERT; 370 | pData->RelaFile.dwCreateOptions |= FILE_SYNCHRONOUS_IO_NONALERT; 371 | pData->OpenFile.dwDesiredAccess |= SYNCHRONIZE; 372 | pData->RelaFile.dwDesiredAccess |= SYNCHRONIZE; 373 | } 374 | 375 | #ifdef __TEST_MODE__ 376 | //DebugCode_TEST(); 377 | DebugCode_SecurityDescriptor(pData->szFileName1); 378 | #endif 379 | 380 | // Show the main dialog 381 | if(bShowHelp == FALSE) 382 | { 383 | // Shall we open the file? 384 | if(bOpenFile) 385 | pData->hFile = InitialOpenFile(pData); 386 | FileTestDialog(NULL, pData); 387 | } 388 | else 389 | HelpCommandLineDialog(NULL); 390 | 391 | // Free the data blobs 392 | pData->NtInfoData.Free(); 393 | pData->RdWrData.Free(); 394 | pData->OutData.Free(); 395 | pData->InData.Free(); 396 | delete pData; 397 | } 398 | 399 | return 0; 400 | } 401 | 402 | 403 | -------------------------------------------------------------------------------- /FileTest_vs08.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 15 | 18 | 19 | 20 | 21 | 22 | 29 | 32 | 35 | 38 | 41 | 44 | 58 | 61 | 64 | 67 | 79 | 82 | 85 | 88 | 91 | 94 | 97 | 101 | 102 | 109 | 112 | 115 | 118 | 121 | 125 | 139 | 142 | 145 | 148 | 160 | 163 | 166 | 169 | 172 | 175 | 178 | 182 | 183 | 191 | 194 | 197 | 200 | 203 | 206 | 217 | 220 | 223 | 226 | 242 | 245 | 248 | 251 | 254 | 257 | 260 | 264 | 265 | 273 | 276 | 279 | 282 | 285 | 289 | 300 | 303 | 306 | 309 | 323 | 326 | 329 | 332 | 335 | 338 | 341 | 345 | 346 | 347 | 348 | 349 | 350 | 355 | 358 | 359 | 362 | 363 | 366 | 367 | 370 | 371 | 374 | 375 | 378 | 381 | 385 | 386 | 389 | 393 | 394 | 397 | 401 | 402 | 405 | 409 | 410 | 411 | 414 | 415 | 418 | 419 | 422 | 423 | 426 | 427 | 430 | 431 | 434 | 435 | 438 | 439 | 442 | 443 | 446 | 447 | 450 | 451 | 454 | 455 | 458 | 459 | 462 | 463 | 466 | 467 | 470 | 471 | 474 | 475 | 478 | 479 | 482 | 483 | 486 | 487 | 490 | 491 | 494 | 495 | 498 | 499 | 502 | 503 | 506 | 507 | 510 | 511 | 514 | 515 | 518 | 521 | 525 | 526 | 529 | 533 | 534 | 537 | 541 | 542 | 545 | 549 | 550 | 551 | 552 | 557 | 560 | 561 | 564 | 565 | 568 | 569 | 572 | 573 | 576 | 577 | 580 | 581 | 584 | 585 | 588 | 589 | 592 | 593 | 596 | 597 | 600 | 601 | 604 | 605 | 606 | 611 | 614 | 615 | 618 | 619 | 622 | 623 | 626 | 627 | 630 | 631 | 634 | 635 | 638 | 639 | 642 | 643 | 646 | 647 | 648 | 651 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | -------------------------------------------------------------------------------- /TFastString.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* TFastString.h Copyright (c) Ladislav Zezula 2017 */ 3 | /*---------------------------------------------------------------------------*/ 4 | /* Helper class for growable string buffers */ 5 | /*---------------------------------------------------------------------------*/ 6 | /* Date Ver Who Comment */ 7 | /* -------- ---- --- ------- */ 8 | /* 27.11.17 1.00 Lad The first version of TFastString.h */ 9 | /*****************************************************************************/ 10 | 11 | #ifndef __TFASTSTRING_H__ 12 | #define __TFASTSTRING_H__ 13 | 14 | //----------------------------------------------------------------------------- 15 | // All allocations are done against global process heap handle 16 | 17 | extern HANDLE g_hHeap; 18 | 19 | //----------------------------------------------------------------------------- 20 | // Useful functions 21 | 22 | template 23 | bool IsSpace(XCHAR ch) 24 | { 25 | return (0 < ch && ch <= 0x20); 26 | } 27 | 28 | template 29 | FORCEINLINE XCHAR * SkipSpaces(const XCHAR * sz) 30 | { 31 | while(0 < *sz && *sz <= 0x20) 32 | sz++; 33 | return (XCHAR *)sz; 34 | } 35 | 36 | template 37 | FORCEINLINE XCHAR * SkipNonSpaces(const XCHAR * sz) 38 | { 39 | while(sz[0] != 0 && sz[0] > 0x20) 40 | sz++; 41 | return (XCHAR *)sz; 42 | } 43 | 44 | template 45 | FORCEINLINE XCHAR * SkipSpacesAndCommas(const XCHAR * sz) 46 | { 47 | while((0 < *sz && *sz <= 0x20) || *sz == ',') 48 | sz++; 49 | return (XCHAR *)sz; 50 | } 51 | 52 | FORCEINLINE size_t StringLength(const char * szStr) 53 | { 54 | return (szStr != NULL) ? strlen(szStr) : 0; 55 | } 56 | 57 | FORCEINLINE size_t StringLength(const wchar_t * szStr) 58 | { 59 | return (szStr != NULL) ? wcslen(szStr) : 0; 60 | } 61 | 62 | template 63 | static DWORD HashString(const XCHAR * szString) 64 | { 65 | DWORD dwHash = 0x7EEEEEE7; 66 | 67 | // Sanity check 68 | assert(szString != NULL); 69 | 70 | // Add the string 71 | while(szString[0] != 0) 72 | { 73 | dwHash = (dwHash >> 24) + (dwHash << 5) + dwHash + szString[0]; 74 | szString++; 75 | } 76 | 77 | return dwHash; 78 | } 79 | 80 | //----------------------------------------------------------------------------- 81 | // Common implementation of the fast string 82 | 83 | template 84 | class TFastString 85 | { 86 | public: 87 | 88 | typedef const XCHAR * LPCXSTR; 89 | typedef XCHAR * LPXSTR; 90 | 91 | TFastString() 92 | { 93 | Init(); 94 | } 95 | 96 | virtual ~TFastString() 97 | { 98 | if(m_pBuffer != m_StaticBuff) 99 | HeapFree(g_hHeap, 0, m_pBuffer); 100 | m_pBuffer = m_StaticBuff; 101 | } 102 | 103 | void InitFromLPCWSTR(LPCWSTR szStringW) 104 | { 105 | // Check for NULL and empty strings 106 | if(szStringW && szStringW[0]) 107 | { 108 | // Calculate length of the string 109 | size_t nWideLength = wcslen(szStringW); 110 | 111 | // Converting LPWSTR -> LPSTR? 112 | if(m_nCharSize == sizeof(CHAR)) 113 | { 114 | size_t nAnsiLength = nWideLength; 115 | size_t nTryCount = 0; 116 | 117 | __TryAgain: 118 | 119 | // Make sure that the string is reset 120 | Reset(); 121 | 122 | // Make sure there is enough space for the string 123 | if(EnsureSpace(nAnsiLength)) 124 | { 125 | // Convert the WIDE string to ANSI string 126 | nAnsiLength = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, szStringW, (int)nWideLength, (LPSTR)m_pBuffer, (int)nAnsiLength, NULL, NULL); 127 | if(nAnsiLength != 0) 128 | { 129 | m_pBufferPtr = m_pBuffer + nAnsiLength; 130 | } 131 | 132 | // If failed, we check whether this is a buffer overflow 133 | else if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) 134 | { 135 | nAnsiLength = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, szStringW, (int)nWideLength, NULL, 0, NULL, NULL); 136 | if(nTryCount++ == 0) 137 | { 138 | goto __TryAgain; 139 | } 140 | } 141 | } 142 | } 143 | else 144 | { 145 | if(EnsureSpace(nWideLength)) 146 | { 147 | memcpy(m_pBuffer, szStringW, nWideLength * sizeof(XCHAR)); 148 | m_pBufferPtr = m_pBuffer + nWideLength; 149 | } 150 | } 151 | } 152 | else 153 | { 154 | m_pBufferPtr = m_pBuffer; 155 | } 156 | 157 | // Make sure we're zero terminated 158 | m_pBufferPtr[0] = 0; 159 | } 160 | 161 | void InitFromLPCSTR(LPCSTR szStringA) 162 | { 163 | // Check for NULL and empty strings 164 | if(szStringA && szStringA[0]) 165 | { 166 | // Calculate length of the string 167 | size_t nAnsiLength = strlen(szStringA); 168 | 169 | // Converting LPSTR -> LPWSTR? 170 | if(m_nCharSize == sizeof(WCHAR)) 171 | { 172 | size_t nWideLength = nAnsiLength; 173 | size_t nTryCount = 0; 174 | 175 | __TryAgain: 176 | 177 | // Make sure that the string is reset 178 | Reset(); 179 | 180 | // Make sure there is enough space for the string 181 | if(EnsureSpace(nWideLength)) 182 | { 183 | // Convert the WIDE string to ANSI string 184 | nWideLength = MultiByteToWideChar(CP_ACP, 0, szStringA, (int)nAnsiLength, (LPWSTR)m_pBuffer, (int)nWideLength); 185 | if(nWideLength != 0) 186 | { 187 | m_pBufferPtr = m_pBuffer + nWideLength; 188 | } 189 | 190 | // If failed, we check whether this is a buffer overflow 191 | else if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) 192 | { 193 | nAnsiLength = MultiByteToWideChar(CP_ACP, 0, szStringA, (int)nAnsiLength, NULL, 0); 194 | if(nTryCount++ == 0) 195 | { 196 | goto __TryAgain; 197 | } 198 | } 199 | } 200 | } 201 | else 202 | { 203 | if(EnsureSpace(nAnsiLength)) 204 | { 205 | memcpy(m_pBuffer, szStringA, nAnsiLength * sizeof(XCHAR)); 206 | m_pBufferPtr = m_pBuffer + nAnsiLength; 207 | } 208 | } 209 | } 210 | else 211 | { 212 | m_pBufferPtr = m_pBuffer; 213 | } 214 | 215 | // Make sure we're zero terminated 216 | m_pBufferPtr[0] = 0; 217 | } 218 | 219 | bool AppendChar(XCHAR chOneChar) 220 | { 221 | // Ensure that there is space for one character 222 | if(!EnsureSpace(1)) 223 | return false; 224 | 225 | // Insert the character 226 | *m_pBufferPtr++ = chOneChar; 227 | return true; 228 | } 229 | 230 | bool AppendChars(XCHAR chOneChar, size_t nCount) 231 | { 232 | // Ensure that there is space for one character 233 | if(!EnsureSpace(nCount)) 234 | return false; 235 | 236 | // Insert the character 237 | for(size_t i = 0; i < nCount; i++) 238 | m_pBufferPtr[i] = chOneChar; 239 | m_pBufferPtr += nCount; 240 | return true; 241 | } 242 | 243 | bool AppendString(LPCXSTR szString, size_t nLength) 244 | { 245 | // Ensure that there is enough space in the buffers 246 | if(!EnsureSpace(nLength)) 247 | return false; 248 | 249 | memcpy(m_pBufferPtr, szString, nLength * sizeof(XCHAR)); 250 | m_pBufferPtr += nLength; 251 | return true; 252 | } 253 | 254 | bool AppendString(LPCXSTR szString) 255 | { 256 | return AppendString(szString, StringLength(szString)); 257 | } 258 | 259 | LPCXSTR PutEosAt(LPCXSTR szPosition) 260 | { 261 | LPXSTR szBufferPos = (LPXSTR)(szPosition); 262 | 263 | if(m_pBuffer <= szBufferPos && szBufferPos <= m_pBufferPtr) 264 | szBufferPos[0] = 0; 265 | return m_pBuffer; 266 | } 267 | 268 | void TrimLeftAndRight(bool(*PfnIsTrimChar)(XCHAR ch)) 269 | { 270 | LPXSTR pTrimRight = m_pBufferPtr; 271 | LPXSTR pTrimLeft = m_pBuffer; 272 | 273 | // Trim left 274 | while(pTrimLeft < pTrimRight && PfnIsTrimChar(pTrimLeft[0])) 275 | pTrimLeft++; 276 | 277 | // Trim right 278 | while(pTrimRight > pTrimLeft && PfnIsTrimChar(pTrimRight[-1])) 279 | pTrimRight--; 280 | 281 | // Perform memmove, if we trimmed something from the left 282 | if(pTrimLeft > m_pBuffer) 283 | memmove(m_pBuffer, pTrimLeft, (pTrimRight - pTrimLeft) * sizeof(TCHAR)); 284 | m_pBuffer[pTrimRight - pTrimLeft] = 0; 285 | m_pBufferPtr = m_pBuffer + (pTrimRight - pTrimLeft); 286 | } 287 | 288 | 289 | void TrimSpaces() 290 | { 291 | TrimLeftAndRight(IsSpace); 292 | } 293 | 294 | bool CutLastChar() 295 | { 296 | if(m_pBufferPtr > m_pBuffer) 297 | { 298 | m_pBufferPtr--; 299 | return true; 300 | } 301 | return false; 302 | } 303 | 304 | // Initializes the string a-new 305 | void Init() 306 | { 307 | // Set the string to the static array 308 | m_pBuffer = m_StaticBuff; 309 | m_pBufferPtr = m_pBuffer; 310 | m_pBufferEnd = m_pBuffer + _countof(m_StaticBuff) - 1; 311 | m_nCharSize = sizeof(XCHAR); 312 | 313 | // Terminate the string with zero 314 | m_StaticBuff[0] = 0; 315 | } 316 | 317 | // Sets the string to have zero length. Also makes it zero terminated. 318 | void Reset() 319 | { 320 | m_pBufferPtr = m_pBuffer; 321 | m_pBuffer[0] = 0; 322 | } 323 | 324 | // Returns the buffer as string. Ensures that it's zero terminated. 325 | LPCXSTR GetStr() 326 | { 327 | m_pBufferPtr[0] = 0; 328 | return m_pBuffer; 329 | } 330 | 331 | // Very fast conversion from LPCWSTR. If XCHAR == WCHAR 332 | // the function just returns the original pointer 333 | LPCXSTR GetLPCXSTR(LPCWSTR szStringW) 334 | { 335 | // Must be non-NULL and non-empty 336 | if(szStringW != NULL) 337 | { 338 | // Conversion from LPCWSTR to LPCSTR? 339 | if(m_nCharSize == sizeof(CHAR)) 340 | { 341 | InitFromLPCWSTR(szStringW); 342 | return GetStr(); 343 | } 344 | else 345 | { 346 | return (LPCXSTR)(szStringW); 347 | } 348 | } 349 | return NULL; 350 | } 351 | 352 | // Very fast conversion from LPCSTR. If XCHAR == CHAR, 353 | // the function just returns the original pointer 354 | LPCXSTR GetLPCXSTR(LPCSTR szStringA) 355 | { 356 | // Must be non-NULL and non-empty 357 | if(szStringA != NULL) 358 | { 359 | // Conversion from LPCSTR to LPCWSTR? 360 | if(m_nCharSize == sizeof(WCHAR)) 361 | { 362 | InitFromLPCSTR(szStringA); 363 | return GetStr(); 364 | } 365 | else 366 | { 367 | return (LPCXSTR)(szStringA); 368 | } 369 | } 370 | return NULL; 371 | } 372 | 373 | LPCXSTR GetBuffer() const 374 | { 375 | return m_pBuffer; 376 | } 377 | 378 | bool SetLength(size_t nLength) 379 | { 380 | // Make sure there is enough space in the bufer 381 | if(nLength > (size_t)(m_pBufferEnd - m_pBuffer)) 382 | { 383 | if(!EnsureSpace(nLength - Length())) 384 | { 385 | return false; 386 | } 387 | } 388 | 389 | // Adjust pointers 390 | assert((m_pBuffer + nLength) < m_pBufferEnd); 391 | m_pBufferPtr = m_pBuffer + nLength; 392 | return true; 393 | } 394 | 395 | size_t Length() const 396 | { 397 | return m_pBufferPtr - m_pBuffer; 398 | } 399 | 400 | bool IsEmpty() const 401 | { 402 | return (m_pBufferPtr == m_pBuffer); 403 | } 404 | 405 | operator LPCXSTR() 406 | { 407 | return GetStr(); 408 | } 409 | 410 | XCHAR operator[](size_t nIndex) const 411 | { 412 | if((m_pBuffer + nIndex) > m_pBufferPtr) 413 | return 0; 414 | return m_pBuffer[nIndex]; 415 | } 416 | 417 | protected: 418 | 419 | bool EnsureSpace(size_t nReserve) 420 | { 421 | // Would we go beyond the buffer if we added that number of chars? 422 | if((m_pBufferPtr + nReserve) > m_pBufferEnd) 423 | { 424 | size_t nMaxLength = (m_pBufferEnd - m_pBuffer); 425 | size_t nLength = (m_pBufferPtr - m_pBuffer); 426 | 427 | // Calculate new needed size 428 | while ((nLength + nReserve) > nMaxLength) 429 | nMaxLength <<= 1; 430 | 431 | // Allocate new buffer 432 | if(m_pBuffer == m_StaticBuff) 433 | { 434 | // First reallocation: Allocate brand new. 435 | m_pBuffer = (LPXSTR)HeapAlloc(g_hHeap, 0, ((nMaxLength + 1) * sizeof(XCHAR))); 436 | if(m_pBuffer == NULL) 437 | { 438 | SetLastError(ERROR_NOT_ENOUGH_MEMORY); 439 | return false; 440 | } 441 | 442 | memcpy(m_pBuffer, m_StaticBuff, nLength * sizeof(XCHAR)); 443 | } 444 | 445 | // Reallocate old buffer 446 | else 447 | { 448 | // Second reallocation: Use HeapReAlloc 449 | LPXSTR pNewBuffer = (LPXSTR)HeapReAlloc(g_hHeap, 0, m_pBuffer, ((nMaxLength + 1) * sizeof(XCHAR))); 450 | 451 | // Failed - the old buffer is still allocated 452 | if(pNewBuffer == NULL) 453 | { 454 | HeapFree(g_hHeap, 0, m_pBuffer); 455 | SetLastError(ERROR_NOT_ENOUGH_MEMORY); 456 | return false; 457 | } 458 | 459 | // Remember the new buffer 460 | m_pBuffer = pNewBuffer; 461 | } 462 | 463 | // Adjust buffers 464 | m_pBufferEnd = m_pBuffer + nMaxLength; 465 | m_pBufferPtr = m_pBuffer + nLength; 466 | } 467 | 468 | return true; 469 | } 470 | 471 | LPXSTR m_pBuffer; // Pointer to the begin of the buffer 472 | LPXSTR m_pBufferPtr; // Pointer to the current position in the buffer 473 | LPXSTR m_pBufferEnd; // Pointer to the end of the buffer. There is always 1 extra character! 474 | size_t m_nCharSize; // sizeof(XCHAR) 475 | XCHAR m_StaticBuff[0x80]; // For shorter strings, we use static buffer 476 | }; 477 | 478 | //----------------------------------------------------------------------------- 479 | // Convertor from UNICODE string to ANSI string 480 | 481 | struct TAnsiString : public TFastString 482 | { 483 | TAnsiString() 484 | {} 485 | 486 | TAnsiString(LPCSTR szString) 487 | { 488 | InitFromLPCSTR(szString); 489 | } 490 | 491 | TAnsiString(LPCWSTR szString) 492 | { 493 | InitFromLPCWSTR(szString); 494 | } 495 | }; 496 | 497 | //----------------------------------------------------------------------------- 498 | // Convertor from ANSI string to UNICODE string 499 | 500 | struct TWideString : public TFastString 501 | { 502 | TWideString() 503 | {} 504 | 505 | TWideString(LPCSTR szString) 506 | { 507 | InitFromLPCSTR(szString); 508 | } 509 | 510 | TWideString(LPCWSTR szString) 511 | { 512 | InitFromLPCWSTR(szString); 513 | } 514 | }; 515 | 516 | #endif // __TFASTSTRING_H__ 517 | --------------------------------------------------------------------------------