mirror of
https://github.com/ladislav-zezula/FileTest
synced 2026-06-08 15:24:12 +00:00
289 lines
9.4 KiB
C++
289 lines
9.4 KiB
C++
/*****************************************************************************/
|
|
/* WinMain.cpp Copyright (c) Ladislav Zezula 2003 */
|
|
/*---------------------------------------------------------------------------*/
|
|
/* A file that simulates access on a file */
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Date Ver Who Comment */
|
|
/* -------- ---- --- ------- */
|
|
/* 14.07.03 1.00 Lad The first version of WinMain.cpp */
|
|
/*****************************************************************************/
|
|
|
|
#include "FileTest.h"
|
|
#include "resource.h"
|
|
|
|
#pragma comment(lib, "Comctl32.lib")
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Global variables
|
|
|
|
TContextMenu g_ContextMenus[MAX_CONTEXT_MENUS];
|
|
TToolTip g_Tooltip;
|
|
DWORD g_dwWinVer;
|
|
DWORD g_dwWinBuild;
|
|
TCHAR g_szInitialDirectory[MAX_PATH];
|
|
DWORD g_dwMenuCount = 0;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Local functions
|
|
|
|
inline bool IsCommandSwitch(LPCTSTR szArg)
|
|
{
|
|
return (szArg[0] == _T('/') || szArg[0] == _T('-'));
|
|
}
|
|
|
|
static void SetTokenObjectIntegrityLevel(DWORD dwIntegrityLevel)
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY Sia = SECURITY_MANDATORY_LABEL_AUTHORITY;
|
|
SECURITY_DESCRIPTOR sd;
|
|
HANDLE hToken;
|
|
DWORD dwLength;
|
|
PACL pAcl;
|
|
PSID pSid;
|
|
|
|
// Do nothing on OSes where mandatory ACEs are not supported
|
|
if(pfnAddMandatoryAce == NULL)
|
|
return;
|
|
|
|
// Initialize blank security descriptor
|
|
if(!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
|
|
return;
|
|
|
|
// Allocate mandatory label SID
|
|
if(!AllocateAndInitializeSid(&Sia, 1, dwIntegrityLevel, 0, 0, 0, 0, 0, 0, 0, &pSid))
|
|
return;
|
|
|
|
// Open current token
|
|
if(!OpenThreadToken(GetCurrentThread(), WRITE_OWNER, TRUE, &hToken))
|
|
{
|
|
if(GetLastError() == ERROR_NO_TOKEN)
|
|
OpenProcessToken(GetCurrentProcess(), WRITE_OWNER, &hToken);
|
|
}
|
|
|
|
// If succeeded, set the integrity level
|
|
if(hToken != NULL)
|
|
{
|
|
// Create ACL
|
|
dwLength = sizeof(ACL) + sizeof(SYSTEM_MANDATORY_LABEL_ACE) - sizeof(DWORD) + GetLengthSid(pSid);
|
|
pAcl = (PACL)HeapAlloc(g_hHeap, 0, dwLength);
|
|
if(pAcl != NULL)
|
|
{
|
|
if(InitializeAcl(pAcl, dwLength, ACL_REVISION))
|
|
{
|
|
if(pfnAddMandatoryAce(pAcl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, pSid))
|
|
{
|
|
NtSetSecurityObject(hToken, LABEL_SECURITY_INFORMATION, &sd);
|
|
}
|
|
}
|
|
|
|
HeapFree(g_hHeap, 0, pAcl);
|
|
}
|
|
}
|
|
|
|
FreeSid(pSid);
|
|
}
|
|
|
|
BOOL CALLBACK EnumMenusProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR /* lParam */)
|
|
{
|
|
// Only take menus
|
|
if(lpszType == RT_MENU)
|
|
{
|
|
// Debug code check
|
|
assert(g_dwMenuCount < MAX_CONTEXT_MENUS);
|
|
|
|
// Check if the number of context menus is in range
|
|
if(g_dwMenuCount < MAX_CONTEXT_MENUS)
|
|
{
|
|
// Insert the menu entry
|
|
g_ContextMenus[g_dwMenuCount].szMenuName = lpszName;
|
|
g_ContextMenus[g_dwMenuCount].hMenu = LoadMenu(hModule, lpszName);
|
|
|
|
// Increment the menu count
|
|
g_dwMenuCount++;
|
|
}
|
|
}
|
|
|
|
// Keep enumerating
|
|
return TRUE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// WinMain
|
|
|
|
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int)
|
|
{
|
|
TFileTestData * pData;
|
|
DWORD dwDesiredAccess = GENERIC_READ;
|
|
DWORD dwShareAccess = FILE_SHARE_READ;
|
|
DWORD dwCreateOptions = 0;
|
|
DWORD dwCopyFileFlags = 0;
|
|
DWORD dwMoveFileFlags = 0;
|
|
bool bAsynchronousOpen = false;
|
|
int nFileNameIndex = 0;
|
|
|
|
// Initialize the instance
|
|
InitInstance(hInstance);
|
|
InitCommonControls();
|
|
|
|
// Get the Windows version
|
|
g_dwWinVer = GetWindowsVersion();
|
|
|
|
// Allocate and fill our working structure with command line parameters
|
|
pData = (TFileTestData *)HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, sizeof(TFileTestData));
|
|
|
|
// Parse command line arguments
|
|
for(int i = 1; i < __argc; i++)
|
|
{
|
|
// If the argument a file name?
|
|
if(!IsCommandSwitch(__targv[i]))
|
|
{
|
|
switch(nFileNameIndex)
|
|
{
|
|
case 0: // The first file name argument
|
|
StringCchCopy(pData->szFileName1, _countof(pData->szFileName1), __targv[i]);
|
|
nFileNameIndex++;
|
|
break;
|
|
|
|
case 1: // The second file name argument
|
|
StringCchCopy(pData->szFileName2, _countof(pData->szFileName2), __targv[i]);
|
|
nFileNameIndex++;
|
|
break;
|
|
|
|
case 2: // The directory file name argument
|
|
StringCchCopy(pData->szDirName, _countof(pData->szFileName2), __targv[i]);
|
|
nFileNameIndex++;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LPCTSTR szArg = __targv[i] + 1;
|
|
|
|
// Check for default read+write access
|
|
if(!_tcsnicmp(szArg, _T("DesiredAccess:"), 14))
|
|
Text2Hex32(szArg+14, &dwDesiredAccess);
|
|
|
|
// Check for default share read+write
|
|
if(!_tcsnicmp(szArg, _T("ShareAccess:"), 12))
|
|
Text2Hex32(szArg+12, &dwShareAccess);
|
|
|
|
// Check for changed create options
|
|
if(!_tcsnicmp(szArg, _T("CreateOptions:"), 14))
|
|
Text2Hex32(szArg+14, &dwCreateOptions);
|
|
|
|
if(!_tcsnicmp(szArg, _T("CopyFileFlags:"), 14))
|
|
Text2Hex32(szArg+14, &dwCopyFileFlags);
|
|
|
|
if(!_tcsnicmp(szArg, _T("MoveFileFlags:"), 14))
|
|
Text2Hex32(szArg+14, &dwMoveFileFlags);
|
|
|
|
// Check for asynchronous open
|
|
if(!_tcsicmp(szArg, _T("AsyncOpen")))
|
|
bAsynchronousOpen = true;
|
|
}
|
|
}
|
|
|
|
// Set default file name
|
|
if(pData->szFileName1[0] == 0)
|
|
{
|
|
StringCchCopy(pData->szFileName1, _countof(pData->szFileName1), _T("C:\\TestFile.bin"));
|
|
pData->IsDefaultFileName1 = TRUE;
|
|
}
|
|
|
|
//
|
|
// DEVELOPMENT CODE: Build the NT status table from the NTSTATUS.h
|
|
//
|
|
|
|
// BuildNtStatusTableFromNTSTATUS_H();
|
|
// VerifyNtStatusTable();
|
|
|
|
//
|
|
// Resolve the dynamic loaded APIs
|
|
//
|
|
|
|
ResolveDynamicLoadedAPIs();
|
|
|
|
//
|
|
// On Vista or newer, set the required integrity level of our token object
|
|
// to lowest possible value. This will allow us to open our token even if the user
|
|
// lowers the integrity level.
|
|
//
|
|
|
|
SetTokenObjectIntegrityLevel(SECURITY_MANDATORY_UNTRUSTED_RID);
|
|
|
|
//
|
|
// Save the application initial directory
|
|
//
|
|
|
|
GetCurrentDirectory(_countof(g_szInitialDirectory), g_szInitialDirectory);
|
|
|
|
//
|
|
// Register the data editor window
|
|
//
|
|
|
|
RegisterDataEditor(hInstance);
|
|
|
|
//
|
|
// To make handles obtained by NtCreateFile usable for calling ReadFile and WriteFile,
|
|
// we have to set the FILE_SYNCHRONOUS_IO_NONALERT into CreateOptions
|
|
// and SYNCHRONIZE into DesiredAccess.
|
|
//
|
|
|
|
// Pre-load menus so they don't generate any FS requests when loaded
|
|
memset(g_ContextMenus, 0, sizeof(g_ContextMenus));
|
|
EnumResourceNames(g_hInst, RT_MENU, EnumMenusProc, NULL);
|
|
|
|
// Set default values for opening relative file by NtOpenFile
|
|
pData->dwDesiredAccessRF = FILE_READ_DATA;
|
|
pData->dwOpenOptionsRF = 0;
|
|
pData->dwShareAccessRF = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
|
|
|
// Set default values for CreateFile and NtCreateFile
|
|
pData->dwCreateDisposition1 = OPEN_ALWAYS;
|
|
pData->dwCreateDisposition2 = FILE_OPEN_IF;
|
|
pData->dwDesiredAccess = dwDesiredAccess;
|
|
pData->dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
|
|
pData->dwShareAccess = dwShareAccess;
|
|
pData->dwCreateOptions = dwCreateOptions;
|
|
pData->dwObjAttrFlags = OBJ_CASE_INSENSITIVE;
|
|
pData->dwMoveFileFlags = MOVEFILE_COPY_ALLOWED;
|
|
pData->dwOplockLevel = OPLOCK_LEVEL_CACHE_READ | OPLOCK_LEVEL_CACHE_WRITE;
|
|
pData->dwCopyFileFlags = dwCopyFileFlags;
|
|
pData->dwMoveFileFlags = dwMoveFileFlags;
|
|
|
|
// Modify for synchronous open, if required
|
|
if(bAsynchronousOpen == false)
|
|
{
|
|
pData->dwCreateOptions |= FILE_SYNCHRONOUS_IO_NONALERT;
|
|
pData->dwDesiredAccess |= SYNCHRONIZE;
|
|
}
|
|
|
|
// Set default values for NtCreateSection/NtOpenSection
|
|
pData->dwSectDesiredAccess = SECTION_MAP_READ;
|
|
pData->dwSectPageProtection = PAGE_READONLY;
|
|
pData->dwSectAllocAttributes = SEC_COMMIT;
|
|
pData->dwSectWin32Protect = PAGE_READONLY;
|
|
|
|
#ifdef _DEBUG
|
|
DebugCode_TEST();
|
|
#endif
|
|
|
|
// Call the dialog
|
|
FileTestDialog(NULL, pData);
|
|
|
|
// Free the data blobs
|
|
pData->NtInfoData.Free();
|
|
pData->RdWrData.Free();
|
|
pData->OutData.Free();
|
|
pData->InData.Free();
|
|
|
|
// Cleanup the TFileTestData structure and exit
|
|
if(pData->pFileEa != NULL)
|
|
delete [] pData->pFileEa;
|
|
HeapFree(g_hHeap, 0, pData);
|
|
|
|
UnloadDynamicLoadedAPIs();
|
|
return 0;
|
|
}
|
|
|
|
|