mirror of
https://github.com/ladislav-zezula/FileTest
synced 2026-06-08 15:24:12 +00:00
595 lines
20 KiB
C++
595 lines
20 KiB
C++
/*****************************************************************************/
|
|
/* Page11Ioctl.cpp Copyright (c) Ladislav Zezula 2019 */
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Description : */
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Date Ver Who Comment */
|
|
/* -------- ---- --- ------- */
|
|
/* 23.01.19 1.00 Lad The first version of Page12Ioctl.cpp */
|
|
/*****************************************************************************/
|
|
|
|
#include "FileTest.h"
|
|
#include "resource.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Local structures
|
|
|
|
#define WM_COMBO_CHANGED (WM_USER + 0x1000)
|
|
|
|
struct TIoctlInfo
|
|
{
|
|
LPCTSTR szName;
|
|
ULONG IoctlCode;
|
|
ULONG InBufferSize;
|
|
ULONG OutBufferSize;
|
|
};
|
|
|
|
typedef NTSTATUS (NTAPI * NT_IOCTL_API)(
|
|
IN HANDLE FileHandle,
|
|
IN HANDLE Event,
|
|
IN PIO_APC_ROUTINE ApcRoutine,
|
|
IN PVOID ApcContext,
|
|
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
|
IN ULONG IoControlCode,
|
|
IN PVOID InputBuffer,
|
|
IN ULONG InputBufferLength,
|
|
IN PVOID OutputBuffer,
|
|
IN ULONG OutputBufferLength
|
|
);
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Local variables
|
|
|
|
static TIoctlInfo IoctlInfoList[] =
|
|
{
|
|
{ _T("FSCTL_SET_SPARSE"), FSCTL_SET_SPARSE, 0, 0 },
|
|
{ _T("FSCTL_GET_COMPRESSION"), FSCTL_GET_COMPRESSION, 0, sizeof(USHORT) },
|
|
{ _T("FSCTL_SET_COMPRESSION"), FSCTL_SET_COMPRESSION, sizeof(USHORT), 0 },
|
|
};
|
|
|
|
static TAnchors * pAnchors = NULL;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Conversion of IOCTL device name to text
|
|
|
|
static LPCTSTR IoctlDeviceTypeNames[] =
|
|
{
|
|
_T("FILE_DEVICE_0"),
|
|
_T("FILE_DEVICE_BEEP"),
|
|
_T("FILE_DEVICE_CD_ROM"),
|
|
_T("FILE_DEVICE_CD_ROM_FILE_SYSTEM"),
|
|
_T("FILE_DEVICE_CONTROLLER"),
|
|
_T("FILE_DEVICE_DATALINK"),
|
|
_T("FILE_DEVICE_DFS"),
|
|
_T("FILE_DEVICE_DISK"),
|
|
_T("FILE_DEVICE_DISK_FILE_SYSTEM"),
|
|
_T("FILE_DEVICE_FILE_SYSTEM"),
|
|
_T("FILE_DEVICE_INPORT_PORT"),
|
|
_T("FILE_DEVICE_KEYBOARD"),
|
|
_T("FILE_DEVICE_MAILSLOT"),
|
|
_T("FILE_DEVICE_MIDI_IN"),
|
|
_T("FILE_DEVICE_MIDI_OUT"),
|
|
_T("FILE_DEVICE_MOUSE"),
|
|
_T("FILE_DEVICE_MULTI_UNC_PROVIDER"),
|
|
_T("FILE_DEVICE_NAMED_PIPE"),
|
|
_T("FILE_DEVICE_NETWORK"),
|
|
_T("FILE_DEVICE_NETWORK_BROWSER"),
|
|
_T("FILE_DEVICE_NETWORK_FILE_SYSTEM"),
|
|
_T("FILE_DEVICE_NULL"),
|
|
_T("FILE_DEVICE_PARALLEL_PORT"),
|
|
_T("FILE_DEVICE_PHYSICAL_NETCARD"),
|
|
_T("FILE_DEVICE_PRINTER"),
|
|
_T("FILE_DEVICE_SCANNER"),
|
|
_T("FILE_DEVICE_SERIAL_MOUSE_PORT"),
|
|
_T("FILE_DEVICE_SERIAL_PORT"),
|
|
_T("FILE_DEVICE_SCREEN"),
|
|
_T("FILE_DEVICE_SOUND"),
|
|
_T("FILE_DEVICE_STREAMS"),
|
|
_T("FILE_DEVICE_TAPE"),
|
|
_T("FILE_DEVICE_TAPE_FILE_SYSTEM"),
|
|
_T("FILE_DEVICE_TRANSPORT"),
|
|
_T("FILE_DEVICE_UNKNOWN"),
|
|
_T("FILE_DEVICE_VIDEO"),
|
|
_T("FILE_DEVICE_VIRTUAL_DISK"),
|
|
_T("FILE_DEVICE_WAVE_IN"),
|
|
_T("FILE_DEVICE_WAVE_OUT"),
|
|
_T("FILE_DEVICE_8042_PORT"),
|
|
_T("FILE_DEVICE_NETWORK_REDIRECTOR"),
|
|
_T("FILE_DEVICE_BATTERY"),
|
|
_T("FILE_DEVICE_BUS_EXTENDER"),
|
|
_T("FILE_DEVICE_MODEM"),
|
|
_T("FILE_DEVICE_VDM"),
|
|
_T("FILE_DEVICE_MASS_STORAGE"),
|
|
_T("FILE_DEVICE_SMB"),
|
|
_T("FILE_DEVICE_KS"),
|
|
_T("FILE_DEVICE_CHANGER"),
|
|
_T("FILE_DEVICE_SMARTCARD"),
|
|
_T("FILE_DEVICE_ACPI"),
|
|
_T("FILE_DEVICE_DVD"),
|
|
_T("FILE_DEVICE_FULLSCREEN_VIDEO"),
|
|
_T("FILE_DEVICE_DFS_FILE_SYSTEM"),
|
|
_T("FILE_DEVICE_DFS_VOLUME"),
|
|
_T("FILE_DEVICE_SERENUM"),
|
|
_T("FILE_DEVICE_TERMSRV"),
|
|
_T("FILE_DEVICE_KSEC"),
|
|
_T("FILE_DEVICE_FIPS"),
|
|
_T("FILE_DEVICE_INFINIBAND"),
|
|
_T("FILE_DEVICE_3C"),
|
|
_T("FILE_DEVICE_3D"),
|
|
_T("FILE_DEVICE_VMBUS"),
|
|
_T("FILE_DEVICE_CRYPT_PROVIDER"),
|
|
_T("FILE_DEVICE_WPD"),
|
|
_T("FILE_DEVICE_BLUETOOTH"),
|
|
_T("FILE_DEVICE_MT_COMPOSITE"),
|
|
_T("FILE_DEVICE_MT_TRANSPORT"),
|
|
_T("FILE_DEVICE_BIOMETRIC"),
|
|
_T("FILE_DEVICE_PMI")
|
|
};
|
|
|
|
static LPCTSTR GetIoctlDeviceType(DWORD dwIoctlCode)
|
|
{
|
|
static TCHAR szDeviceType[128];
|
|
DWORD dwDeviceType = DEVICE_TYPE_FROM_CTL_CODE(dwIoctlCode);
|
|
|
|
if(dwDeviceType <= _countof(IoctlDeviceTypeNames))
|
|
return IoctlDeviceTypeNames[dwDeviceType];
|
|
|
|
StringCchPrintf(szDeviceType, _countof(szDeviceType), _T("0x%X"), dwDeviceType);
|
|
return szDeviceType;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Conversion of IOCTL method to text
|
|
|
|
static LPCTSTR IoctlMethodNames[] =
|
|
{
|
|
_T("METHOD_BUFFERED"),
|
|
_T("METHOD_IN_DIRECT"),
|
|
_T("METHOD_OUT_DIRECT"),
|
|
_T("METHOD_NEITHER"),
|
|
};
|
|
|
|
LPCTSTR GetIoctlMethod(DWORD dwIoctlCode)
|
|
{
|
|
return IoctlMethodNames[METHOD_FROM_CTL_CODE(dwIoctlCode)];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Conversion of IOCTL code to access name
|
|
|
|
static LPCTSTR IoctlAccessNames[] =
|
|
{
|
|
_T("FILE_ANY_ACCESS"),
|
|
_T("FILE_READ_ACCESS"),
|
|
_T("FILE_WRITE_ACCESS"),
|
|
_T("FILE_READ_ACCESS | FILE_WRITE_ACCESS"),
|
|
};
|
|
|
|
LPCTSTR GetIoctlAccess(DWORD dwIoctlCode)
|
|
{
|
|
return IoctlAccessNames[(dwIoctlCode >> 14) & 0x0003];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Helper functions
|
|
|
|
static void CompleteAsynchronousOperation(HWND hDlg, TApcEntry * pApc, DWORD dwErrCode, DWORD dwTransferred)
|
|
{
|
|
TFileTestData * pData = GetDialogData(hDlg);
|
|
HWND hWndEditor;
|
|
|
|
// Convert the error code and number of bytes transferred
|
|
if(pApc->bAsynchronousCompletion)
|
|
{
|
|
if(pApc->bHasIoStatus == false)
|
|
{
|
|
if(!GetOverlappedResult(pData->hFile, &pApc->Overlapped, &dwTransferred, TRUE))
|
|
dwErrCode = GetLastError();
|
|
else
|
|
dwErrCode = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
// If the operation has succeeded, update few UI elements
|
|
if(dwErrCode == ERROR_SUCCESS)
|
|
{
|
|
// If we have an output buffer, copy it to the data buffer
|
|
if(pApc->BufferLength)
|
|
{
|
|
// Copy the data buffer from the APC to our user buffer
|
|
pData->OutData.SetLength(pApc->BufferLength);
|
|
memcpy(pData->OutData.pbData, (pApc + 1), pData->OutData.cbData);
|
|
|
|
hWndEditor = GetDlgItem(hDlg, IDC_OUTPUT_DATA);
|
|
DataEditor_SetData(hWndEditor, 0, pData->OutData.pbData, pData->OutData.cbData);
|
|
}
|
|
}
|
|
|
|
// Set the information about the operation
|
|
if(pApc->bHasIoStatus)
|
|
SetResultInfo(hDlg, RSI_NTSTATUS | RSI_INFORMATION, pApc->IoStatus.Status, &pApc->IoStatus);
|
|
else
|
|
SetResultInfo(hDlg, RSI_LAST_ERROR | RSI_INFO_INT32, dwErrCode, dwTransferred);
|
|
|
|
// Free the APC entry
|
|
FreeApcEntry(pApc);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Local functions
|
|
|
|
static void AddAnchorData(HWND hDlg, TAnchors * pAnc, UINT nIDFrame, UINT nIDLabel, UINT nIDLength, UINT nIDSpin, UINT nIDData)
|
|
{
|
|
pAnc->AddAnchor(hDlg, nIDFrame, akLeft | akRight | akBottom);
|
|
pAnc->AddAnchor(hDlg, nIDLabel, akLeft | akRight | akBottom);
|
|
pAnc->AddAnchor(hDlg, nIDLength, akLeft | akRight | akBottom);
|
|
pAnc->AddAnchor(hDlg, nIDSpin, akRight | akBottom);
|
|
pAnc->AddAnchor(hDlg, nIDData, akLeft | akRight | akBottom);
|
|
}
|
|
|
|
static void InitializeData(HWND hDlg, UINT nIDLength, UINT nIDData)
|
|
{
|
|
HWND hWndChild;
|
|
|
|
// Set the length of the data
|
|
Hex2DlgText32(hDlg, nIDLength, 0);
|
|
|
|
if((hWndChild = GetDlgItem(hDlg, nIDData)) != NULL)
|
|
{
|
|
DataEditor_SetDataFormat(hWndChild, PtrPointer32Bit, 0x08);
|
|
DataEditor_SetData(hWndChild, 0, NULL, 0);
|
|
}
|
|
}
|
|
|
|
static void UpdateIoctlData(HWND hDlg, UINT nIDLength)
|
|
{
|
|
TFileTestData * pData = GetDialogData(hDlg);
|
|
TDataBlob * pDataBlob = NULL;
|
|
HWND hWndChild = NULL;
|
|
BOOL bTranslated = FALSE;
|
|
UINT dwValue;
|
|
|
|
// The dialog must be initialized
|
|
if(pData != NULL)
|
|
{
|
|
// Translate the text value into a number
|
|
dwValue = GetDlgItemInt(hDlg, nIDLength, &bTranslated, FALSE);
|
|
if(bTranslated)
|
|
{
|
|
// Retrieve the data editor handle
|
|
if(nIDLength == IDC_INPUT_DATA_LENGTH)
|
|
{
|
|
hWndChild = GetDlgItem(hDlg, IDC_INPUT_DATA);
|
|
pDataBlob = &pData->InData;
|
|
}
|
|
if(nIDLength == IDC_OUTPUT_DATA_LENGTH)
|
|
{
|
|
hWndChild = GetDlgItem(hDlg, IDC_OUTPUT_DATA);
|
|
pDataBlob = &pData->OutData;
|
|
}
|
|
|
|
// If both controls exist, update them
|
|
if(pDataBlob != NULL && hWndChild != NULL)
|
|
{
|
|
// Set the data size and the data itself
|
|
pDataBlob->SetLength(dwValue);
|
|
DataEditor_SetData(hWndChild, 0, pDataBlob->pbData, pDataBlob->cbData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Message handlers
|
|
|
|
static int OnInitDialog(HWND hDlg, LPARAM lParam)
|
|
{
|
|
PROPSHEETPAGE * pPage = (PROPSHEETPAGE *)lParam;
|
|
TFileTestData * pData = (TFileTestData *)pPage->lParam;
|
|
HWND hWndChild;
|
|
int nIndex;
|
|
|
|
// Save the data pointer into the dialog
|
|
SetDialogData(hDlg, pPage->lParam);
|
|
|
|
// Configure dialog resizing
|
|
if(pData->bEnableResizing)
|
|
{
|
|
if((pAnchors = new TAnchors(hDlg)) != NULL)
|
|
{
|
|
pAnchors->AddAnchor(hDlg, IDC_IOCTL_REQUEST_FRAME, akAll);
|
|
pAnchors->AddAnchor(hDlg, IDC_IOCTL_CODE, akLeft | akTop | akRight);
|
|
pAnchors->AddAnchor(hDlg, IDC_IOCTL_CODE_DECODED_TITLE, akLeft | akTop | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_IOCTL_CODE_DECODED, akAll);
|
|
|
|
AddAnchorData(hDlg, pAnchors, IDC_INPUT_DATA_FRAME, IDC_INPUT_DATA_HINT, IDC_INPUT_DATA_LENGTH, IDC_INPUT_DATA_SPIN, IDC_INPUT_DATA);
|
|
AddAnchorData(hDlg, pAnchors, IDC_OUTPUT_DATA_FRAME, IDC_OUTPUT_DATA_HINT, IDC_OUTPUT_DATA_LENGTH, IDC_OUTPUT_DATA_SPIN, IDC_OUTPUT_DATA);
|
|
|
|
pAnchors->AddAnchor(hDlg, IDC_DEVICE_IO_CONTROL1, akLeft | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_DEVICE_IO_CONTROL2, akLeftCenter | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_DEVICE_IO_CONTROL3, akRight | akBottom);
|
|
|
|
pAnchors->AddAnchor(hDlg, IDC_RESULT_FRAME, akLeft | akRight | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_ERROR_CODE_TITLE, akLeft | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_ERROR_CODE, akLeft | akRight | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_INFORMATION_TITLE, akLeft | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_INFORMATION, akLeft | akRight | akBottom);
|
|
}
|
|
}
|
|
|
|
// Configure input data
|
|
InitializeData(hDlg, IDC_INPUT_DATA_LENGTH, IDC_INPUT_DATA);
|
|
InitializeData(hDlg, IDC_OUTPUT_DATA_LENGTH, IDC_OUTPUT_DATA);
|
|
|
|
// Initialize combo box with the IOCTL list
|
|
if((hWndChild = GetDlgItem(hDlg, IDC_IOCTL_CODE)) != NULL)
|
|
{
|
|
for (size_t i = 0; i < _countof(IoctlInfoList); i++)
|
|
{
|
|
nIndex = ComboBox_AddString(hWndChild, IoctlInfoList[i].szName);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnSetActive(HWND hDlg)
|
|
{
|
|
TFileTestData * pData = GetDialogData(hDlg);
|
|
BOOL bEnabled = (IsHandleValid(pData->hFile)) ? TRUE : FALSE;
|
|
|
|
// Enable/disable the buttons
|
|
EnableDlgItems(hDlg, bEnabled, IDC_DEVICE_IO_CONTROL1, IDC_DEVICE_IO_CONTROL2, IDC_DEVICE_IO_CONTROL3, 0);
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnDeltaPos(HWND hDlg, NMUPDOWN * pNMUpDown, UINT nIDLength)
|
|
{
|
|
HWND hWndChild;
|
|
DWORD dwValue = 0;
|
|
|
|
if((hWndChild = GetDlgItem(hDlg, nIDLength)) != NULL)
|
|
{
|
|
// Change the value
|
|
DlgText2Hex32(hDlg, nIDLength, &dwValue);
|
|
dwValue -= pNMUpDown->iDelta;
|
|
if(dwValue & 0x80000000)
|
|
dwValue = 0;
|
|
Hex2DlgText32(hDlg, nIDLength, dwValue);
|
|
|
|
// Update the data
|
|
UpdateIoctlData(hDlg, nIDLength);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnDeltaPos(HWND hDlg, NMUPDOWN * pNMUpDown)
|
|
{
|
|
if(pNMUpDown->hdr.idFrom == IDC_INPUT_DATA_SPIN)
|
|
return OnDeltaPos(hDlg, pNMUpDown, IDC_INPUT_DATA_LENGTH);
|
|
if(pNMUpDown->hdr.idFrom == IDC_OUTPUT_DATA_SPIN)
|
|
return OnDeltaPos(hDlg, pNMUpDown, IDC_OUTPUT_DATA_LENGTH);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void OnComboBoxEditChange(HWND hDlg)
|
|
{
|
|
DWORD dwIoctlCode;
|
|
|
|
if(DlgText2Hex32(hDlg, IDC_IOCTL_CODE, &dwIoctlCode) == ERROR_SUCCESS)
|
|
{
|
|
LPCTSTR szDeviceType = GetIoctlDeviceType(dwIoctlCode);
|
|
LPCTSTR szMethod = GetIoctlMethod(dwIoctlCode);
|
|
LPCTSTR szAccess = GetIoctlAccess(dwIoctlCode);
|
|
DWORD dwFunction = (dwIoctlCode >> 2) & 0xFFF;
|
|
TCHAR szText[0x100];
|
|
|
|
// Get the device type
|
|
rsprintf(szText, _countof(szText), IDS_IOCTL_FORMAT, szDeviceType, dwFunction, szMethod, szAccess);
|
|
SetDlgItemText(hDlg, IDC_IOCTL_CODE_DECODED, szText);
|
|
}
|
|
}
|
|
|
|
static void OnComboBoxSelChanged(HWND hDlg)
|
|
{
|
|
TIoctlInfo * pIoctlInfo;
|
|
HWND hWndChild;
|
|
int nIndex;
|
|
|
|
if((hWndChild = GetDlgItem(hDlg, IDC_IOCTL_CODE)) != NULL)
|
|
{
|
|
if((nIndex = ComboBox_GetCurSel(hWndChild)) != CB_ERR)
|
|
{
|
|
if(nIndex < _countof(IoctlInfoList))
|
|
{
|
|
// Get the IOCTL info
|
|
pIoctlInfo = &IoctlInfoList[nIndex];
|
|
|
|
// Change the combo box's value
|
|
Hex2DlgText32(hDlg, IDC_IOCTL_CODE, pIoctlInfo->IoctlCode);
|
|
OnComboBoxEditChange(hDlg);
|
|
|
|
// Set the input data length
|
|
Hex2DlgText32(hDlg, IDC_INPUT_DATA_LENGTH, pIoctlInfo->InBufferSize);
|
|
Hex2DlgText32(hDlg, IDC_OUTPUT_DATA_LENGTH, pIoctlInfo->OutBufferSize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void OnIoctlClick(HWND hDlg, UINT nIDCtrl)
|
|
{
|
|
TFileTestData * pData = GetDialogData(hDlg);
|
|
NT_IOCTL_API NtIoControlApi;
|
|
TApcEntry * pApc;
|
|
NTSTATUS Status;
|
|
LPBYTE OutputBuffer = NULL;
|
|
LPBYTE InputBuffer = NULL;
|
|
ULONG OutputLength = 0;
|
|
ULONG InputLength = 0;
|
|
ULONG IoctlCode = 0;
|
|
DWORD dwTransferred = 0;
|
|
DWORD dwErrCode = ERROR_SUCCESS;
|
|
|
|
// Get the lengths
|
|
DlgText2Hex32(hDlg, IDC_OUTPUT_DATA_LENGTH, &OutputLength);
|
|
assert(pData->OutData.cbData == OutputLength);
|
|
DlgText2Hex32(hDlg, IDC_INPUT_DATA_LENGTH, &InputLength);
|
|
assert(pData->InData.cbData == InputLength);
|
|
DlgText2Hex32(hDlg, IDC_IOCTL_CODE, &IoctlCode);
|
|
assert(IoctlCode != 0);
|
|
|
|
// Create new APC entry
|
|
pApc = CreateApcEntry(pData, APC_TYPE_IOCTL, OutputLength);
|
|
if(pApc != NULL)
|
|
{
|
|
// Configure the APC
|
|
if((pApc->BufferLength = OutputLength) != 0)
|
|
OutputBuffer = (LPBYTE)(pApc + 1);
|
|
if(InputLength != 0)
|
|
InputBuffer = pData->InData.pbData;
|
|
|
|
// Perform function-specific call
|
|
switch (nIDCtrl)
|
|
{
|
|
case IDC_DEVICE_IO_CONTROL1:
|
|
|
|
if(!DeviceIoControl(pData->hFile,
|
|
IoctlCode,
|
|
InputBuffer,
|
|
InputLength,
|
|
OutputBuffer,
|
|
OutputLength,
|
|
&dwTransferred,
|
|
&pApc->Overlapped))
|
|
{
|
|
dwErrCode = GetLastError();
|
|
}
|
|
|
|
if(dwErrCode == ERROR_IO_PENDING)
|
|
{
|
|
SetResultInfo(hDlg, RSI_LAST_ERROR | RSI_INFO_INT32, ERROR_IO_PENDING, 0);
|
|
InsertApcEntry(pData, pApc);
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case IDC_DEVICE_IO_CONTROL2:
|
|
case IDC_DEVICE_IO_CONTROL3:
|
|
|
|
// Configure the APC
|
|
NtIoControlApi = (nIDCtrl == IDC_DEVICE_IO_CONTROL2) ? NtDeviceIoControlFile : NtFsControlFile;
|
|
pApc->bHasIoStatus = TRUE;
|
|
|
|
// Call the appropriate API
|
|
Status = NtIoControlApi(pData->hFile,
|
|
pApc->hEvent,
|
|
NULL,
|
|
NULL,
|
|
&pApc->IoStatus,
|
|
IoctlCode,
|
|
InputBuffer,
|
|
InputLength,
|
|
OutputBuffer,
|
|
OutputLength);
|
|
|
|
// If the read operation ended with STATUS_PENDING, queue the APC
|
|
if(Status == STATUS_PENDING)
|
|
{
|
|
SetResultInfo(hDlg, RSI_NTSTATUS | RSI_INFORMATION, STATUS_PENDING, &pApc->IoStatus);
|
|
InsertApcEntry(pData, pApc);
|
|
return;
|
|
}
|
|
|
|
pApc->IoStatus.Status = Status;
|
|
break;
|
|
}
|
|
|
|
// Complete the read/write operation
|
|
CompleteAsynchronousOperation(hDlg, pApc, dwErrCode, dwTransferred);
|
|
}
|
|
else
|
|
{
|
|
SetResultInfo(hDlg, RSI_LAST_ERROR | RSI_NOINFO, GetLastError());
|
|
}
|
|
}
|
|
|
|
static int OnCommand(HWND hDlg, UINT nNotify, UINT nIDCtrl)
|
|
{
|
|
switch (nNotify)
|
|
{
|
|
case EN_CHANGE:
|
|
UpdateIoctlData(hDlg, nIDCtrl);
|
|
return FALSE;
|
|
|
|
case CBN_SELENDOK: // Can't change combo box's text right now, need to postpone
|
|
PostMessage(hDlg, WM_COMBO_CHANGED, 0, 0);
|
|
return FALSE;
|
|
|
|
case CBN_EDITCHANGE:
|
|
OnComboBoxEditChange(hDlg);
|
|
return FALSE;
|
|
|
|
case BN_CLICKED:
|
|
if(nIDCtrl == IDC_DEVICE_IO_CONTROL1 || nIDCtrl == IDC_DEVICE_IO_CONTROL2 || nIDCtrl == IDC_DEVICE_IO_CONTROL3)
|
|
OnIoctlClick(hDlg, nIDCtrl);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnNotify(HWND hDlg, NMHDR * pNMHDR)
|
|
{
|
|
switch(pNMHDR->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
return OnSetActive(hDlg);
|
|
|
|
case UDN_DELTAPOS:
|
|
return OnDeltaPos(hDlg, (NMUPDOWN *)pNMHDR);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Public functions
|
|
|
|
INT_PTR CALLBACK PageProc12(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
// Handlers specific to our dialog
|
|
switch(uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
OnInitDialog(hDlg, lParam);
|
|
return TRUE;
|
|
|
|
case WM_SIZE:
|
|
case WM_GETMINMAXINFO:
|
|
return pAnchors->OnMessage(uMsg, wParam, lParam);
|
|
|
|
case WM_COMBO_CHANGED:
|
|
OnComboBoxSelChanged(hDlg);
|
|
return FALSE;
|
|
|
|
case WM_APC:
|
|
CompleteAsynchronousOperation(hDlg, (TApcEntry *)lParam, 0, 0);
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
return OnCommand(hDlg, HIWORD(wParam), LOWORD(wParam));
|
|
|
|
case WM_NOTIFY:
|
|
return OnNotify(hDlg, (NMHDR *)lParam);
|
|
|
|
case WM_DESTROY:
|
|
if(pAnchors != NULL)
|
|
delete pAnchors;
|
|
pAnchors = NULL;
|
|
return FALSE;
|
|
}
|
|
return FALSE;
|
|
}
|