static int OnDeleteFileClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); int nError = ERROR_SUCCESS; // Save the dialog variables SaveDialog(hDlg); // Choose what exactly to do switch(FileActionDialog(hDlg)) { case IDC_SIMPLE_DELETE: if(!DeleteFile(pData->szFileName1)) nError = GetLastError(); break; case IDC_FORCED_DELETE: nError = ForceRemoveFile(pData->szFileName1); break; default: return TRUE; } UpdateDialogButtons(hDlg); SetResultInfo(hDlg, nError); return TRUE; }
static int OnApc(HWND hDlg, LPARAM lParam) { TWindowData * pData = GetDialogData(hDlg); TApcEntry * pApc = (TApcEntry *)lParam; // Perform APC-specific action if(pApc->ApcType == APC_TYPE_FSCTL) { // Show the result in the result UI SetResultInfo(hDlg, pApc->IoStatus.Status); // If the APC was an oplock APC, also show the result switch(pApc->UserParam) { case FSCTL_REQUEST_OPLOCK_LEVEL_1: case FSCTL_REQUEST_OPLOCK_LEVEL_2: case FSCTL_REQUEST_BATCH_OPLOCK: case FSCTL_REQUEST_FILTER_OPLOCK: OnCompleteOplockApc(pData, pApc); break; case FSCTL_REQUEST_OPLOCK: OnCompleteOplockApc_Win7(pData, pApc); break; } } return TRUE; }
static int OnDeleteDirectoryClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); int nError = ERROR_SUCCESS; // Save the dialog variables SaveDialog(hDlg); // Choose what exactly to do switch(DirectoryActionDialog(hDlg)) { case IDC_SINGLE_DIRECTORY: if(!RemoveDirectory(pData->szFileName1)) nError = GetLastError(); break; case IDC_DIRECTORY_TREE: nError = RemoveDirectoryTree(pData->szFileName1); break; default: return TRUE; } SetResultInfo(hDlg, nError); return TRUE; }
static int OnGetFileAttributes(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); TFlagInfo * pFlags = FileAttributesValues; TCHAR szFileAttributes[512] = _T(""); DWORD dwAttr; int nError = ERROR_SUCCESS; SaveDialog(hDlg); dwAttr = GetFileAttributes(pData->szFileName1); if(dwAttr != INVALID_FILE_ATTRIBUTES) { for(int i = 0; pFlags->dwValue != 0; i++, pFlags++) { if(IS_FLAG_SET(pFlags, dwAttr)) { if(szFileAttributes[0] != 0) StringCchCat(szFileAttributes, _countof(szFileAttributes), _T("\n")); StringCchCat(szFileAttributes, _countof(szFileAttributes), pFlags->szFlagText); } } if(szFileAttributes[0] == 0) StringCchCopy(szFileAttributes, _countof(szFileAttributes), _T("0")); MessageBoxRc(hDlg, IDS_FILE_ATTRIBUTES, (UINT_PTR)szFileAttributes); } else nError = GetLastError(); SetResultInfo(hDlg, nError); return TRUE; }
static void CompleteReadWriteOperation(HWND hDlg, TApcReadWrite * pApc, int nError, DWORD dwTransferred) { HWND hWndEditor; // Set the information about the operation SetResultInfo(hDlg, nError, NULL, dwTransferred); // If the operation has succeeded, update few UI elements if(nError == ERROR_SUCCESS) { // If the "increase position" is checked, increment the byte position if(pApc->bIncrementPosition) { pApc->ByteOffset.QuadPart += dwTransferred; Hex2DlgText64(hDlg, IDC_BYTE_OFFSET, pApc->ByteOffset.QuadPart); } // If we shall update the data view, do it if(pApc->bUpdateData) { hWndEditor = GetDlgItem(hDlg, IDC_FILE_DATA); InvalidateRect(hWndEditor, NULL, TRUE); } } }
static int OnUnmapViewClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); NTSTATUS Status; // Get the base address where it is mapped if(SaveDialog2(hDlg) == ERROR_SUCCESS) { // Unmap the view from the base address Status = NtUnmapViewOfSection(NtCurrentProcess(), pData->pvSectionMappedView); // Clear the base address, so the next click on "MapView" will succeed Hex2DlgTextPtr(hDlg, IDC_BASE_ADDRESS, NULL); pData->pvSectionMappedView = NULL; // Clear the view size, so the next click on "MapView" will succeed Hex2DlgTextPtr(hDlg, IDC_VIEW_SIZE, 0); pData->cbSectViewSize = 0; // Show the result SetResultInfo(hDlg, Status, pData->hSection); UpdateDialog(hDlg, pData); } return TRUE; }
static int OnMakeDirectoryClick(HWND hDlg) { OBJECT_ATTRIBUTES ObjAttr; IO_STATUS_BLOCK IoStatus = {0, 0}; UNICODE_STRING FileName; TFileTestData * pData = GetDialogData(hDlg); NTSTATUS Status = STATUS_SUCCESS; LPTSTR szDirectory = pData->szDirName; LPTSTR szPathPart = pData->szDirName; LPTSTR szTemp; USHORT SaveLength; // Get the values from dialog controls to the dialog data if(SaveDialog(hDlg) != ERROR_SUCCESS) return FALSE; // Initialize object attributes and the unicode string InitializeObjectAttributes(&ObjAttr, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL); RtlInitUnicodeString(&FileName, pData->szDirName); SaveLength = FileName.Length; // Now parse the directory as-is, create every sub-directory if(szDirectory[0] != 0) { // Now find the begin of the first directory part szPathPart = FindDirectoryPathPart(szDirectory); if(szPathPart != NULL) { while(szPathPart[0] != 0) { // Find either next backslash or end of string szTemp = FindNextPathSeparator(szPathPart); // Create the directory part FileName.Length = (USHORT)((szTemp - szDirectory) * sizeof(WCHAR)); Status = MyCreateDirectory(pData, &ObjAttr, &IoStatus); if(!NT_SUCCESS(Status)) break; // Go to the next part of the path FileName.Length = SaveLength; szPathPart = szTemp; } } else { Status = MyCreateDirectory(pData, &ObjAttr, &IoStatus); } } else { Status = MyCreateDirectory(pData, &ObjAttr, &IoStatus); } SetResultInfo(hDlg, Status, NULL, IoStatus.Information); return TRUE; }
static int OnSetEndOfFileClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); int nError = ERROR_SUCCESS; if(!SetEndOfFile(pData->hFile)) nError = GetLastError(); SetResultInfo(hDlg, nError); return TRUE; }
static int OnFlushFile(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); int nError = ERROR_SUCCESS; if(!FlushFileBuffers(pData->hFile)) nError = GetLastError(); SetResultInfo(hDlg, nError); return TRUE; }
static int OnNtCreateSectionClick(HWND hDlg, UINT nIDCtrl) { TFileTestData * pData = GetDialogData(hDlg); POBJECT_ATTRIBUTES pObjectAttributes = NULL; OBJECT_ATTRIBUTES ObjAttr; UNICODE_STRING SectionName; NTSTATUS Status; HANDLE FileHandle = NULL; // Close the section, if already open if(IsHandleValid(pData->hSection)) OnNtCloseClick(hDlg); // Get the values from dialog controls to the dialog data if(SaveDialog1(hDlg) != ERROR_SUCCESS) return FALSE; // Format the object attributes if(pData->szSectionName[0] != 0) { InitializeObjectAttributes(&ObjAttr, &SectionName, OBJ_CASE_INSENSITIVE, NULL, NULL); RtlInitUnicodeString(&SectionName, pData->szSectionName); pObjectAttributes = &ObjAttr; } // Get the file handle for it if(IsHandleValid(pData->hFile)) FileHandle = pData->hFile; // Either create a section or open one if(nIDCtrl == IDC_NTCREATE_SECTION) { Status = NtCreateSection(&pData->hSection, pData->dwSectDesiredAccess, pObjectAttributes, &pData->MaximumSize, pData->dwSectPageProtection, pData->dwSectAllocAttributes, FileHandle); } else { Status = NtOpenSection(&pData->hSection, pData->dwSectDesiredAccess, pObjectAttributes); } // Set the result info SetResultInfo(hDlg, Status, pData->hSection); UpdateDialog(hDlg, pData); return TRUE; }
static int OnMapViewClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); LARGE_INTEGER SectionOffset; NTSTATUS Status; SIZE_T ViewSize; PVOID BaseAddress; // If we have mapped view, unmap it now if(pData->bSectionViewMapped) OnUnmapViewClick(hDlg); // Get the values from dialog controls to the dialog data if(SaveDialog2(hDlg) != ERROR_SUCCESS) return FALSE; // Copy some values to stack SectionOffset.QuadPart = pData->SectionOffset.QuadPart; BaseAddress = pData->pvSectionMappedView; ViewSize = pData->cbSectViewSize; // Call the NtMapViewOfSection Status = NtMapViewOfSection(pData->hSection, NtCurrentProcess(), &BaseAddress, 0, pData->cbSectCommitSize, &SectionOffset, &ViewSize, ViewShare, pData->dwSectAllocType, pData->dwSectWin32Protect); if(NT_SUCCESS(Status)) { // If the section offset changed, set it to the dialog control if(SectionOffset.QuadPart != pData->SectionOffset.QuadPart) Hex2DlgText64(hDlg, IDC_SECTION_OFFSET, SectionOffset.QuadPart); if(BaseAddress != pData->pvSectionMappedView) Hex2DlgTextPtr(hDlg, IDC_BASE_ADDRESS, (ULONG_PTR)BaseAddress); if(ViewSize != pData->cbSectViewSize) Hex2DlgTextPtr(hDlg, IDC_VIEW_SIZE, ViewSize); // Remember the view pData->pvSectionMappedView = BaseAddress; pData->cbSectViewSize = ViewSize; pData->bSectionViewMapped = TRUE; } SetResultInfo(hDlg, Status, pData->hSection); UpdateDialog(hDlg, pData); return TRUE; }
static int OnSendAsynchronousFsctl( HWND hDlg, ULONG IoctlCode, PVOID InputBuffer = NULL, ULONG InputBufferSize = 0, PVOID OutputBuffer = NULL, ULONG OutputBufferSize = 0) { TFileTestData * pData = GetDialogData(hDlg); TApcEntry * pApc; NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; // Create new APC entry pApc = (TApcEntry *)CreateApcEntry(pData, APC_TYPE_FSCTL, sizeof(TApcEntry) + OutputBufferSize); if(pApc != NULL) { // If there's an output buffer, move it to the APC structure if(OutputBuffer && OutputBufferSize) { memcpy(pApc + 1, OutputBuffer, OutputBufferSize); OutputBuffer = (pApc + 1); } // Send the FSCTL Status = NtFsControlFile(pData->hFile, pApc->hEvent, NULL, NULL, &pApc->IoStatus, IoctlCode, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize); // If the IOCTL returned STATUS_PENDING, it means that the oplock is active. // If the oplock breaks, the event becomes signalled, and we get the APC message if(Status == STATUS_PENDING) { pApc->UserParam = IoctlCode; InsertApcEntry(pData, pApc); } else { FreeApcEntry(pApc); } } SetResultInfo(hDlg, RtlNtStatusToDosError(Status)); return TRUE; }
static int OnMakeDirectoryClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); LPTSTR szDirectory = pData->szDirName; LPTSTR szPathPart = pData->szDirName; LPTSTR szTemp; TCHAR chSaveChar; int nError = ERROR_SUCCESS; // Get the values from dialog controls to the dialog data if(SaveDialog(hDlg) != ERROR_SUCCESS) return FALSE; // Now parse the directory as-is, create every sub-directory if(szDirectory[0] != 0) { // Now find the begin of the first directory part szPathPart = FindDirectoryPathPart(szDirectory); if(szPathPart != NULL) { while(szPathPart[0] != 0) { // Find either next backslash or end of string szTemp = FindNextPathSeparator(szPathPart); // Create the directory part chSaveChar = szTemp[0]; szTemp[0] = 0; nError = MyCreateDirectory(pData, szDirectory); if(nError != ERROR_SUCCESS) break; // Go to the next part of the path szPathPart = szTemp; szTemp[0] = chSaveChar; } } else { nError = MyCreateDirectory(pData, szDirectory); } } else { nError = MyCreateDirectory(pData, szDirectory); } SetResultInfo(hDlg, nError, pData->hFile); return TRUE; }
static int OnGetFileSizeClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); LARGE_INTEGER FileSize = {0}; int nError = ERROR_SUCCESS; // Get the file size SetLastError(ERROR_SUCCESS); FileSize.LowPart = GetFileSize(pData->hFile, (LPDWORD)&FileSize.HighPart); nError = GetLastError(); SetResultInfo(hDlg, nError, NULL, 0, &FileSize); return TRUE; }
static int OnMoveFileClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); int nError = ERROR_SUCCESS; SaveDialog(hDlg); // Perform the rename if(!MoveFileEx(pData->szFileName1, pData->szFileName2, pData->dwMoveFileFlags)) nError = GetLastError(); // Set the result SetResultInfo(hDlg, nError); return TRUE; }
static int OnNtCloseClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); NTSTATUS Status = STATUS_SUCCESS; // Close the handle if(IsHandleValid(pData->hSection)) Status = NtClose(pData->hSection); pData->hSection = NULL; // Set the result info SetResultInfo(hDlg, Status, pData->hSection); UpdateDialog(hDlg, pData); return TRUE; }
static int OnCopyFileClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); int nError; // Get the source and target file GetDlgItemText(hDlg, IDC_FILE_NAME1, pData->szFileName1, _maxchars(pData->szFileName1)); GetDlgItemText(hDlg, IDC_FILE_NAME2, pData->szFileName2, _maxchars(pData->szFileName2)); // Run the copy file dialog nError = (int)CopyFileDialog(hDlg, pData); // Set the result SetResultInfo(hDlg, nError); return TRUE; }
static int OnSetFilePointerClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); LARGE_INTEGER ByteOffset; int nError = ERROR_SUCCESS; // Get the file offset from the dialog DlgText2Hex64(hDlg, IDC_BYTE_OFFSET, &ByteOffset.QuadPart); // Apply the file size SetLastError(ERROR_SUCCESS); SetFilePointer(pData->hFile, ByteOffset.LowPart, &ByteOffset.HighPart, FILE_BEGIN); nError = GetLastError(); SetResultInfo(hDlg, nError); return TRUE; }
static int OnNtQueryAttributesFile(HWND hDlg) { FILE_BASIC_INFORMATION BasicInfo; OBJECT_ATTRIBUTES ObjAttr; TFileTestData * pData = GetDialogData(hDlg); UNICODE_STRING FileName = {0, 0, NULL}; NTSTATUS Status; TCHAR szMsgText[512] = _T(""); // Save the current state of the dialog SaveDialog(hDlg); // Retrieve the NT name of the file InitializeObjectAttributes(&ObjAttr, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = FileNameToUnicodeString(&FileName, pData->szFileName1); // Query the attributes if(NT_SUCCESS(Status)) { Status = NtQueryAttributesFile(&ObjAttr, &BasicInfo); if(NT_SUCCESS(Status)) { StringCchPrintf(szMsgText, _countof(szMsgText), _T("CreationTime: %08X-%08X\n") _T("LastAccessTime: %08X-%08X\n") _T("LastWriteTime: %08X-%08X\n") _T("ChangeTime: %08X-%08X\n") _T("FileAttributes: %08X"), BasicInfo.CreationTime.HighPart, BasicInfo.CreationTime.LowPart, BasicInfo.LastAccessTime.HighPart, BasicInfo.LastAccessTime.LowPart, BasicInfo.LastWriteTime.HighPart, BasicInfo.LastWriteTime.LowPart, BasicInfo.ChangeTime.HighPart, BasicInfo.ChangeTime.LowPart, BasicInfo.FileAttributes); MessageBoxRc(hDlg, IDS_FILE_BASIC_INFORMATION, (UINT_PTR)szMsgText); } } // Set the result information SetResultInfo(hDlg, Status); FreeFileNameString(&FileName); return TRUE; }
static int OnNtCloseClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); NTSTATUS Status = STATUS_SUCCESS; // Invoke breakpoint if the user wants to if(IsDlgButtonChecked(hDlg, IDC_BREAKPOINT) == BST_CHECKED) DebugBreak(); // Close file handle first if(IsHandleValid(pData->hFile)) Status = NtClose(pData->hFile); pData->hFile = NULL; // Close directory handle last if(IsHandleValid(pData->hDirectory)) NtClose(pData->hDirectory); pData->hDirectory = NULL; SetResultInfo(hDlg, Status, NULL, 0xFFFFFFFF); return TRUE; }
static int OnCloseHandleClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); int nError = ERROR_SUCCESS; if(IsHandleValid(pData->hFile)) { // If directory has been changed, set it back to initial if(pData->szDirName[0] != 0) SetCurrentDirectory(g_szInitialDirectory); // Invoke breakpoint if the user wants to if(IsDlgButtonChecked(hDlg, IDC_BREAKPOINT) == BST_CHECKED) DebugBreak(); if(!CloseHandle(pData->hFile)) nError = GetLastError(); } pData->hFile = NULL; SetResultInfo(hDlg, nError, pData->hFile); return TRUE; }
// Querying the file ID from the file itself static int OnFileIdGetClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); OBJECT_ATTRIBUTES ObjAttr; IO_STATUS_BLOCK IoStatus; UNICODE_STRING FolderName = {0, 0, NULL}; UNICODE_STRING FileName = {0, 0, NULL}; ULARGE_INTEGER FileId = {0}; NTSTATUS Status = STATUS_SUCCESS; HANDLE Handle = NULL; TCHAR szFileID[MAX_FILEID_PATH]; BYTE InfoBuff[0x200]; // Convert the file name to the NT file name if(NT_SUCCESS(Status)) { SaveDialog(hDlg); Status = FileNameToUnicodeString(&FolderName, pData->szFileName1); } // Get the directory name from the file name if(NT_SUCCESS(Status)) { PWSTR sz = FolderName.Buffer + (FolderName.Length / sizeof(WCHAR)); // Go back and find the last directory name while(sz > FolderName.Buffer && sz[0] != L'\\') sz--; // Did we find it? if(sz[0] == L'\\' && sz > FolderName.Buffer) { // Initialize the file name sz = sz + 1; RtlInitUnicodeString(&FileName, sz); // Cut the folder name. Make sure that the ending backslash is there, // because we don't want to open "\??\C:" instead of "\??\C:\" FolderName.MaximumLength = FolderName.Length = (USHORT)((sz - FolderName.Buffer) * sizeof(WCHAR)); // Attempt to open the folder and query the ID InitializeObjectAttributes(&ObjAttr, &FolderName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenFile(&Handle, FILE_READ_DATA | SYNCHRONIZE, &ObjAttr, &IoStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_ALERT); // If succeeded, we call for query directory on thet file if(NT_SUCCESS(Status)) { PFILE_ID_BOTH_DIR_INFORMATION pDirInfo = (PFILE_ID_BOTH_DIR_INFORMATION)InfoBuff; Status = NtQueryDirectoryFile(Handle, NULL, NULL, NULL, &IoStatus, pDirInfo, sizeof(InfoBuff), FileIdBothDirectoryInformation, TRUE, &FileName, FALSE); if(NT_SUCCESS(Status)) FileId.QuadPart = pDirInfo->FileId.QuadPart; NtClose(Handle); } } else { // Do it by Open - QueryID - Close InitializeObjectAttributes(&ObjAttr, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenFile(&Handle, FILE_READ_ATTRIBUTES, &ObjAttr, &IoStatus, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0); if(NT_SUCCESS(Status)) { PFILE_INTERNAL_INFORMATION pFileInfo = (PFILE_INTERNAL_INFORMATION)InfoBuff; Status = NtQueryInformationFile(Handle, &IoStatus, pFileInfo, sizeof(FILE_INTERNAL_INFORMATION), FileInternalInformation); if(NT_SUCCESS(Status)) FileId.QuadPart = pFileInfo->IndexNumber.QuadPart; NtClose(Handle); } } } // Did we query the file ID just fine? if(NT_SUCCESS(Status)) { FileIDToString(pData, FileId.QuadPart, szFileID); SetDlgItemText(hDlg, IDC_FILE_ID, szFileID); } // On the end, set the file ID SetResultInfo(hDlg, RtlNtStatusToDosError(Status)); FreeFileNameString(&FolderName); return TRUE; }
static int OnCreateFileClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); OBJECT_ATTRIBUTES ObjAttr; IO_STATUS_BLOCK IoStatus; UNICODE_STRING FileName; UNICODE_STRING DirName; LARGE_INTEGER AllocationSize; NTSTATUS Status = STATUS_SUCCESS; HANDLE SaveTransactionHandle = NULL; TCHAR szFileName[MAX_NT_PATH]; TCHAR szDirName[MAX_NT_PATH]; DWORD cbObjectID = 0; BYTE ObjectID[0x10]; // Close the handle, if already open if(IsHandleValid(pData->hDirectory) || IsHandleValid(pData->hFile)) OnNtCloseClick(hDlg); // Get the various create options if(SaveDialog(hDlg) != ERROR_SUCCESS) return FALSE; if(pData->bUseTransaction && pfnRtlSetCurrentTransaction != NULL) { SaveTransactionHandle = pfnRtlGetCurrentTransaction(); pfnRtlSetCurrentTransaction(pData->hTransaction); } // Get the directory name from the dialog data StringCchCopy(szDirName, _countof(szDirName), pData->szDirName); StringCchCopy(szFileName, _countof(szFileName), pData->szFileName1); // If we are about to open a file by ID, and we have no relative directory, // try to take the directory from the file name if(szDirName[0] == 0 && (pData->dwCreateOptions & FILE_OPEN_BY_FILE_ID)) { LPTSTR szFullName = pData->szFileName1; LPTSTR szFileId = _tcsrchr(szFullName, _T('\\')); size_t nLength = szFileId - szFullName + 1; if(szFileId != NULL) { StringCchCopy(szDirName, nLength, szFullName); StringCchCopy(szFileName, _countof(szFileName), szFileId + 1); } } // Open the relative file (if any) if(szDirName[0] != 0) { RtlInitUnicodeString(&DirName, szDirName); InitializeObjectAttributes(&ObjAttr, &DirName, pData->dwObjAttrFlags, 0, NULL); Status = NtOpenFile(&pData->hDirectory, pData->dwDesiredAccessRF, &ObjAttr, &IoStatus, pData->dwShareAccessRF, pData->dwOpenOptionsRF); if(!NT_SUCCESS(Status)) { SetResultInfo(hDlg, Status, NULL, IoStatus.Information); return TRUE; } } // Prepare the file open if(NT_SUCCESS(Status)) { RtlInitUnicodeString(&FileName, szFileName); // If open by ID required, set the ID to the string if(pData->dwCreateOptions & FILE_OPEN_BY_FILE_ID) { // Convert object ID to binary value if(StringToFileID(szFileName, NULL, ObjectID, &cbObjectID) != ERROR_SUCCESS) return TRUE; // Set the object ID to the UNICODE_STRING FileName.MaximumLength = FileName.Length = (USHORT)cbObjectID; FileName.Buffer = (PWSTR)ObjectID; } ZeroMemory(&IoStatus, sizeof(IO_STATUS_BLOCK)); InitializeObjectAttributes(&ObjAttr, &FileName, pData->dwObjAttrFlags, pData->hDirectory, NULL); AllocationSize.QuadPart = (LONGLONG)pData->AllocationSize; // Invoke breakpoint if the user wants to if(IsDlgButtonChecked(hDlg, IDC_BREAKPOINT) == BST_CHECKED) DebugBreak(); Status = NtCreateFile(&pData->hFile, pData->dwDesiredAccess, &ObjAttr, &IoStatus, &AllocationSize, pData->dwFileAttributes, pData->dwShareAccess, pData->dwCreateDisposition2, pData->dwCreateOptions, pData->pFileEa, pData->dwEaSize); SetResultInfo(hDlg, Status, pData->hFile, IoStatus.Information); // If this operation failed, we close the directory as well if(!NT_SUCCESS(Status) && pData->hDirectory != NULL) { NtClose(pData->hDirectory); pData->hDirectory = NULL; } } if(pData->bUseTransaction && pfnRtlSetCurrentTransaction != NULL) { pfnRtlSetCurrentTransaction(SaveTransactionHandle); SaveTransactionHandle = NULL; } return TRUE; }
static int OnLockUnlockFile(HWND hDlg, int nReadWriteType) { TFileTestData * pData = GetDialogData(hDlg); TApcReadWrite * pApc; LARGE_INTEGER ByteOffset = {0}; LARGE_INTEGER LockLength = {0}; NTSTATUS Status; int nError = ERROR_SUCCESS; // Get the start position DlgText2Hex64(hDlg, IDC_BYTE_OFFSET, &ByteOffset.QuadPart); DlgText2Hex32(hDlg, IDC_LENGTH, &LockLength.LowPart); assert((LONGLONG)pData->cbFileData >= LockLength.QuadPart); // Create new APC entry pApc = (TApcReadWrite *)CreateApcEntry(pData, APC_TYPE_READ_WRITE, sizeof(TApcReadWrite)); if(pApc != NULL) { // Perform the I/O operation switch(nReadWriteType) { case IDC_LOCK_FILE: // Perform the lock operation using LockFile if(!LockFile(pData->hFile, ByteOffset.LowPart, ByteOffset.HighPart, LockLength.LowPart, LockLength.HighPart)) nError = GetLastError(); break; case IDC_UNLOCK_FILE: // Perform the unlock operation using UnlockFile if(!UnlockFile(pData->hFile, ByteOffset.LowPart, ByteOffset.HighPart, LockLength.LowPart, LockLength.HighPart)) nError = GetLastError(); break; case IDC_NTLOCK_FILE: // Remember that this is a native call pApc->bNativeCall = false; // Perform the lock operation using NtLockFile Status = NtLockFile(pData->hFile, pApc->hEvent, NULL, NULL, &pApc->IoStatus, &ByteOffset, &LockLength, 0, TRUE, TRUE); // If the lock operation ended with STATUS_PENDING, queue the APC if(Status == STATUS_PENDING) { SetResultInfo(hDlg, ERROR_IO_PENDING); InsertApcEntry(pData, pApc); return TRUE; } // Save the error nError = RtlNtStatusToDosError(Status); break; case IDC_NTUNLOCK_FILE: // Perform the unlock operation using NtUnlockFile Status = NtUnlockFile(pData->hFile, &pApc->IoStatus, &ByteOffset, &LockLength, 0); // Save the error assert(Status != STATUS_PENDING); nError = RtlNtStatusToDosError(Status); break; } // Set the information about the operation SetResultInfo(hDlg, nError); FreeApcEntry(pApc); } else { SetResultInfo(hDlg, GetLastError()); } return TRUE; }
static int OnReadWriteFile(HWND hDlg, int nIDCtrl) { IO_STATUS_BLOCK IoStatus = {0}; TFileTestData * pData = GetDialogData(hDlg); TApcReadWrite * pApc; LARGE_INTEGER ByteOffset = {0}; NTREADWRITE NtReadWrite; READWRITE ReadWrite; NTSTATUS Status; DWORD dwTransferred = 0; DWORD Length = 0; int nError = ERROR_SUCCESS; // Get the start position DlgText2Hex64(hDlg, IDC_BYTE_OFFSET, &ByteOffset.QuadPart); DlgText2Hex32(hDlg, IDC_LENGTH, &Length); assert(pData->cbFileData >= Length); // Create new APC entry pApc = (TApcReadWrite *)CreateApcEntry(pData, APC_TYPE_READ_WRITE, sizeof(TApcReadWrite)); if(pApc != NULL) { // Remember the state of "Increment position" pApc->ByteOffset = ByteOffset; pApc->bIncrementPosition = (IsDlgButtonChecked(hDlg, IDC_INCREASE_FILEPOS) == BST_CHECKED); // Perform the appropriate API switch(nIDCtrl) { case IDC_READ_FILE: case IDC_WRITE_FILE: // Get the pointer to the appropriate API ReadWrite = (nIDCtrl == IDC_READ_FILE) ? ReadFile : (READWRITE)WriteFile; pApc->bUpdateData = (nIDCtrl == IDC_READ_FILE); pApc->bNativeCall = false; // Prepare the OVERLAPPED structure in the APC pApc->Overlapped.OffsetHigh = ByteOffset.HighPart; pApc->Overlapped.Offset = ByteOffset.LowPart; // Perform the read operation using ReadFile if(!ReadWrite(pData->hFile, pData->pbFileData, Length, &dwTransferred, &pApc->Overlapped)) nError = GetLastError(); // If the read operation ended with ERROR_IO_PENDING, queue the APC if(nError == ERROR_IO_PENDING) { SetResultInfo(hDlg, ERROR_IO_PENDING); InsertApcEntry(pData, pApc); return TRUE; } break; case IDC_NTREAD_FILE: case IDC_NTWRITE_FILE: // Get the pointer to the appropriate API NtReadWrite = (nIDCtrl == IDC_NTREAD_FILE) ? NtReadFile : NtWriteFile; pApc->bUpdateData = (nIDCtrl == IDC_NTREAD_FILE); pApc->bNativeCall = true; // Perform the read/write operation Status = NtReadWrite(pData->hFile, pApc->hEvent, NULL, NULL, &pApc->IoStatus, pData->pbFileData, Length, &ByteOffset, NULL); // If the read operation ended with STATUS_PENDING, queue the APC if(Status == STATUS_PENDING) { SetResultInfo(hDlg, ERROR_IO_PENDING); InsertApcEntry(pData, pApc); return TRUE; } // Fill the number of bytes transferred dwTransferred = (DWORD)IoStatus.Information; nError = RtlNtStatusToDosError(Status); break; } // Complete the read/write operation CompleteReadWriteOperation(hDlg, pApc, nError, dwTransferred); FreeApcEntry(pApc); } else { SetResultInfo(hDlg, GetLastError()); } return TRUE; }
static int OnObjectIdMoreClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); FILE_OBJECTID_BUFFER ObjId = {0}; UINT_PTR nAction; HANDLE hFile = INVALID_HANDLE_VALUE; TCHAR szObjectID[0x40]; DWORD dwFlagsAndAttributes = 0; DWORD dwDesiredAccess = FILE_READ_ATTRIBUTES; DWORD dwBytesReturned; DWORD dwIoctlCode = FSCTL_CREATE_OR_GET_OBJECT_ID; int nError = ERROR_SUCCESS; // Ask the user for the action nAction = ObjectIDActionDialog(hDlg); if(nAction == IDCANCEL) return TRUE; SaveDialog(hDlg); // Use the proper desired access // Note that we also need restore privilege in order to succeed if(nAction == IDC_SET_OBJECT_ID) { dwFlagsAndAttributes = FILE_FLAG_BACKUP_SEMANTICS; dwDesiredAccess = FILE_WRITE_DATA; } // Convert the file name to the NT file name hFile = CreateFile(pData->szFileName1, dwDesiredAccess, 0, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL); if(hFile == INVALID_HANDLE_VALUE) nError = GetLastError(); // Perform an action specific to if(nError == ERROR_SUCCESS) { switch(nAction) { case IDC_CREATE_OR_GET: case IDC_GET_OBJECT_ID: if(nAction == IDC_GET_OBJECT_ID) dwIoctlCode = FSCTL_GET_OBJECT_ID; memset(&ObjId, 0, sizeof(FILE_OBJECTID_BUFFER)); if(DeviceIoControl(hFile, dwIoctlCode, NULL, 0, &ObjId, sizeof(FILE_OBJECTID_BUFFER), &dwBytesReturned, NULL)) { ObjectIDToString(ObjId.ObjectId, pData->szFileName1, szObjectID); SetDlgItemText(hDlg, IDC_OBJECT_ID, szObjectID); } else { nError = GetLastError(); } break; case IDC_SET_OBJECT_ID: GetDlgItemText(hDlg, IDC_OBJECT_ID, szObjectID, _maxchars(szObjectID)); nError = StringToFileID(szObjectID, NULL, ObjId.ObjectId, NULL); if(nError != ERROR_SUCCESS) break; if(!DeviceIoControl(hFile, FSCTL_SET_OBJECT_ID, &ObjId, sizeof(FILE_OBJECTID_BUFFER), NULL, 0, &dwBytesReturned, NULL)) { nError = GetLastError(); } break; } } if(hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); SetResultInfo(hDlg, nError); return TRUE; }
static int OnCreateFileClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); HANDLE hTemplateFile = NULL; int nError = ERROR_SUCCESS; // Close the handle, if already open if(IsHandleValid(pData->hFile)) OnCloseHandleClick(hDlg); // Get the values from dialog controls to the dialog data if(SaveDialog(hDlg) != ERROR_SUCCESS) return FALSE; // Change the directory (If any) if(pData->szDirName[0] != 0) { if(!SetCurrentDirectory(pData->szDirName)) { nError = GetLastError(); SetResultInfo(hDlg, nError, INVALID_HANDLE_VALUE); return TRUE; } } // Prepare the template file if(nError == ERROR_SUCCESS && pData->szTemplate[0] != 0) { hTemplateFile = CreateFile(pData->szTemplate, FILE_READ_EA, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if(hTemplateFile == INVALID_HANDLE_VALUE) nError = GetLastError(); } // Prepare the file open if(nError == ERROR_SUCCESS) { if(pData->bUseTransaction == FALSE) { // Invoke breakpoint if the user wants to if(IsDlgButtonChecked(hDlg, IDC_BREAKPOINT) == BST_CHECKED) DebugBreak(); pData->hFile = CreateFile(pData->szFileName1, pData->dwDesiredAccess, pData->dwShareAccess, NULL, pData->dwCreateDisposition1, pData->dwFileAttributes, hTemplateFile); } else { // Invoke breakpoint if the user wants to if(IsDlgButtonChecked(hDlg, IDC_BREAKPOINT) == BST_CHECKED) DebugBreak(); pData->hFile = pfnCreateFileTransacted(pData->szFileName1, pData->dwDesiredAccess, pData->dwShareAccess, NULL, pData->dwCreateDisposition1, pData->dwFileAttributes, hTemplateFile, pData->hTransaction, NULL, NULL); } if(IsHandleInvalid(pData->hFile)) nError = GetLastError(); } if(IsHandleValid(hTemplateFile)) CloseHandle(hTemplateFile); SetResultInfo(hDlg, nError, pData->hFile); return TRUE; }