├── .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 | 
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 |
--------------------------------------------------------------------------------