Wide Char Version of Get last Error? - c++

This is Microsoft's code:
void ErrorExit(LPCWSTR lpszFunction, DWORD NTStatusMessage)
{
// Retrieve the system error message for the last-error code
DWORD dww = 0;
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
if (NTStatusMessage)
{
dww = NTStatusMessage;
FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_FROM_HMODULE,
hdlNtCreateFile,
dww,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR) &lpMsgBuf,
0,
NULL );
}
else
{
dww = GetLastError();
FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dww,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpMsgBuf,0, NULL);
}
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %lu: %s"), lpszFunction, dww, lpMsgBuf);
printf("\a"); //audible bell not working yet
MessageBoxW(NULL, (LPCTSTR)lpDisplayBuf, L"Error", MB_OK);
LocalFree(lpDisplayBuf);
LocalFree(lpMsgBuf);
//ExitProcess(dw);
}
I added a section for NTstatus and changed the arg to LPCWSTR. It's basically nonfunctional as simply changing to StringCchPrintfW segfaults on the LPVOID types. Any way of making it wide char friendly?

This problem was solved by adding _UNICODE and UNICODE to the Preprocessor definitions in C/C++ > Preprocessor.
The MessageBox call in the OP code adjusted a little: thanks to someone knowledgeable on the Microsoft forums.

Related

Argument of type "const wchar_t*" is incompatible with parameter of type "LPTSTR" [duplicate]

This question already has an answer here:
Keeps getting the same C++ error
(1 answer)
Closed 8 months ago.
I am a programmer familiar with C# & Java and new to C++. I am trying to create an editor in C# WPF for my C++ OpenGL application and I am following these tutorials: Creating OpenGL Windows in WPF and Walkthrough: Host a Win32 Control in WPF. The latter is from Microsoft.
This line of code Helper::ErrorExit(L"RegisterWindowClass"); gives me this error: Argument of type "const wchar_t*" is incompatible with parameter of type "LPTSTR". It is the L that is triggering this according to Visual Studio and I don't exactly know how to fix it.
public:
//
// Taken from MSDN
//
static void ErrorExit(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
::MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}
TEXT("RegisterWindowClass") is supposed to be used.
Avoid using L"RegisterWindowClass" or "RegisterWindowClass" with parameters of type LPTSTR.
Also change the parameter type to LPCTSTR in static void ErrorExit(LPCTSTR lpszFunction).

Failed with error 87: The parameter is incorrect. How to determine which parameter is incorrect?

I'm trying to create a win32 window as simple as possible, in a unit test, but I get an error 87: how do I get which parameter is incorrect ?
#include <windows.h>
#include <strsafe.h>
LPTSTR GetErrorMessage(wstring fnName)
{
LPTSTR messageBuffer{};
LPTSTR displayBuffer{};
DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
0, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&messageBuffer, 0, 0);
displayBuffer = (LPTSTR)LocalAlloc(LMEM_ZEROINIT, lstrlen(messageBuffer) + (fnName.size() + 40) * sizeof(TCHAR));
StringCchPrintf(displayBuffer, LocalSize(displayBuffer) / sizeof(TCHAR), L"%s failed with error %d: %s", fnName.c_str(), dw, messageBuffer);
return displayBuffer;
}
TEST_METHOD(WinTest)
{
auto hwnd = CreateWindowExW(WS_EX_APPWINDOW, 0, L"test w", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 800, 600, 0, 0, 0, 0);
Assert::IsNotNull(hwnd, GetErrorMessage(L"CreateWindowExW"));
ShowWindow(hwnd, SW_SHOWDEFAULT);
Sleep(1000);
}
Assert failed. CreateWindowExW failed with error 87: The parameter is incorrect.
Reference: createwindowexw on learn.microsoft.com
To answer the specific question you asked - the Win32 API does not tell you WHICH parameter is invalid. You have to read the documentation for the function that failed, and then debug your code to compare the values you are actually passing to the function to see how they differ from the acceptable values the function is expecting.
In this particular example, you are passing a NULL pointer to the lpClassName parameter of CreateWindowEx(), which is not allowed. You must specify the name of the window class you want to create.
On a side note, your GetErrorMessage() function is leaking memory, as it does not free the memory allocated by either FormatMessage() or LocalAlloc(). Both messageBuffer and displayBuffer need to be freed with LocalFree().
I strongly advise you to make GetErrorMessage() return a wstring instead of a raw TCHAR* pointer, eg:
wstring GetErrorMessage(const wstring &fnName)
{
DWORD dw = GetLastError();
wostringstream displayBuffer;
displayBuffer << fnName << L" failed with error " << dw;
LPWSTR messageBuffer{};
if (FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
0,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR)&messageBuffer,
0,
0))
{
displayBuffer << L": " << messageBuffer;
LocalFree(messageBuffer);
}
return displayBuffer.str();
}

Locking a drive with FSCTL_LOCK_VOLUME

I'm having trouble locking my C drive so I can extract some file information later.
#define wszDrive L"\\\\.\\PhysicalDrive0"
HANDLE targetVol = INVALID_HANDLE_VALUE;
DWORD stats;
targetVol = CreateFile(wszDrive,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
/*FILE_FLAG_NO_BUFFERING | FILE_FLAG_RANDOM_ACCESS*/0,
NULL);
if (targetVol == INVALID_HANDLE_VALUE) // cannot open the drive
{
cout << "error in ioControl with volume handler" << endl;
system("pause");
}
if (DeviceIoControl(targetVol,
FSCTL_LOCK_VOLUME,
NULL, 0, NULL, 0,
&stats,
NULL) ==0)
{
cout << "Error with targetVol DeviceIo" << endl;
ErrorExit(TEXT("GetProcessId"));
system("pause");
}
The Error exit below returns "GetProcessID faile with error 1: Incorrect function."
void ErrorExit(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}
Do you guys have any idea what's going on wrong?
The MSDN docs for FSCTL_LOCK_VOLUME say right off the bat that
Locks a volume if it is not in use
The C: drive is almost always in use. The only time it's not in use is if you've booted from different media.

'XcvData' was not declared in this scope

I'm trying to install a virtual printer with Ghostscript and RedMon which prints to a PDF file using c++, but when i try to compile my code, i got 'XcvData' was not declared in this scope on the function below:
#include <windows.h>
#include <winspool.h>
BOOL AddPort()
{
DWORD cbneed,cbstate;
PBYTE pOutputData;
HANDLE hXcv = INVALID_HANDLE_VALUE;
PRINTER_DEFAULTS Defaults = { NULL,NULL,SERVER_ACCESS_ADMINISTER };
WCHAR pszPortName[]=L"UTReportPDFPort:";
pOutputData=(PBYTE)malloc(MAX_PATH);
if(!OpenPrinter((WCHAR*)",XcvMonitor Redirected Port",&hXcv,&Defaults ))
{
LPVOID lpMsgBuf;
GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), NULL,(LPTSTR) &lpMsgBuf, 0, NULL );
::MessageBox(0,(LPCTSTR)lpMsgBuf,(WCHAR*)"ERROR",MB_OK|MB_ICONINFORMATION);
free(pOutputData);
LocalFree( lpMsgBuf );
return FALSE;
}
if(!XcvData(hXcv,L"AddPort",(PBYTE)pszPortName,sizeof(pszPortName),(PBYTE)pOutputData,MAX_PATH,&cbneed,&cbstate))
{
LPVOID lpMsgBuf;
SetLastError(cbstate);
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), NULL,(LPTSTR) &lpMsgBuf, 0, NULL );
::MessageBox(0,(LPCTSTR)lpMsgBuf,(WCHAR*)"ERROR",MB_OK|MB_ICONINFORMATION);
LocalFree( lpMsgBuf );
free(pOutputData);
}
free(pOutputData);
ClosePrinter(hXcv);
return TRUE;
}
What i can do to use the XcvData function on my Qt application?

install driver using c++

I'm trying to install driver behind the user:
I've create DLL which call SetupCopyOEMInf using c++ then i call it from VB application:
C++ code:
PBOOL bRebootRequired = false;
PCTSTR szInfFileName = (PCTSTR) "c:\\temp\\ttt\\Driver\\slabvcp.inf";
if(!SetupCopyOEMInf(szInfFileName,NULL, SPOST_PATH, SP_COPY_REPLACEONLY, NULL, 0, NULL, NULL)){;
DWORD dw = GetLastError();
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf,0, NULL );
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
}
And when i call this function i receiving error "The system cannot find the file specified."
But the path to my file is correct.
PCTSTR szInfFileName = (PCTSTR) "c:\\temp\\ttt\\Driver\\slabvcp.inf";
A cast is not going to work, it will turn your 8-bit character string into Chinese. Fix:
PCTSTR szInfFileName = _T("c:\\temp\\ttt\\Driver\\slabvcp.inf");