Windows + SetCommState how to set RTS? - visual-studio-2012

I have an application that has been ported up from VC++ 6 where it worked fine. The code in question uses the WinAPI for a serial device driver. When ported to VS2012, the same code behaves rather differently.
Create a DCB, set SetCommState and go. CTS was set high, RTS was set high and you were on your way.
Since ported up to VS2012 Pro MFC, I am finding that it sets up SetCommState the same with or without hardware flow control:
memset(&dcb, 0x00, sizeof(dcb));
dcb.DCBlength = sizeof(DCB);
// Must be TRUE, only binary mode in Windows
dcb.fBinary = TRUE;
dcb.fParity = FALSE;
// XOn/XOff disabled
dcb.fTXContinueOnXoff = TRUE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.XonLim = 0;
dcb.XoffLim = 0;
dcb.XonChar = 0;
dcb.XoffChar = 0;
// Misc Stuff
dcb.EofChar = 0;
dcb.EvtChar = 0;
dcb.ErrorChar = 0;
dcb.fErrorChar = FALSE;
dcb.fNull = FALSE;
dcb.fAbortOnError = FALSE;
// 8N1 Setup
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
// Baud Rate
if (dwBaudRate == BAUD_115200)
{
dcb.BaudRate = CBR_115200;
}
else
{
dcb.BaudRate = CBR_38400;
}
// setup hardware flow control
if (bHardware == eYesHardwareFlowControl)
{
// ================ FLOW CONTROL ON ================
switch (bIgnoreCTS)
{
case eIgnoreCTS:
dcb.fOutxCtsFlow = FALSE;
break;
case eEnableCTS:
dcb.fOutxCtsFlow = TRUE;
break;
default:
case eCTSDecideLater:
dcb.fOutxCtsFlow = TRUE;
break;
}
// DSR Flow Control
dcb.fDsrSensitivity = FALSE;
dcb.fOutxDsrFlow = FALSE;
// <<Hardware flow control On(TRUE) Off(FALSE)>>
dcb.fDtrControl = DTR_CONTROL_ENABLE;
// <<Hardware flow control On(_HANDSHAKE) Off(_ENBLE)>>
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
}
else
{
// ================ FLOW CONTROL OFF ================
switch (bIgnoreCTS)
{
case eIgnoreCTS:
dcb.fOutxCtsFlow = FALSE;
break;
case eEnableCTS:
dcb.fOutxCtsFlow = TRUE;
break;
default:
case eCTSDecideLater:
dcb.fOutxCtsFlow = FALSE;
break;
}
// DSR Flow Control
dcb.fDsrSensitivity = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
}
if (SetCommState(m_hIdComDev, &dcb) == WINDOWS_API_ZERO_IS_BAD)
{
dwLastError = GetLastError();
}
At this point, I have set up the DCB, cleared it. I don't read in the previous state is I don't want to trust any garbage of anyone that previously used the port. Then I set up every field with Baud, Flow Control and CTS Ignore being the only optional items.
So, what I've noticed is that I can create situation where the Device and the PC don't communicate. Now, mind you, they always did before and they always work with Hyperterminal, ProComm, TeraTerm and so on. What I can see is that when these comm programs start (and the old VC++ 6 App), when the device is created and set up, RTS is immediately set high.
Now, my App, once the DCB is set up, SetCommState called; RTS is always LOW. And when this happens, communications is toast.
I want to FORCE RTS to be high and thought I could do it like this:
if (EscapeCommFunction(m_hIdComDev, CLRRTS) == WINDOWS_API_ZERO_IS_BAD)
{
dwLastError = GetLastError();
}
if (EscapeCommFunction(m_hIdComDev, SETRTS) == WINDOWS_API_ZERO_IS_BAD)
{
dwLastError = GetLastError();
}
But this fails, it gives an error 87 (parameter error). And I cannot quite figure it out. Even if I just SETRTS high only, it fails.
Any ideas on how I can force Windows to set RTS high after I setup the comm parameters in the DCB?

Well it turned out to be a device problem and not a windows problem at all.

Related

How to recreate swapchain after vkAcquireNextImageKHR is VK_SUBOPTIMAL_KHR?

This vulkan tutorial discusses swapchain recreation:
You could also decide to [recreate the swapchain] that if the swap chain is suboptimal, but I've chosen to proceed anyway in that case because we've already acquired an image.
My question is: how would one recreate the swapchain and not proceed in this case of VK_SUBOPTIMAL_KHR?
To see what I mean, let's look at the tutorial's render function:
void drawFrame() {
vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
uint32_t imageIndex;
VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
recreateSwapChain();
return;
/* else if (result == VK_SUBOPTIMAL_KHR) { createSwapchain(); ??? } */
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
throw std::runtime_error("failed to acquire swap chain image!");
}
if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) {
vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);
}
imagesInFlight[imageIndex] = inFlightFences[currentFrame];
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame]};
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffers[imageIndex];
VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]};
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
vkResetFences(device, 1, &inFlightFences[currentFrame]);
if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) {
throw std::runtime_error("failed to submit draw command buffer!");
}
VkPresentInfoKHR presentInfo{};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores;
VkSwapchainKHR swapChains[] = {swapChain};
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &imageIndex;
result = vkQueuePresentKHR(presentQueue, &presentInfo);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized) {
framebufferResized = false;
recreateSwapChain();
} else if (result != VK_SUCCESS) {
throw std::runtime_error("failed to present swap chain image!");
}
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
}
The trouble is as follows:
vkAcquireImageKHR succeeds, signaling the semaphore and returning a valid, suboptimal image
Recreate the swapchain
We can't present the image from 1 with the swapchain from 2 due to VUID-VkPresentInfoKHR-pImageIndices-01430. We need to call vkAcquireImageKHR again to get a new image.
When we call vkAcquireImageKHR again, the semaphore is in the signaled state which is not allowed (VUID-vkAcquireNextImageKHR-semaphore-01286), we need to 'unsignal' it.
Is the best solution here to destroy and recreate the semaphore?
Ad 3: you can use the old images (and swapchain) if you properly use the oldSwapchain parameter when creating the new swapchain. Which is what I assume the tutorial suggests.
Anyway. What I do is that I paranoidly sanitize that toxic semaphore like this:
// cleanup dangerous semaphore with signal pending from vkAcquireNextImageKHR (tie it to a specific queue)
// https://github.com/KhronosGroup/Vulkan-Docs/issues/1059
void cleanupUnsafeSemaphore( VkQueue queue, VkSemaphore semaphore ){
const VkPipelineStageFlags psw = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
VkSubmitInfo submit_info = {};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &semaphore;
submit_info.pWaitDstStageMask;
vkQueueSubmit( queue, 1, &submit_info, VK_NULL_HANDLE );
}
After that the semaphore can be properly catched with a fence or vkQueueWaitIdle, and then destroyed or reused.
I just destroy them, because the new semaphore count might differ, and I don't really consider swapchain recreation a hotspot (and also I just use vkDeviceWaitIdle in such case).

CView::OnFilePrint crashing MFC application

We have an MFC application that has been used and maintained for many years. Recently we made some administrative changes to some computers that are running the application. Now the software occasionally crashes when printing from the application.
We are using pretty standard MFC code to initiate the printing. We added try/catch blocks around what we felt like are the pertinent areas of the code with no luck. Whatever is failing does not seem to throw.
We get the typical dialog stating that "____ MFC Application has stopped working". Closing the program is the only option.
The windows event logger shows that our application is the Faulting application.
The exception code is 0xc0000005, which appears to be an Access Denied error.
The application is in the CView::OnFilePrint() code when the crash occurs.
We have added some logging, and we know that we get through DoPreparePrinting, and OnBeginPrinting.
We believe that CDC::StartDoc would be the next thing called, then CView::OnPrepareDC. We don't get to OnPrepareDC when we fail.
We don't seem to find the source code for CView::OnFilePrint, so we are not sure what it looks like. From research online, we think that things happen in this order in OnFilePrint:
// what we think is in OnFilePrint:
CView::OnFilePrint()
{
OnPreparePrinting(); <- we get through our override of this
OnBeginPrinting(); <- we get through our override of this
// loop back to here on multiple docs
CDC::StartDoc();
CView::OnPrepareDC(); <- we do not reach our override of this
CView::OnPaint();
CDC::EndPage();
// loop back on multiple docs
...
// finish if last doc...
}
I would like to have the source for it so we could attempt to rewrite it and try to gracefully fail instead of failing by crashing.
I'm looking for:
1) any suggestions as to how to figure out why the process of printing causes our application to crash.
2) A location for where the CView::OnFilePrint code is located, if available.
(the only idea I have left to narrow down the problem is to call our own version of this so that we can step through it and add logging and/or see if we can at least fail gracefully when it the problem occurs.)
The printer is Xerox Phaser 3610, for what its worth.
source code for CView::OnFilePrint should be in C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\src\mfc\viewprnt.cpp, depending on VS version. There could also be a problem with printer initialization/access.
If there is any error it is most likely due to printer initialization. You can override OnFilePrint and add CPrintInfo printInfo for testing. Example:
//ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
//ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT, OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, OnFilePrint)
void CMyView::OnFilePrint()
{
try
{
CPrintInfo printInfo;
}
catch(...)
{
//log error
AfxMessageBox(L"error");
}
CView::OnFilePrint();
}
As noted in comments, another possibility is that there is a bug somewhere else in the code, which may not necessarily be related to printing.
Inside of CView::OnFilePrint, this occurs:
CWnd * hwndTemp = AfxGetMainWnd();
It turns out that if you don't call OnFilePrint from the main thread, this returns NULL.
Due to slight timing changes when the computers were logged onto a domain, OnFilePrint was being called from another thread. This causes the above call to return null, then when this line gets executed:
hwndTemp->EnableWindow(FALSE);
The application crashes.
There are several ways to fix this. One is to use this:
CWnd * hwndTemp = AfxGetApp()->GetMainWnd();
In place of this:
CWnd * hwndTemp = AfxGetMainWnd();
Another way is to assure that OnFilePrint is only called from the main thread.
A cut to the chase version of the code in CView::OnFilePrint is here:
// disable main window while printing & init printing status dialog
// Store the Handle of the Window in a temp so that it can be enabled
// once the printing is finished
CWnd * hwndTemp = AfxGetMainWnd(); // <--- CAN RETURN NULL HERE
hwndTemp->EnableWindow(FALSE); // <--- CRASH WILL OCCUR HERE
CPrintingDialog dlgPrintStatus(this);
Full version of CView::OnFilePrint is below.
The OnFilePrint code, with the problem area noted:
void CView::OnFilePrint()
{
// get default print info
CPrintInfo printInfo;
ASSERT(printInfo.m_pPD != NULL); // must be set
if (LOWORD(GetCurrentMessage()->wParam) == ID_FILE_PRINT_DIRECT)
{
CCommandLineInfo* pCmdInfo = AfxGetApp()->m_pCmdInfo;
if (pCmdInfo != NULL)
{
if (pCmdInfo->m_nShellCommand == CCommandLineInfo::FilePrintTo)
{
printInfo.m_pPD->m_pd.hDC = ::CreateDC(pCmdInfo->m_strDriverName,
pCmdInfo->m_strPrinterName, pCmdInfo->m_strPortName, NULL);
if (printInfo.m_pPD->m_pd.hDC == NULL)
{
AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
return;
}
}
}
printInfo.m_bDirect = TRUE;
}
if (OnPreparePrinting(&printInfo))
{
// hDC must be set (did you remember to call DoPreparePrinting?)
ASSERT(printInfo.m_pPD->m_pd.hDC != NULL);
// gather file to print to if print-to-file selected
CString strOutput;
if (printInfo.m_pPD->m_pd.Flags & PD_PRINTTOFILE && !printInfo.m_bDocObject)
{
// construct CFileDialog for browsing
CString strDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULTEXT));
CString strPrintDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULT));
CString strFilter(MAKEINTRESOURCE(AFX_IDS_PRINTFILTER));
CString strCaption(MAKEINTRESOURCE(AFX_IDS_PRINTCAPTION));
CFileDialog dlg(FALSE, strDef, strPrintDef,
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, strFilter, NULL, 0);
dlg.m_ofn.lpstrTitle = strCaption;
if (dlg.DoModal() != IDOK)
return;
// set output device to resulting path name
strOutput = dlg.GetPathName();
}
// set up document info and start the document printing process
CString strTitle;
CDocument* pDoc = GetDocument();
if (pDoc != NULL)
strTitle = pDoc->GetTitle();
else
EnsureParentFrame()->GetWindowText(strTitle);
DOCINFO docInfo;
memset(&docInfo, 0, sizeof(DOCINFO));
docInfo.cbSize = sizeof(DOCINFO);
docInfo.lpszDocName = strTitle;
CString strPortName;
if (strOutput.IsEmpty())
{
docInfo.lpszOutput = NULL;
strPortName = printInfo.m_pPD->GetPortName();
}
else
{
docInfo.lpszOutput = strOutput;
AfxGetFileTitle(strOutput,
strPortName.GetBuffer(_MAX_PATH), _MAX_PATH);
}
// setup the printing DC
CDC dcPrint;
if (!printInfo.m_bDocObject)
{
dcPrint.Attach(printInfo.m_pPD->m_pd.hDC); // attach printer dc
dcPrint.m_bPrinting = TRUE;
}
OnBeginPrinting(&dcPrint, &printInfo);
if (!printInfo.m_bDocObject)
dcPrint.SetAbortProc(_AfxAbortProc);
/**********************************************************************
Problem area.
If the calling thread is not the main thread, the call to AfxGetMainWnd
can return NULL. In this case, hwndTemp->EnableWindow(FALSE) will crash
the application.
**********************************************************************/
// disable main window while printing & init printing status dialog
// Store the Handle of the Window in a temp so that it can be enabled
// once the printing is finished
CWnd * hwndTemp = AfxGetMainWnd(); // <--- CAN RETURN NULL HERE
hwndTemp->EnableWindow(FALSE); // <--- CRASH WILL OCCUR HERE
CPrintingDialog dlgPrintStatus(this);
CString strTemp;
dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_DOCNAME, strTitle);
dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PRINTERNAME,
printInfo.m_pPD->GetDeviceName());
dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PORTNAME, strPortName);
dlgPrintStatus.ShowWindow(SW_SHOW);
dlgPrintStatus.UpdateWindow();
// start document printing process
if (!printInfo.m_bDocObject)
{
printInfo.m_nJobNumber = dcPrint.StartDoc(&docInfo);
if (printInfo.m_nJobNumber == SP_ERROR)
{
// enable main window before proceeding
hwndTemp->EnableWindow(TRUE);
// cleanup and show error message
OnEndPrinting(&dcPrint, &printInfo);
dlgPrintStatus.DestroyWindow();
dcPrint.Detach(); // will be cleaned up by CPrintInfo destructor
AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
return;
}
}
// Guarantee values are in the valid range
UINT nEndPage = printInfo.GetToPage();
UINT nStartPage = printInfo.GetFromPage();
if (nEndPage < printInfo.GetMinPage())
nEndPage = printInfo.GetMinPage();
if (nEndPage > printInfo.GetMaxPage())
nEndPage = printInfo.GetMaxPage();
if (nStartPage < printInfo.GetMinPage())
nStartPage = printInfo.GetMinPage();
if (nStartPage > printInfo.GetMaxPage())
nStartPage = printInfo.GetMaxPage();
int nStep = (nEndPage >= nStartPage) ? 1 : -1;
nEndPage = (nEndPage == 0xffff) ? 0xffff : nEndPage + nStep;
VERIFY(strTemp.LoadString(AFX_IDS_PRINTPAGENUM));
// If it's a doc object, we don't loop page-by-page
// because doc objects don't support that kind of levity.
BOOL bError = FALSE;
if (printInfo.m_bDocObject)
{
OnPrepareDC(&dcPrint, &printInfo);
OnPrint(&dcPrint, &printInfo);
}
else
{
// begin page printing loop
for (printInfo.m_nCurPage = nStartPage;
printInfo.m_nCurPage != nEndPage; printInfo.m_nCurPage += nStep)
{
OnPrepareDC(&dcPrint, &printInfo);
// check for end of print
if (!printInfo.m_bContinuePrinting)
break;
// write current page
TCHAR szBuf[80];
ATL_CRT_ERRORCHECK_SPRINTF(_sntprintf_s(szBuf, _countof(szBuf), _countof(szBuf) - 1, strTemp, printInfo.m_nCurPage));
dlgPrintStatus.SetDlgItemText(AFX_IDC_PRINT_PAGENUM, szBuf);
// set up drawing rect to entire page (in logical coordinates)
printInfo.m_rectDraw.SetRect(0, 0,
dcPrint.GetDeviceCaps(HORZRES),
dcPrint.GetDeviceCaps(VERTRES));
dcPrint.DPtoLP(&printInfo.m_rectDraw);
// attempt to start the current page
if (dcPrint.StartPage() < 0)
{
bError = TRUE;
break;
}
// must call OnPrepareDC on newer versions of Windows because
// StartPage now resets the device attributes.
OnPrepareDC(&dcPrint, &printInfo);
ASSERT(printInfo.m_bContinuePrinting);
// page successfully started, so now render the page
OnPrint(&dcPrint, &printInfo);
if ((nStep > 0) && // pages are printed in ascending order
(nEndPage > printInfo.GetMaxPage() + nStep)) // out off pages
{
// OnPrint may have set the last page
// because the end of the document was reached.
// The loop must not continue with the next iteration.
nEndPage = printInfo.GetMaxPage() + nStep;
}
// If the user restarts the job when it's spooling, all
// subsequent calls to EndPage returns < 0. The first time
// GetLastError returns ERROR_PRINT_CANCELLED
if (dcPrint.EndPage() < 0 && (GetLastError()!= ERROR_SUCCESS))
{
HANDLE hPrinter;
if (!OpenPrinter(LPTSTR(printInfo.m_pPD->GetDeviceName().GetBuffer()), &hPrinter, NULL))
{
bError = TRUE;
break;
}
DWORD cBytesNeeded;
if(!GetJob(hPrinter,printInfo.m_nJobNumber,1,NULL,0,&cBytesNeeded))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
bError = TRUE;
break;
}
}
JOB_INFO_1 *pJobInfo;
if((pJobInfo = (JOB_INFO_1 *)malloc(cBytesNeeded))== NULL)
{
bError = TRUE;
break;
}
DWORD cBytesUsed;
BOOL bRet = GetJob(hPrinter,printInfo.m_nJobNumber,1,LPBYTE(pJobInfo),cBytesNeeded,&cBytesUsed);
DWORD dwJobStatus = pJobInfo->Status;
free(pJobInfo);
pJobInfo = NULL;
// if job status is restart, just continue
if(!bRet || !(dwJobStatus & JOB_STATUS_RESTART) )
{
bError = TRUE;
break;
}
}
if(!_AfxAbortProc(dcPrint.m_hDC, 0))
{
bError = TRUE;
break;
}
}
}
// cleanup document printing process
if (!printInfo.m_bDocObject)
{
if (!bError)
dcPrint.EndDoc();
else
dcPrint.AbortDoc();
}
hwndTemp->EnableWindow(); // enable main window
OnEndPrinting(&dcPrint, &printInfo); // clean up after printing
dlgPrintStatus.DestroyWindow();
dcPrint.Detach(); // will be cleaned up by CPrintInfo destructor
}
}

Uinput - Mouse events were not working

I was finding a problem in emulating the mouse events via uinput device event files.
I could write the event with 'struct input_event' structure format for keyboard/mouse events but only key events were working fine and mouse events were not working
I enabled all the bits required for uinput
UI_SET_EVBIT - EV_KEY (keyboard/mouse), EV_REP (Repeating events), EV_SYN (Sync report events), EV_REL (Mouse)
UI_SET_RELBIT - REL_X, REL_Y (Mouse)
UI_SET_KEYBIT - All the keys in keyboard, BTN_MOUSE, BTN_LEFT, BTN_RIGHT, BTN_MIDDLE
I triggered the events with the below code
gettimeofday(&ev.time,0);
ev.type = EV_KEY;
ev.code = BTN_LEFT;
ev.value = <MOUSE PRESS/RELEASE>; // tbhis wil lbe either 0 or 1
if(write(uinputfd, &ev, sizeof(ev)) < 0)
{
return false;
}
// Then send the X
gettimeofday(&ev.time,0);
ev.type = EV_REL;
ev.code = REL_X;
ev.value = x;
if(write(uinputfd, &ev, sizeof(ev)) < 0)
{
return false;
}
// Then send the Y
gettimeofday(&ev.time,0);
ev.type = EV_REL;
ev.code = REL_Y;
ev.value = y;
if(write(uinputfd, &ev, sizeof(ev)) < 0)
{
return false;
}
// Finally send the SYN
gettimeofday(&ev.time,0);
ev.type = EV_SYN;
ev.code = SYN_REPORT;
ev.value = 0;
if(write(uinputfd, &ev, sizeof(ev)) < 0)
{
return false;
}
Also, I could read/print the Keyboard/Mouse events from the corresponding uinput device input files.
Does anybody have any idea why only mouse events were not working?
I do not have an answer why, but I have noticed that I had to separate keys, absolute, and relative into separate devices. I was hoping somebody else had the answer of how to combine them into one device.
Edit1: Key and relative events are able to be on the same device. If you would still like help for this, I would suggest posting the code used to set up the struct uinput_user_dev, and writing the SET_EVBIT and SET_RELBIT. The sending of events looks fine, so it is probably the initialization, or closing.

Using "Microsoft Windows Security Auditing" provider in real-time consumer with ETW (Event Tracing for Windows)

My task is to make an ETW real-time consumer with events provided by 'Microsoft Windows Security Auditing'.
I made a simple controller and consumer application, basing on this example http://msdn.microsoft.com/en-us/library/windows/desktop/ee441325%28v=vs.85%29.aspx
and changing flags to work in real-time mode.
The main function looks this way:
LPTSTR SessionName = L"hahahaaa";
ULONG status = ERROR_SUCCESS;
PEVENT_TRACE_PROPERTIES pSessionProperties = NULL;
EVENT_TRACE_LOGFILE trace;
TRACEHANDLE hTrace = 0;
TRACEHANDLE hSession = 0;
const GUID providerId = { 0x54849625, 0x5478, 0x4994, { 0xA5, 0xBA, 0x3E, 0x3B, 0x03, 0x28, 0xC3, 0x0D } };
//const GUID providerId = { 0xA68CA8B7, 0x004F, 0xD7B6, { 0xA6, 0x98, 0x07, 0xE2, 0xDE, 0x0F, 0x1F, 0x5D } };
HANDLE hToken = NULL;
HANDLE hProcess = NULL;
hProcess = GetCurrentProcess();
if (OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken) == FALSE) {
printf("Error: Couldn't open the process token\n");
goto cleanup;
}
if(!SetPrivilege(hToken, SE_SECURITY_NAME, TRUE)) goto cleanup;
if (!pSessionProperties) {
const size_t buffSize = sizeof(EVENT_TRACE_PROPERTIES)+(_tcslen(SessionName) + 1) * sizeof(TCHAR);
pSessionProperties = reinterpret_cast<EVENT_TRACE_PROPERTIES *>(malloc(buffSize));
ZeroMemory(pSessionProperties, buffSize);
pSessionProperties->Wnode.BufferSize = buffSize;
pSessionProperties->Wnode.ClientContext = 1;
pSessionProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
pSessionProperties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
pSessionProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
}
// Create the trace session.
status = StartTrace(&hSession, SessionName, pSessionProperties);
if (ERROR_SUCCESS != status) {
wprintf(L"StartTrace() failed with %lu\n", status);
goto cleanup;
}
status = EnableTraceEx2(hSession, &providerId, EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_VERBOSE, 0, 0, 0, NULL);
if (ERROR_SUCCESS != status) {
wprintf(L"EnableTrace() failed with %lu\n", status);
goto cleanup;
}
ZeroMemory(&trace, sizeof(EVENT_TRACE_LOGFILE));
trace.LogFileName = NULL;
trace.LoggerName = SessionName;
trace.CurrentTime = 0;
trace.BuffersRead = 0;
trace.BufferSize = 0;
trace.Filled = 0;
trace.EventsLost = 0;
trace.Context = NULL;
trace.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD;
trace.EventRecordCallback = (PEVENT_RECORD_CALLBACK)(ProcessEvent);
hTrace = OpenTrace(&trace);
if (INVALID_PROCESSTRACE_HANDLE == hTrace)
{
wprintf(L"OpenTrace failed with %lu\n", GetLastError());
goto cleanup;
}
status = ProcessTrace(&hTrace, 1, 0, 0);
if (status != ERROR_SUCCESS && status != ERROR_CANCELLED)
{
wprintf(L"ProcessTrace failed with %lu\n", status);
goto cleanup;
}
The application at 'ProcessTrace()' point should wait for incoming events and write to stdout theirs meta-data. But it simply does not. All generated events by me (i.e. I turn on Detailed Tracking - Process Creation and run an application) are shown in EventViewer, but my program shows nothing.
I thought that it might be some privileges problem, and using this example http://msdn.microsoft.com/en-us/library/windows/desktop/aa446619%28v=vs.85%29.aspx I set SE_SECURITY_NAME privilege and of course run application in Administrator's mode. But nothing changed.
Another try was a session name. Maybe it is the same problem as with 'Windows Kernel Trace' which can log only to system session 'NT Kernel Logger'. Only thing which I found was that 'Microsoft Windows Security Auditing' is correlated with 'Eventlog-Security' session, but when I set session name by this I received 'Access Denied' error. I don't know which extra privilege I should set to handle this.
Last try was to use 'logman' and collect events into a file, but everything was the same. When I set session name by 'Eventlog-Security' I received 'Access Denied'. On the other hand, when I set it by something else I only received one event, provided by 'MSNT_SystemTrace', which is the abstract class for other events.
If I change provider to i.e. 'Microsoft Windows Kernel General' (commented GUID) and generate an event (update system clock) everything works as it should (in my application and using 'logman').
I works in Windows 7 Professional x64 and Visual Studio Ultimate 2013.
My question is, what can I do to receive events from 'Microsoft Windows Security Auditing' provider?
Thanks for any help!
EDIT
As I wrote in comment, if we set SessionName on Eventlog-Security, the application is shortened to OpenTrace() and ProcessTrace().
EDIT 2
As Luke suggested in comment, I ran my application with LocalSystem privileges, and everything started working.

How to send data from barcode scanner MT2070

i've got problems with the barcode scanner MT2070 from Motorola. I use the EMDK 2.6 for .NET(Update 2) to create strings from the scanned barcode, then transmit them to the host pc. But the transmit failed.
The MT2070 run with Windows CE5.0 and is connected over bluetooth to the cradle STB2078. But everytime i get "send failed" and the ResultCode is "E_INCORRECT_MODE".
The problem is that dont understand what they mean with "INCORRECT_MODE" i set it to DECODE and by RawData what is mean with source?
ScannerServicesClient scannerServices;
scannerServices = new ScannerServicesClient();
SCANNERSVC_MODE mode;
if(scannerServices.Connect(true))
{
Logger("start service with decode rights"); // primitiv method to see what happen
scannerServices.GetMode(out mode);
if (mode != SCANNERSVC_MODE.SVC_MODE_DECODE)
{
mode = SCANNERSVC_MODE.SVC_MODE_DECODE;
if (scannerServices.SetMode(mode) != RESULTCODE.E_OK)
{
Logger("cant set mode: " + mode.ToString());
}
}
// wanna know which connection is use
string connection = "";
switch (scannerServices.HostParameters.CurrentConnection)
{
case SCANNERSVC_DATA_CONNECTION.NO_CONNECTION:
connection = "Not connected";
break;
case SCANNERSVC_DATA_CONNECTION.BLUETOOTH:
connection = scannerServices.HostParameters.BluetoothConnection.ToString();
break;
case SCANNERSVC_DATA_CONNECTION.RS232:
connection = scannerServices.HostParameters.RS232Connection.ToString();
break;
case SCANNERSVC_DATA_CONNECTION.USB_CABLE:
connection = scannerServices.HostParameters.USBConnection.ToString();
break;
}
Logger(connection);
ScannerHostParameters scnHost = new ScannerHostParameters(scannerServices);
//example hello
string input = "hello"; //what should send
byte[] output = new byte[input.Length]; //field with converted data
byte source = 0; //<-- what mean source? i sum all byte-value but this cant be correct
for (int i = 0; i < input.Length; ++i)
{
output[i] = Convert.ToByte(input[i]);
source += output[i];
}
RawData rawData = new RawData(output, input.Length, source);
//RawParameters rawParam = new RawParameters();
//rawParam.BaudRate = RawParameters.RawBaudRates.RAWSERIAL_9600;
//rawParam.Type = RawParameters.RawHostType.Auto;
RESULTCODE result = scannerServices.SendRawData(rawData, 2000);
if(result == RESULTCODE.E_OK)
{
Logger("successful send");
}
else
{
Logger("Send failed: " + result.ToString());
}
Logger("ScannerService kill");
scannerServices.Disconnect();
}
Logger("\n");
scannerServices.Dispose();
scannerServices = null;
Thanks for your help! (and sorry for my english)
At some point (somewhere where you're setting the mode - I do it right after setting the mode) you'll want to do this:
//set raw mode
if (RESULTCODE.E_OK != scannerServices.SetAttributeByte((ushort)ATTRIBUTE_NUMBER.ATT_MIA_HOSTNUM, (byte)ENUM_HOSTS.HOST_RAW))
{
throw new Exception("Can't set RAW mode");
scannerServices.Disconnect();
scannerServices.Dispose();
return;
}
Where you have:
RawData rawData = new RawData(output, input.Length, source);
you can leave source as 0:
RawData rawData = new RawData(output, input.Length, 0);
Unfortunately I'm not the greatest when it comes to programming so I've only managed to stumble my way through getting my scanner to work. The documentation isn't great, in fact I find it severly lacking. Even the people at Motorola don't seem to know much about it or how to program it. I've been given misinformation by them on on at least one point.
I use the CDC COM Port Emulation mode for the scanner so that it shows up under Ports in Device Manager (I need the scanner to work with an old program we have which uses COM ports). A driver is also needed for this.
Depending on how you're using the scanner, the above may or may not work.

Resources