CreateFileA Visit a windows file system driver returned INVALID_HANDLE_VALUE - windows

I writed a file system demo most likely fast fat ,but when I use CreateFileA to call my dirver ,it gives an INVALID_HANDLE_VALUE result . I have checked the driver `s IRP dispatches and found no DbgPrint setting in the function entries triggered .
This is the user mode code:
public IntPtr LoadDriver(string lpFileName)
{
int error = 0;
string openName = string.Format("\\\\.\\{0}", EXE_DRIVER_NAME);
IntPtr hSCManager = WinAPI.OpenSCManager(null, null,
WinAPI.SC_MANAGER_CREATE_SERVICE);
if (IntPtr.Zero != hSCManager)
{
//创建服务
IntPtr hService = WinAPI.CreateService(hSCManager, EXE_DRIVER_NAME,
DISPLAY_NAME, WinAPI.SERVICE_START,
WinAPI.SERVICE_KERNEL_DRIVER, WinAPI.SERVICE_DEMAND_START,
WinAPI.SERVICE_ERROR_IGNORE, lpFileName, null, IntPtr.Zero, null, null, null);
if (WinAPI.ERROR_SERVICE_EXISTS == WinAPI.GetLastError())
{
hService = WinAPI.OpenService(hSCManager, EXE_DRIVER_NAME, WinAPI.SERVICE_START);
}
error = WinAPI.GetLastError();
if(error!=0)
{
dumpErrorCode("OpenService失败 ", error);
}
int startflag = WinAPI.StartService(hService, 0, 0);
if (startflag == 0)
{
error = WinAPI.GetLastError();
if (error != WinAPI.ERROR_SERVICE_ALREADY_RUNNING) //已经启动
{
dumpErrorCode("StartService失败", error);
}
else
{
MessageBox.Show("服务已经启动");
}
}
// WinAPI.CloseServiceHandle(hService);
// WinAPI.CloseServiceHandle(hSCManager);
MessageBox.Show(openName);
try
{
hDriver = WinAPI.CreateFileA(openName, WinAPI.GENERIC_READ , 0, IntPtr.Zero, WinAPI.OPEN_EXISTING, null, IntPtr.Zero);
if (hDriver == (IntPtr)(-1))
{
dumpErrorCode("获取文件句柄失败 ", error);
}
else
{
MessageBox.Show("成功创建驱动");
//his.OpenDriverEvent();
}
}
catch (Exception exp)
{
MessageBox.Show(exp.Message);
}
}
return hDriver;
}
This is the driver`s entry point code:
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
NTSTATUS Status;
UNICODE_STRING UnicodeString;
FS_FILTER_CALLBACKS FilterCallbacks;
UNREFERENCED_PARAMETER( RegistryPath );
DbgPrint("\nThis is HRFS Driver Entry\n");
RtlInitUnicodeString(&UnicodeString, L"\\fastFatDemo");
gSFilterDriverObject = DriverObject;
Status = IoCreateDevice( DriverObject,
0,
&UnicodeString,
FILE_DEVICE_DISK_FILE_SYSTEM,
0,
FALSE,
&HrfsDiskFileSystemDeviceObject );
if (!NT_SUCCESS( Status )) {
return Status;
}
DbgPrint("HRFS device HRFS created\n ");
DriverObject->DriverUnload = FatUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)FatFsdCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)HrfsFsdClose;
DriverObject->MajorFunction[IRP_MJ_READ] = (PDRIVER_DISPATCH)FatFsdRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = (PDRIVER_DISPATCH)FatFsdWrite;
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = (PDRIVER_DISPATCH)FatFsdQueryInformation;
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = (PDRIVER_DISPATCH)FatFsdSetInformation;
DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = (PDRIVER_DISPATCH)FatFsdQueryEa;
DriverObject->MajorFunction[IRP_MJ_SET_EA] = (PDRIVER_DISPATCH)FatFsdSetEa;
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = (PDRIVER_DISPATCH)FatFsdFlushBuffers;
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = (PDRIVER_DISPATCH)FatFsdQueryVolumeInformation;
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = (PDRIVER_DISPATCH)FatFsdSetVolumeInformation;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = (PDRIVER_DISPATCH)FatFsdCleanup;
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = (PDRIVER_DISPATCH)FatFsdDirectoryControl;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = (PDRIVER_DISPATCH)FatFsdFileSystemControl;
DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = (PDRIVER_DISPATCH)FatFsdLockControl;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)FatFsdDeviceControl;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = (PDRIVER_DISPATCH)FatFsdShutdown;
DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH)FatFsdPnp;
DbgPrint("HRFS device HRFS MajorFunction created\n ");
DriverObject->FastIoDispatch = NULL;
DbgPrint("HRFS device HRFS FatFastIoDispatch created\n ");
RtlZeroMemory(&FatFastIoDispatch, sizeof(FatFastIoDispatch));
FatFastIoDispatch.SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
FatFastIoDispatch.FastIoCheckIfPossible = FALSE; // CheckForFastIo
FatFastIoDispatch.FastIoRead = FALSE; // Read
FatFastIoDispatch.FastIoWrite = FALSE; // Write
FatFastIoDispatch.FastIoQueryBasicInfo = FALSE; // QueryBasicInfo
FatFastIoDispatch.FastIoQueryStandardInfo = FALSE; // QueryStandardInfo
FatFastIoDispatch.FastIoLock = FALSE; // Lock
FatFastIoDispatch.FastIoUnlockSingle = FALSE; // UnlockSingle
FatFastIoDispatch.FastIoUnlockAll = FALSE; // UnlockAll
FatFastIoDispatch.FastIoUnlockAllByKey = FALSE; // UnlockAllByKey
FatFastIoDispatch.FastIoQueryNetworkOpenInfo = FALSE;
FatFastIoDispatch.AcquireForCcFlush = FALSE;
FatFastIoDispatch.ReleaseForCcFlush = FALSE;
FatFastIoDispatch.MdlRead = FALSE;
FatFastIoDispatch.MdlReadComplete = FALSE;
FatFastIoDispatch.PrepareMdlWrite = FALSE;
FatFastIoDispatch.MdlWriteComplete = FALSE;
//FatFastIoDispatch.SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
//FatFastIoDispatch.FastIoCheckIfPossible = FatFastIoCheckIfPossible; // CheckForFastIo
//FatFastIoDispatch.FastIoRead = FsRtlCopyRead; // Read
//FatFastIoDispatch.FastIoWrite = FsRtlCopyWrite; // Write
//FatFastIoDispatch.FastIoQueryBasicInfo = FatFastQueryBasicInfo; // QueryBasicInfo
//FatFastIoDispatch.FastIoQueryStandardInfo = FatFastQueryStdInfo; // QueryStandardInfo
//FatFastIoDispatch.FastIoLock = FatFastLock; // Lock
//FatFastIoDispatch.FastIoUnlockSingle = FatFastUnlockSingle; // UnlockSingle
//FatFastIoDispatch.FastIoUnlockAll = FatFastUnlockAll; // UnlockAll
//FatFastIoDispatch.FastIoUnlockAllByKey = FatFastUnlockAllByKey; // UnlockAllByKey
//FatFastIoDispatch.FastIoQueryNetworkOpenInfo = FatFastQueryNetworkOpenInfo;
//FatFastIoDispatch.AcquireForCcFlush = HrfsAcquireForCcFlush;
//FatFastIoDispatch.ReleaseForCcFlush = HrfsReleaseForCcFlush;
//FatFastIoDispatch.MdlRead = FsRtlMdlReadDev;
//FatFastIoDispatch.MdlReadComplete = FsRtlMdlReadCompleteDev;
//FatFastIoDispatch.PrepareMdlWrite = FsRtlPrepareMdlWriteDev;
//FatFastIoDispatch.MdlWriteComplete = FsRtlMdlWriteCompleteDev;
/* FsFilter通知回调例程在下层文件系统执行某些操作之前或之后调用。
如果需要获取更多有关于FsFilter回调例程相关信息,可参见FsRtlRegisterFileSystemFilterCallbacks例程
为了注册FsFilter的通知回调例程必须分配并初始化FS_FILTER_CALLBACKS结构体,然后向该结构体中促出FsFilter回调例程,
并将存储有Callbacks parameter到FsRtlRegisterFileSystemFilterCallbacks中。*/
RtlZeroMemory( &FilterCallbacks,
sizeof(FS_FILTER_CALLBACKS) );
FilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS);
FilterCallbacks.PreAcquireForSectionSynchronization = HrfsFilterCallbackAcquireForCreateSection;
Status = FsRtlRegisterFileSystemFilterCallbacks( DriverObject,
&FilterCallbacks );
if (!NT_SUCCESS( Status )) {
IoDeleteDevice( HrfsDiskFileSystemDeviceObject );
return Status;
}
DbgPrint("HRFS device HRFS FilterCallbacks registed\n ");
RtlZeroMemory( &HrfsData, sizeof(FAT_DATA));
HrfsData.NodeTypeCode = HRFS_NTC_DATA_HEADER;
HrfsData.NodeByteSize = sizeof(FAT_DATA);
InitializeListHead(&HrfsData.VcbQueue);
pDriverObject = DriverObject;
HrfsData.DiskFileSystemDeviceObject = HrfsDiskFileSystemDeviceObject;
//
// This list head keeps track of closes yet to be done.
//
InitializeListHead( &HrfsData.AsyncCloseList );
InitializeListHead( &HrfsData.DelayedCloseList );
HrfsData.FatCloseItem = IoAllocateWorkItem( HrfsDiskFileSystemDeviceObject);
if (HrfsData.FatCloseItem == NULL) {
IoDeleteDevice (HrfsDiskFileSystemDeviceObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
DbgPrint("HRFS device HRFS workitem created\n ");
//
// Allocate the zero page
//
HrfsData.ZeroPage = ExAllocatePoolWithTag( NonPagedPoolNx, PAGE_SIZE, 'ZtaF' );
if (HrfsData.ZeroPage == NULL) {
IoDeleteDevice (HrfsDiskFileSystemDeviceObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory( HrfsData.ZeroPage, PAGE_SIZE );
//
// Now initialize our general purpose spinlock (gag) and figure out how
// deep and wide we want our delayed lists (along with fooling ourselves
// about the lookaside depths).
//
KeInitializeSpinLock( &HrfsData.GeneralSpinLock );
HrfsData.CacheManagerCallbacks.AcquireForLazyWrite = &HrfsAcquireFcbForLazyWrite;
HrfsData.CacheManagerCallbacks.ReleaseFromLazyWrite = &HrfsReleaseFcbFromLazyWrite;
HrfsData.CacheManagerCallbacks.AcquireForReadAhead = &HrfsAcquireFcbForReadAhead;
HrfsData.CacheManagerCallbacks.ReleaseFromReadAhead = &HrfsReleaseFcbFromReadAhead;
HrfsData.CacheManagerNoOpCallbacks.AcquireForLazyWrite = &HrfsNoOpAcquire;
HrfsData.CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = &HrfsNoOpRelease;
HrfsData.CacheManagerNoOpCallbacks.AcquireForReadAhead = &HrfsNoOpAcquire;
HrfsData.CacheManagerNoOpCallbacks.ReleaseFromReadAhead = &HrfsNoOpRelease;
//
// Set up global pointer to our process.
//
HrfsData.OurProcess = PsGetCurrentProcess();
DbgPrint("HRFS device HRFS our process getted\n ");
//
// Setup the number of processors we support for statistics as the current number
// running.
//
#if (NTDDI_VERSION >= NTDDI_VISTA)
HrfsData.NumberProcessors = KeQueryActiveProcessorCount( NULL );
#else
HrfsData.NumberProcessors = KeNumberProcessors;
#endif
DbgPrint("HrfsData.NumberProcessors :%d", HrfsData.NumberProcessors);
ExInitializeResourceLite( &HrfsData.Resource );
IoRegisterFileSystem(HrfsDiskFileSystemDeviceObject);
ObReferenceObject (HrfsDiskFileSystemDeviceObject);
DbgPrint("Device HRFS HrfsDiskFileSystemDeviceObject registed\n ");
return( STATUS_SUCCESS );
}

Related

How to get windows folder display order by C + +

I need to get the pictures in the windows folder and sort them according to the order in which they are displayed. Now there is a method to traverse the entire folder display items through the handle by getting the folder window handle. However, this method has a drawback: it can't get the order of the unopened folder, because there is no open file and no window handle.
Qt is used.
Please forgive my grammatical mistakes.
//Find out the current folder window according to the mouse click position
HWND findOpenFileWindow(const QString& path)
{
Sleep(3 * 1000);
POINT pNow = { 0, 0 };
if (!GetCursorPos(&pNow))
return NULL;
TCHAR szClass[255] = {0};
HWND pMouseChooseHandle = WindowFromPoint(pNow);
HWND pParent = ::GetParent(pMouseChooseHandle);
GetClassName(pParent, szClass, 255);
if (_tcscmp(szClass, L"SHELLDLL_DefView") == 0 || _tcscmp(szClass, L"NSEViewClass") == 0 )
{
bool bQingDisk = _tcscmp(szClass, L"NSEViewClass") == 0;
pParent = ::GetParent(pParent);
GetClassName(pParent, szClass, 255);
if (_tcscmp(szClass, L"WorkerW"))
{
pParent = pMouseChooseHandle;
for (int i = 0; i < 6; i++)
{
if(pParent != NULL)
pParent = ::GetParent(pParent);
}
HWND pChild = ::GetWindow(pParent, GW_CHILD);
GetClassName(pChild, szClass, 255);
while (pChild != NULL)
{
GetClassName(pChild, szClass, 255);
if (_tcscmp(szClass, TEXT("ShellTabWindowClass")) == 0)
{
pParent = pChild;
break;
}
pChild = ::GetNextWindow(pChild, GW_HWNDNEXT);
}
TCHAR exploreWndName[MAX_PATH] = {0};
::GetWindowText(pParent, exploreWndName, MAX_PATH);
if(QFileInfo(path).fileName() == QString().fromWCharArray(exploreWndName))
return pParent;
}
}
return NULL;
}
//Traverse window display items, get them
QStringList listNormalFolderFile( const QString& path, const QStringList& filter )
{
HWND folderWnd = findOpenFileWindow(path);
HWND hwnd;
IDispatch *pDispatch;
CComPtr<IShellWindows> pShellWindows;
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pShellWindows));
if (FAILED(hr))
{
CoUninitialize();
return QStringList();
}
LONG lCount = 0;
pShellWindows->get_Count(&lCount);
QStringList fileList;
for (LONG i = 0; i < lCount; i++)
{
CComPtr<IShellBrowser> pShellBrowser;
VARIANT var;
var.vt = VT_I4;
var.lVal = i;
if(SUCCEEDED(pShellWindows->Item(var, &pDispatch)))
{
if(SUCCEEDED(IUnknown_QueryService(pDispatch, SID_STopLevelBrowser, IID_PPV_ARGS(&pShellBrowser))))
{
if (SUCCEEDED(IUnknown_GetWindow(pShellBrowser, &hwnd)))
{
TCHAR szBuf[256];
GetWindowText(hwnd, szBuf, sizeof(szBuf) / sizeof(TCHAR));
if(QFileInfo(path).fileName() != QString().fromWCharArray(szBuf))
continue;
CComPtr<IShellView> pShellView;
if(FAILED(pShellBrowser->QueryActiveShellView(&pShellView)))
continue;
CComPtr<IFolderView> pFv = NULL;
/*
do something here
*/
CComPtr<IPersistFolder2 > pFolder;
if( FAILED(pFv->GetFolder(IID_IPersistFolder2, (void**) &pFolder)))
continue;
LPITEMIDLIST pidl = nullptr;
if( SUCCEEDED(pFolder->GetCurFolder(&pidl)))
{
wchar_t cPath[32767];
if( ::SHGetPathFromIDList(pidl, cPath))
{
QString filePath;
QFileInfo fileInfo(filePath.fromWCharArray(cPath));
if(fileInfo.absoluteFilePath() == QFileInfo(path).absoluteFilePath())
{
if(folderWnd == NULL || folderWnd == hwnd)
{
fileList = listFileInBrowser(pShellBrowser, filter);
break;
}
}
}
}
}
}
}
}
CoUninitialize();
return fileList;

WriteFile on Com port indicates Tx complete, but no data transmitted

I am using VS 2013 Professional in an MFC project
I have been using my software to receive data from the com port for some time, but recently needed to add transmission capability
The Init code is:
BOOL PASCAL FAR SetupConnect(pCONNECTION pCon, pCOMCONFIG pCfg)
{
DCB dcb;
pSERBUF pSB = pCon->BufStruct;
// pSERBUF *ppSB = (pSERBUF*)pCon->BufStruct;
// pSB = *ppSB;
dcb.DCBlength = sizeof(DCB);
CheckComs(); // Gets available COM ports
pCon->Port = pNames[0].PortNames[3] - 0x30;
if (pCon->BufStruct == NULL) // This is a personal Communications structure
{ // Init
pCon->hSB = GlobalAlloc(GHND, sizeof(SERBUF));
if (pCon->hSB == NULL)
{
// return INVALID_HANDLE_VALUE;
return 0;
}
pSB = (pSERBUF)GlobalLock(pCon->hSB);
pSB->idComDev = INVALID_HANDLE_VALUE;
pCon->BufStruct = pSB;
}
else return (0);
if (pSB->idComDev == INVALID_HANDLE_VALUE)
{
pSB->idComDev = CreateFile(pNames[0].PortNames, GENERIC_READ | GENERIC_WRITE,
0, //exclusive access
NULL, // no security
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
}
// Current configuration
GetCommState(pSB->idComDev, &dcb);
// Setup baudrate, parity, etc.
dcb.BaudRate = pCfg->dwBaudRate;
dcb.ByteSize = pCfg->bDataBits;
dcb.Parity = pCfg->bParity;
dcb.StopBits = pCfg->bStopBits;
// Setup Flow Control
dcb.fOutxDsrFlow = pCfg->handshake_DTR;
dcb.fDtrControl = DTR_CONTROL_ENABLE; // DTR high while port open
dcb.fOutxCtsFlow = pCfg->handshake_RTS;
dcb.fRtsControl = RTS_CONTROL_DISABLE; // Toggle RTS with EscapeCommFunction
// XON/XOFF Not Used
dcb.fInX = FALSE;
dcb.fOutX = FALSE;
dcb.fBinary = TRUE;
dcb.fParity = TRUE;
//return TRUE if everything looks cool
return (SetCommState(pSB->idComDev, &dcb));
}
And:
CSerCom::CSerCom()
{
pCon = &Con;
pCfg = &Cfg;
m_SerHwnd = this;
pCfg->dwBaudRate = 115200;
pCfg->bDataBits = 8;
pCfg->bParity = NOPARITY;
pCfg->bStopBits = TWOSTOPBITS;
// here
SetupConnect(pCon, pCfg);
pSERBUF pSB = pCon->BufStruct; // pSB is set in SetUpConnect
if (pSB->idComDev == INVALID_HANDLE_VALUE)
{
// device open failure
// hardware not there or someone else controls it!
GlobalUnlock(pCon->hSB);
GlobalFree(pCon->hSB);
pCon->BufStruct = NULL;
// TODO stop this from going any further
HandleFailure();
}
else // Only continue if Port is available
{
// Clear Buffer
SetupComm(pSB->idComDev, 4096, 4096);
PurgeComm(pSB->idComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
// create the overlapped events
memset(&(pSB->osRead), 0, sizeof(OVERLAPPED));
memset(&(pSB->osWrite), 0, sizeof(OVERLAPPED));
pSB->osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
pSB->osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if ((pSB->osRead.hEvent == NULL) || (pSB->osWrite.hEvent == NULL))
{
ReleaseNetResources(pCon);
CloseHandle(pSB->idComDev);
pSB->idComDev = INVALID_HANDLE_VALUE;
HandleFailure();
// return (pSB->idComDev);
}
// allocate & lock the mem
// (used to contain data points to & from the MODBUS
// as well as the receive buffer for incoming serial data)
pSB->hRcv = GlobalAlloc(GHND, MAX_RX_LEN);
if (pSB->hRcv == NULL)
{
ReleaseNetResources(pCon);
CloseHandle(pSB->idComDev);
pSB->idComDev = INVALID_HANDLE_VALUE;
HandleFailure();
// return (pSB->idComDev);
}
pSB->pRcv = (char *)GlobalLock(pSB->hRcv);
pSB->hTx = (char *)GlobalAlloc(GHND, MAX_TX_LEN);
if (pSB->hTx == NULL)
{
ReleaseNetResources(pCon);
CloseHandle(pSB->idComDev);
pSB->idComDev = INVALID_HANDLE_VALUE;
HandleFailure();
// return (pSB->idComDev);
}
pSB->pTx = (char *)GlobalLock(pSB->hTx);
// remember the setup params
pSB->TimeOut = 3; //CalculateTimeOut(pCfg->dwBaudRate);
// pSB->TimerId = TimerId;
// initialize the status counters
// pSB->ValidCt = 0;
// pSB->InvalidCt = 0;
pSB->RxInIdx = 0;
// pSB->RTS_Delay[0] = pCfg->RTS_Delay[0];
// pSB->RTS_Delay[1] = pCfg->RTS_Delay[1];
pSB->RTS_Delay[0] = 100;
pSB->RTS_Delay[1] = 100;
// setup the Comm Timeouts
CommTimeOuts.ReadIntervalTimeout = 0xffffffff;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 1000;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 1000;
SetCommTimeouts(pSB->idComDev, &CommTimeOuts);
// if everything looks good to here
// create the Receive Thread & return the CONNECT handle
pSB->hIOThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
0,
(LPTHREAD_START_ROUTINE)SerProc,
(LPVOID)pCon,
0,
&dwThreadID);
if (pSB->hIOThread == NULL)
{
ReleaseNetResources(pCon);
CloseHandle(pSB->idComDev);
pSB->idComDev = INVALID_HANDLE_VALUE;
HandleFailure();
// return (pSB->idComDev);
}
hIOT = pSB->hIOThread;
}
}
So with that set up, I enter a thread loop in which I have the following
// wait indefinitely for somthing to happen
WaitCommEvent(pSB->idComDev, &dwEvtMask, NULL);
// Catch Rx event
if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
{
Edit1_txt.Format(_T("Rx'd"));
E1->SetWindowText(Edit1_txt);
CMFCView->UpdateWindow();
// only try to read number of bytes in queue
ClearCommError(pSB->idComDev, &dwErrorFlags, &ComStat);
dwLength = ComStat.cbInQue;
// Read data bytes into connection Rcv Buffer at current RxInIdx
if (dwLength > 0)
{
fReadStat = ReadFile(pSB->idComDev,
&(pSB->pRcv[pSB->RxInIdx]),
dwLength,
&bytesread,
&(pSB->osRead));
if (!fReadStat)
{
if (GetLastError() == ERROR_IO_PENDING)
{
// We have to wait for read to complete.
while (!GetOverlappedResult(pSB->idComDev,
&(pSB->osRead), &bytesread, FALSE))
{
dwErrorFlags = GetLastError();
if (dwErrorFlags != ERROR_IO_INCOMPLETE)
// an error occurred, try to recover
ClearCommError(pSB->idComDev, &dwErrorFlags, &ComStat);
}
}
else
{
// some other error occurred
dwLength = 0;
ClearCommError(pSB->idComDev, &dwErrorFlags, &ComStat);
}
} // End of Read Error
} // End of Read Char
if (ComStat.cbInQue < 500)
{
// update the receive index
pSB->RxInIdx += dwLength;
wSleepime = GetTickCount(); // hkk 7/16/99 for console app
ParseAPI(pSB);
}
else
ComStat.cbInQue = 0;
}
// At some point in the program pSB->TxOutIdx is set to some positive value
if (pSB->TxOutIdx > 0)
{
dwLength = pSB->TxOutIdx;
fWriteStat = WriteFile(pSB->idComDev,
&(pSB->pTx[pSB->TxOutIdx]),
dwLength,
&byteswritten,
&(pSB->osWrite));
if (!fWriteStat)
{
if (GetLastError() == ERROR_IO_PENDING)
{
while (!GetOverlappedResult(pSB->idComDev,
&(pSB->osWrite), &byteswritten, FALSE))
{
dwErrorFlags = GetLastError();
if (dwErrorFlags != ERROR_IO_INCOMPLETE)
// an error occurred, try to recover
ClearCommError(pSB->idComDev, &dwErrorFlags, &ComStat);
}
}
pSB->TxOutIdx -= byteswritten;
}
}
}
This detects the Tx buffer full, (pSB->TxOutIdx > 0)
and transmits the data
The transmit fails with an IO pending error, but after execution of GetOverlappedResult, bytes written show the length desired.
However, no data comes out the port. I have checked, and the port found and used is correct.
Wassup?

Structure of the certificate pointed to by NCRYPT_KEY_HANDLE

I've written a credential provider and a key storage provider to logon to windows via certificate. As the documentation in this points is quite vague I used different samples from Microsoft to get things working.
I think I'm nearly there, but the logon behaves unpredictably. Sometimes I get through to the kerberos server (which complains about the certificate), sometimes the process fails with 0x80090029 without any information and sometimes windows crashes. As these crashes all have to do with access violations or null pointers and happen to occur in various places (kerberos.dll, Windows.UI.Logon.dll, ...) I think it has something to do with my key structure that i point the given NCRYT_KEY_HANDLE to in my OpenKey-implementation.
The KeyStorageProviderSample in the CNG-Kit has an example, but relies on a RSA-key stored in %AppData%. I don't have the private key available as it is stored in secure hardware, I just have the public part (i.e. the public certificate), that I read from another device and import via the following code:
SECURITY_STATUS WINAPI KeyHandler::ReadPemCert(__inout KSP_KEY *keyHandle)
{
LOG_FUNCTION;
CERT_CONTEXT certContext = {};
DWORD readLength = 0;
LOG("Fetch certificate");
const int maxSizeInBytes = 4096;
char pemCertificateAsBytes[maxSizeInBytes];
BluetoothClient bluetoothClient = BluetoothClient();
bluetoothClient.getCertificate((PBYTE)pemCertificateAsBytes, readLength);
DWORD certAsDerLen = readLength;
BYTE* certAsDer = new BYTE[certAsDerLen];
LOG("convert PEM to DER");
if (!CryptStringToBinaryA(pemCertificateAsBytes, 0, CRYPT_STRING_BASE64, certAsDer, &certAsDerLen, NULL, NULL))
{
LOG_LAST_ERROR("CryptStringToBinary failed. Err:");
}
LOG_BYTES_AS_HEX("DER-Zertifikat", certAsDer, certAsDerLen);
PCCERT_CONTEXT pcCertContext = CertCreateCertificateContext(X509_ASN_ENCODING, certAsDer, certAsDerLen);
certContext->pCertInfo = pcCertContext->pCertInfo;
certContext->cbCertEncoded = pcCertContext->cbCertEncoded;
certContext->pbCertEncoded = pcCertContext->pbCertEncoded;
certContext->dwCertEncodingType = pcCertContext->dwCertEncodingType;
CERT_INFO *certInfo;
certInfo = certContext.pCertInfo;
CERT_PUBLIC_KEY_INFO pubKeyInfo = certInfo->SubjectPublicKeyInfo;
LOG("Aquire cryptocontext");
HCRYPTPROV hProv = 0;
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
{
LOG_LAST_ERROR("CryptAcquireContext failed. Err:");
return -1;
}
}
LOG("Importing public key");
NCRYPT_KEY_HANDLE publicKeyHandle = NULL;
if (!CryptImportPublicKeyInfo(hProv, X509_ASN_ENCODING, &pubKeyInfo, &publicKeyHandle))
{
LOG_LAST_ERROR("CryptImportPublicKeyInfo failed. Err:");
return -1;
}
keyHandle->fFinished = TRUE;
keyHandle->hPublicKey = (BCRYPT_KEY_HANDLE)publicKeyHandle;
keyHandle->pszKeyBlobType = BCRYPT_RSAPUBLIC_BLOB;
LocalFree(certInfo);
return ERROR_SUCCESS;
}
The key structure is initialized this way:
SECURITY_STATUS
WINAPI
KeyHandler::CreateNewKeyObject(
__in_opt LPCWSTR pszKeyName,
__deref_out KSP_KEY **ppKey)
{
LOG_FUNCTION;
KSP_KEY *pKey = NULL;
DWORD cbKeyName = 0;
SECURITY_STATUS Status = NTE_INTERNAL_ERROR;
NTSTATUS ntStatus = STATUS_INTERNAL_ERROR;
pKey = (KSP_KEY *)HeapAlloc(GetProcessHeap(), 0, sizeof(KSP_KEY));
if (pKey == NULL)
{
return NTE_NO_MEMORY;
}
pKey->cbLength = sizeof(KSP_KEY);
pKey->dwMagic = KSP_KEY_MAGIC;
pKey->dwAlgID = KSP_RSA_ALGID;
pKey->pszKeyFilePath = NULL;
pKey->pszKeyBlobType = NULL;
pKey->dwKeyBitLength = 0;
pKey->fFinished = FALSE;
//Copy the keyname into the key struct.
if (pszKeyName != NULL)
{
cbKeyName = (DWORD)(wcslen(pszKeyName) + 1) * sizeof(WCHAR);
pKey->pszKeyName = (LPWSTR)HeapAlloc(
GetProcessHeap(),
0,
cbKeyName + sizeof(WCHAR));
if (pKey->pszKeyName == NULL)
{
return NTE_NO_MEMORY;
}
CopyMemory(pKey->pszKeyName, pszKeyName, cbKeyName);
pKey->pszKeyName[cbKeyName / sizeof(WCHAR)] = L'\0';
}
else
{
pKey->pszKeyName = NULL;
}
if (globalRSAProviderHandle == NULL)
{
ntStatus = BCryptOpenAlgorithmProvider(
&globalRSAProviderHandle,
BCRYPT_RSA_ALGORITHM,
NULL,
0);
if (!NT_SUCCESS(ntStatus))
{
return NormalizeNteStatus(ntStatus);
}
}
pKey->hProvider = globalRSAProviderHandle;
pKey->pbKeyFile = NULL;
pKey->cbKeyFile = 0;
pKey->pbPrivateKey = NULL;
pKey->cbPrivateKey = 0;
pKey->hPublicKey = NULL;
pKey->hPrivateKey = NULL;
pKey->dwExportPolicy = NCRYPT_ALLOW_EXPORT_FLAG | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;
pKey->dwKeyUsagePolicy = NCRYPT_ALLOW_DECRYPT_FLAG | NCRYPT_ALLOW_SIGNING_FLAG;
pKey->pbSecurityDescr = NULL;
pKey->cbSecurityDescr = 0;
InitializeListHead(&pKey->PropertyList);
*ppKey = pKey;
pKey = NULL;
return ERROR_SUCCESS;
}
Somewhere in there must be the mistake leading to the various memory errors. But as I'm quite new to windows programming and c/c++ I just can't spot the point and can't find any documentation about the datastructure that windows expects for the NCRYTP_KEY_HANDLE.
Does anybody know more about this structure?
NCRYPT_KEY_HANDLE is just a pointer to a structure that you defined.
Windows itself doesn't care about this structure and expect that your provider knows how to work with it.
In KeyHandler::ReadPemCert you mixed legacy CryptoAPI and CNG API. Since you are implementing KSP you should use only CNG API (CryptImportPublicKeyInfoEx2).
DWORD error = NTE_FAIL;
BCRYPT_KEY_HANDLE hKey = NULL;
...
PCCERT_CONTEXT pcCertContext = CertCreateCertificateContext(X509_ASN_ENCODING, certAsDer, certAsDerLen);
if(!pcCertContext)
{
goto Exit;
}
if (!CryptImportPublicKeyInfoEx2(X509_ASN_ENCODING, &pcCertContext->pCertInfo->SubjectPublicKeyInfo, 0, nullptr, &hKey))
{
goto Exit;
}
/* Also you can export key and print out the result to make sure everything works
DWORD temp = 0;
status = BCryptExportKey(hKey, 0, BCRYPT_RSAPUBLIC_BLOB, nullptr, 0, &temp, 0);
if (status != ERROR_SUCCESS)
{
goto Exit;
}
std::vector<BYTE> key(temp);
status = BCryptExportKey(hKey, 0, BCRYPT_RSAPUBLIC_BLOB, key.data(), key.size(), &temp, 0);
if (status != ERROR_SUCCESS)
{
goto Exit;
}
for (auto const& i : key)
{
std::cout << std::hex << (int)i;
}
}
*/
keyHandle->fFinished = TRUE;
keyHandle->hPublicKey = hKey;
keyHandle->pszKeyBlobType = BCRYPT_RSAPUBLIC_BLOB;
erro = ERROR_SUCCESS;
Exit:
if(pcCertContext)
{
CertFreeCertificateContext(pcCertContext);
}
return error;

mixerGetControlDetails always return FFFF on Win8.1 and Win10

I'm trying to read the current volume level.
I moved from the waveOut* functions to the mixer* functions.
If I run the application under Windows XP the value are aligned with the system volume level.
If I run under Win8.1 and Win10 I always receive 0xFFFF.
My code is:
TCHAR msg[100];
g_uNumDevs = mixerGetNumDevs();
wsprintf( msg, L"N. mixer: %d", g_uNumDevs);
pInfo->Log(msg);
if (g_uNumDevs)
{
UINT i = 0;
while(i < g_uNumDevs)
{
MMRESULT mmRes = mixerOpen(&hMixer, i, 0, 0, MIXER_OBJECTF_MIXER);
if (mmRes != MMSYSERR_NOERROR)
{
wsprintf( msg, L"Errore openMixer i:%d err:%d", i, mmRes);
pInfo->Log(msg);
}
// Master line
MIXERLINE ml = {0};
ml.cbStruct = sizeof(MIXERLINE);
ml.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; // Volume master
mmRes = mixerGetLineInfo((HMIXEROBJ) hMixer, &ml, MIXER_GETLINEINFOF_COMPONENTTYPE);
pInfo->Log( ml.szName);
if (mmRes != MMSYSERR_NOERROR)
{
wsprintf( msg, L"Errore mixerGetLineInfo err:%d", mmRes);
pInfo->Log(msg);
mixerClose(hMixer);
return FALSE;
}
// get the volume control of the speaker line.
MIXERLINECONTROLS mlc = {0};
MIXERCONTROL mc = {0};
mlc.cbStruct = sizeof(MIXERLINECONTROLS);
mlc.dwLineID = ml.dwLineID;
mlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
mlc.cControls = 1;
mlc.pamxctrl = &mc;
mlc.cbmxctrl = sizeof(MIXERCONTROL);
mmRes = mixerGetLineControls((HMIXEROBJ) hMixer, &mlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
if (mmRes != MMSYSERR_NOERROR)
{
wsprintf( msg, L"Errore mixerGetLineControls err:%d", mmRes);
pInfo->Log(msg);
EnableWindow( g_hwndSlider, FALSE);
EnableWindow( g_hwndVerifBtn, FALSE);
}
else {
// GetVolume level
MIXERCONTROLDETAILS_UNSIGNED mxcdVolume;
MIXERCONTROLDETAILS mxcd;
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = mc.dwControlID;
mxcd.cChannels = 1;
mxcd.cMultipleItems = 0;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = &mxcdVolume;
mmRes = mixerGetControlDetails(reinterpret_cast<HMIXEROBJ>(hMixer),
&mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE);
if (mmRes != MMSYSERR_NOERROR)
{
EnableWindow( g_hwndSlider, FALSE);
EnableWindow( g_hwndVerifBtn, FALSE);
//return FALSE;
}
else {
DWORD dwVol = mxcdVolume.dwValue;
dwVol &= 0xFFFF;
DWORD perc = dwVol * 100 / 0xFFFF;
SendMessage( g_hwndSlider, TBM_SETPOS, 1, perc);
wsprintf( msg, L"Volume = %d %% [%d]", perc, dwVol);
pInfo->Log(msg);
}
}
mixerClose(hMixer);
++i;
} // while
}
else {
pInfo->Log(L"No audio device !!");
return FALSE;
}

NtRequestPort - parameter incorrect

I'm try to communicate with \Windows\SbApiPort port .
The problem is that I get an error from NtRequestPort (0xc000000d - status invalid parameter).
The parameters of PORT_MESSAGE are not documented so I don't know where is my problem...
I tried to change the length, CallbackId, but the same problem...
Thanks for the help !
Here is the code:
HANDLE hSection=0;
LARGE_INTEGER SecSize;
SecSize.LowPart=0x10000;
SecSize.HighPart=0x0;
if(NtCreateSection(&hSection, SECTION_ALL_ACCESS, NULL, &SecSize, PAGE_READWRITE,SEC_COMMIT ,NULL))
{
printf("couldn't create a section");
}
HANDLE hPort;
PORT_VIEW sectionInfo;
REMOTE_PORT_VIEW mapInfo;
byte ConnectDataBuffer[0x100];
DWORD Size = sizeof(ConnectDataBuffer);
UNICODE_STRING uStr;
WCHAR * uString=L"\\Windows\\SbApiPort";
DWORD maxSize;
SECURITY_QUALITY_OF_SERVICE qos;
for (int i=0 ; i < 0x100 ; i++)
{
ConnectDataBuffer[i]=0xcc;
}
memset(&sectionInfo, 0, sizeof(sectionInfo));
memset(&mapInfo, 0, sizeof(mapInfo));
memset(&mapInfo, 0, sizeof(mapInfo));
memset(&qos, 0, sizeof(qos));
qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
qos.ImpersonationLevel = SecurityImpersonation;
qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
qos.EffectiveOnly = TRUE;
sectionInfo.Length = sizeof(LPC_SECTION_OWNER_MEMORY);
sectionInfo.SectionHandle = hSection;
sectionInfo.SectionOffset = 0;
sectionInfo.ViewSize = 0x10000;
sectionInfo.ViewBase = NULL;
sectionInfo.ViewRemoteBase = NULL;
mapInfo.Length = sizeof(LPC_SECTION_MEMORY);
mapInfo.ViewSize = 0;
mapInfo.ViewBase = NULL;
uStr.Length = wcslen(uString)*2;
uStr.MaximumLength = wcslen(uString)*2+2;
uStr.Buffer =uString;
NTSTATUS res = NtConnectPort(&hPort,&uStr,&qos,&sectionInfo,&mapInfo,&maxSize,(DWORD*)&ConnectDataBuffer,&Size);
if (res)
{
printf("Could not connect to LPC port.\n -%x", res);
return 1;
}
PORT_MESSAGE PortMessage;
ZeroMemory(&PortMessage,sizeof(PORT_MESSAGE));
PortMessage.u1.Length = 0x20;
PortMessage.u2.s2.DataInfoOffset = 15;
PortMessage.u2.ZeroInit = 0x20;
PortMessage.MessageId = LPC_REQUEST;
PortMessage.ClientViewSize = 0x20;
PortMessage.ClientId.UniqueProcess = GetCurrentProcess();
PortMessage.ClientId.UniqueThread = GetCurrentThread();
PortMessage.CallbackId = 0;
res = NtRequestPort(hPort, &PortMessage);
if (res)
{
printf("Could not request LPC port.\n -%x", res);
return 1;
}
printf("End\n", res);

Resources