Files
ladislav-zezula-FileTest/WinMain.cpp
T
2021-04-25 21:51:38 +02:00

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;
}