In my C++ Windows application I received what appears to be an invalid system error code using GetLastError() after a failed Overlapped I/O operation.
// Code
DWORD errorCode = GetLastError();
loggerInt1(LOGERROR, "failed getIoResult, errorCode %d", (int)errorCode);
// Log file
failed getIoResult, errorCode -1073741781
failed getIoResult, errorCode -1073741781
failed getIoResult, errorCode -1073741781
//... many more times at different time points
errorCode is a DWORD, which is an unsigned long, and I casted it to int. But Windows system error codes should only be between 0 and 15999, well within an int.
-1073741781 is C000 002B on 32-bit system (mine) and FFFF FFFF C000 002B on 64-bit system. Interpreted as unsigned long it's 3,221,225,515 (32-bit) or some freakishly huge number (64-bit). Either way it's well outside of the 0-15999 range of a Windows system error.
How can this be? Is there a sane reason for why I got such an error code?
0xC000002B is an NTSTATUS code which resolves to STATUS_PARITY_ERROR.
There is no contractual agreement that a value stored here is a standard Win32 error code. The documentation for GetLastError vaguely implies this:
The error codes returned by a function are not part of the Windows API
specification and can vary by operating system or device driver. For this reason, we cannot provide the complete list of error codes that can be returned by each function
The standard error codes are well documented, so the above statement wouldn't make much sense if all possible results are initially understood.
Note that some WINAPIs can also return HRESULT values.
Related
I am trying to communicatate with a USB device on Windows 7. After I find the device using the vendor and product ID I open it with the following command
dev->device_handle = CreateFile( path, (GENERIC_WRITE | GENERIC_READ),
(FILE_SHARE_READ|FILE_SHARE_WRITE),
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
Then I do a write into the device using
res = WriteFile(dev->device_handle, buf, length, &bytes_written, &ol);
where length is 64.
My device can read and write 64 bytes of data in this interface and this has been tested on Linux and using another tool in windows (I dont have the source of the tool).
The WriteFile function gives me an error code of 87. which is invalid parameters.
Could anybody please point me out the mistake I am making.
P.S. I have already analysed the question
WriteFile returning error code 87
I have made some debug logs
--------------------------------------------------
Before write call
dev_handle:152
buf:2293463
length:65
bytes_written:0
overlap:0
--------------------------------------------------
--------------------------------------------------
After write call
dev_handle:152
buf:2293463
length:65
bytes_written:0
overlap:259
--------------------------------------------------
Last Error: 87
Well, there are 5 parameters:
dev->device_handle could be INVALID_HANDLE_VALUE if CreateFile failed.
buf should not be NULL
length cannot be checked, so it can't be the problem.
&bytes_written is rather pointless (use GetOverlappedResult).
&lo must contain a valid offset and event. Also, all other fields must be zeroed.
Lacking context, we can't fault any specific parameter. I'd check &bytes_written first because it's the most obvious suspect to me.
I have the problem . I am trying to get process memory usage , but unfortunatly some process always returning the same value in my case - 3276. How can I get the real amount of memory using by the process. Thanks in advance.
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID);
PROCESS_MEMORY_COUNTERS memCounter;
BOOL result = GetProcessMemoryInfo(hProcess,
&memCounter,
sizeof( memCounter ));
char procID[20];
char procMem[100];
sprintf_s(procMem, "%d",(memCounter.WorkingSetSize/1024/1024));
if (!(strcmp(procMem,"3276"))) {
strcpy(procMem, "<unavaliable>");
}
sprintf_s(procID, "%d",entry.th32ProcessID);
You are not checking the return values for errors. You simply must do that. Clearly one of them is failing. Is it OpenProcess, or is it GetProcessMemoryInfo? How can we tell without any error checking. Read the documentation for the function and follow the instructions there given to check for errors.
Once you identify which function is failing you can try to work out why. In case of failure, both of these functions will set the last error value and so you can call GetLastError to discern what went wrong.
Quite possibly OpenProcess is failing because you are asking for too many access rights. All you need is PROCESS_QUERY_INFORMATION | PROCESS_VM_READ. Another possible failure mode is that some system processes will not give up this information. Ultimately you need to perform error checking to diagnose the specific problem.
I would like to present meaningful error messages when my program encounters Win32 errors. I call GetLastError, and then FormatMessage. But some of the error messages contain placeholders. For instance, ERROR_BAD_EXE_FORMAT has the text:
%1 is not a valid Win32 application.
Presumably, the %1 is meant to be replaced by the name of the module which is not valid. How can I effect that replacement?
Note that I would ideally like a general solution because I note that there are many errors with placeholders. I can see the following messages in the documentation:
The wrong diskette is in the drive. Insert %2 (Volume Serial Number: %3) into drive %1.
The operating system cannot run %1.
This version of %1 is not compatible with the version of Windows you're running. Check your computer's system information and then contact the software publisher.
The image file %1 is signed, unable to modify.
The system cannot find message text for message number 0x%1 in the message file for %2.
... and so on.
I think Raymond Chen effectively answers the question in a comment on his blog where he writes:
It bugs me too that system error messages contain %1 insertions that you just have to "know" on a case-by-case basis.
ERROR_BAD_EXE_FORMAT contains an insertion %1. You can replace that by using last parameter of FormatMessage(). This code a little sample.
LPWSTR pMessage = L"%1";
DWORD_PTR pArgs[] = {(DWORD_PTR)L"My_Test_App.exe" };
TCHAR buffer[1024];
DWORD dwError = ERROR_BAD_EXE_FORMAT;
DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY;
DWORD dwResult = FormatMessage(dwFlags, pMessage, dwError, 0, buffer, 1024, (va_list*)pArgs);
if (dwResult)
{
//now, 'buffer' contains below message.
//
//My_Test_App.exe is not a valid Win32 application.
//
}
I know that some sytem error codes have insertion. I think we can't supply relevant argument for all of them. So, if I were you, I would like to use just system error code, not FormatMessage(). Or, support argument list and FormatMessage()for only some frequently system error code.
Hoping to find somebody that has experience with services in windows.
I am trying to use the NdisProt driver for ethernet adapters in Delphi
my_Handle := CreateFile(PChar('\\.\NdisProt'),
GENERIC_WRITE or GENERIC_READ, 0, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
(have tried with \\.\\NdisProt too)
After execution my_Handle always has the value '4008' decimal and GetLastError always returns 0
If I try to read or write to the file I get acces violation, anybody knows why I'm getting this unwanted behavior?
If CreateFile doesn't return Invalid_Handle_Value, then it has given you a valid handle, or else the driver for that device is severely buggy. Assume the former.
An access violation has nothing to do with your handle value. It means you're accessing memory that doesn't belong to your process (such as by dereferencing a null pointer, an uninitialized pointer, a non-pointer, or an already freed pointer). Your problem lies elsewhere, perhaps in the reading or writing code that you neglected to show here.
The code in your question is not an assignment statement. It's a comparison expression. You should have gotten a warning from the compiler that the variable's value is undefined. If it always has the value 4008 after executing that code, then you should check whether it also had that value before executing that code. It could simply be that CreateFile is returning a valid handle value, but you're not using the value it returns.
If 4008 isn't the value CreateFile returns, then it's probable that 4008 isn't a valid handle value. If the OS treats handles as pointers (or if it performs some kind of transform on handles to generate pointers), then it could be that the pointer corresponding to that "handle" is not a valid address in your process; that would explain the access violation.
On success, ShellExecute returns a handle.
Do we need to close this handle, and if so, how ?
According to examples published my Microsoft, we need not close this handle. But the doc of ShellExecute itself is mute on the subject. Can you confirm we indeed do not need to close this handle ?
But then, how can a handle be valid and in no need of being closed ??? Which of the following statements is/are true:
the handle is invalid and we can't do anything with it;
the handle is never freed and there is a (Microsoft-sponsored) memory leak (until the caller program ends);
the handle is automatically freed by the system at some time and never reused afterwards (-> another kind of resource leak). Only on trying to use it can we know whether it still points to something.
what else ?
That hinstance is a 16 bit thing, in win32, it is just a number > 32 on success and can't be used for anything other than as an error code when the function fails. On the other hand, if you pass SEE_MASK_NOCLOSEPROCESS to the Ex version, you have a handle you need to close.
Taken from: http://msdn.microsoft.com/en-us/library/bb762153%28VS.85%29.aspx
If the function succeeds, it returns a
value greater than 32. If the function
fails, it returns an error value that
indicates the cause of the failure.
The return value is cast as an
HINSTANCE for backward compatibility
with 16-bit Windows applications. It
is not a true HINSTANCE, however. It
can be cast only to an int and
compared to either 32 or the following
error codes below.
I clear a little what is HINSTANCE and HMODULE. This are not a HANDLE, but much more as a memory address (pointer). You can understand this if you just cast a hInstance to (IMAGE_DOS_HEADER *) and look inside of the loaded module. You can use VirtualQueryEx (GetCurrentProcess(),...) to receive more information (a size for example) from a memory address.
Look at http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx and http://www.apriorit.com/our-experience/articles/9-sd-articles/74-hmodule-hinstance-handle-from-static-library-in-c and you will be see how you can receive a HINSTANCE from a memory address (__ImageBase).
So if you LoadLibrary for example you receive a HMODULE (it's the same as HINSTANCE). You should use FreeLibrary not to "close handle", but to unload module from memory. If you use GetModuleHandle for example, you receive also the same address (you receive address casted as HMODULE), but you should NOT call FreeLibrary to "close the handle".
If you understand what is HINSTANCE and HMODULE and how they should be used, you will be know how to use HINSTANCE returned from ShellExecute.