Mystery HRESULT, 0x889000D - c++

Decimal: 143196173
Hex: 0x889000D
Results from a call to IAudioSessionControl2->GetProcessId().
GetLastError = 126*
Message = "The specified module could not be found"
I'm not really sure how to interpret this error. Additionally, I can't find a description of the HRESULT anywhere. The documented return codes are S_OK, E_POINTER, AUDCLNT_E_NO_SINGLE_PROCESS, and AUDCLNT_E_DEVICE_INVALIDATED.
Anyone know what this code indicates?
*This is an error marshalled across a managed/unmanaged boundary, obtained by Marshal.GetLastError with a Win32Exception providing the message. It could be bogus, but its what I've got. The HRESULT is pulled out of the unmanaged code directly.
Further investigation, FAILED() doesn't seem to think this is an error. However, the out parameter is cleared (set to 0) which doesn't really make sense. Also, GetErrorInfo returns S_FALSE; so there isn't any additional debug info to go on.

This is AUDCLNT_S_NO_CURRENT_PROCESS - I realized that it somehow missed the Windows 7 SDK headers too late.
The SDK documentation is going to be updated to reflect this.
The result means that the session is a cross process session. The process ID returned is the process ID for the first process which created the session, but if you get this result, you really can't depend on the process ID since the process ID isn't unique.

COM methods can set IErrorInfo on failure. Try to retrieve it - it can contain additional information. In unmanaged code you use GetErrorInfo() for that.

Related

How do I programmatically find why a DLL fails to load?

My C++ program calls LoadLibraryEx() to load a third party DLL. The result is a null handle - it fails to load. A call to GetLastError() returns zero afterwards which isn't of much use but at least it's not a missing DLL file.
The code goes something like this:
HINSTANCE instance = ::LoadLibraryExW(
path, 0, LOAD_WITH_ALTERED_SEARCH_PATH );
if (instance == 0)
{
DWORD lastError = GetLastError();
LOG( "Failed to load, error code is " +
LastErrorAsString( lastError ));
return E_FAIL;
}
I cannot access that machine - I can only deploy code there and observe logs uploaded into network storage.
How would I programmatically find why the DLL fails to load?
Probably your dll can be found but it has a dependency on a dll that cannot found on the remote machine.
If you cannot use Dependency Walker then you can try to use techniques as described in articles such as this:
How to determine a windows executables DLL dependencies programatically?
Okay, so I checked better - and indeed there was another WinAPI call which caused "last error" to be overwritten after LoadLibraryEx(). It was hidden deep inside several layers of C++ helper objects so I didn't notice it earlier. So it was a bug in the caller code and the real "last error" was non-zero.
It looks like the problem is likely to be third-party software that has installed a hook or other anti-virus measure, the hook might be buggy and not setting the correct last error code.
As a troubleshooting measure, you should try LdrLoadDll instead of LoadLibraryEx.
Note that this is an undocumented internal function, so you might prefer not to use it in production code, but it would be a useful troubleshooting step as it should produce a more useful error code.

Setting useUnsafeHeaderParsing for C++ WinHttp

I'm trying to reach a web page on an embedded device.
I'm using WinHttp on Win32.
When trying to read response I get error
ERROR_WINHTTP_INVALID_SERVER_RESPONSE
12152
The server response cannot be parsed.
But when I captured with WireShark I can see that response is coming.
So to test I wrote a simple C# program.
GetResponse was throwing exception
The server committed a protocol violation. Section=ResponseHeader
Detail=CR must be followed by LF
So according to below solution I set useUnsafeHeaderParsing to true. And it worked fine.
HttpWebRequestError: The server committed a protocol violation. Section=ResponseHeader Detail=CR must be followed by LF
Since I can't use C# I need to find a way to set useUnsafeHeaderParsing to true for WinHttp with win32 C++
Many thanks
I've briefly looked into the option flags of WinHttpSetOption and found the following entry:
WINHTTP_OPTION_UNSAFE_HEADER_BLOCKING
This option is reserved for internal use and should not be called.
Since the option looks linke an on/off switch I would try to do the following:
BOOL bResult;
BOOL bOption = FALSE;
bResult = WinHttpSetOption(hInternet,
WINHTTP_OPTION_UNSAFE_HEADER_BLOCKING,
&bOption,
sizeof(bOption));
if (bResult == FALSE)
{
/* handle error with GetLastError() */
}
Well but as MSDN says it's reserved for internal use and therefore the function may change in the future (or has already changed in the past). But it's worth a try... Good Luck!
Looks like the name of the option must have changed since then: with the current SDK it's WINHTTP_OPTION_UNSAFE_HEADER_PARSING. Also, I verified (by examining the Assembly code directly) that:
the option must be DWORD-sized
the value of the option doesn't matter, as long as it's nonzero
you can only enable unsafe parsing; trying to disable (by setting the option value to zero) causes an error to be returned
Obviously, since this undocumented, it's subject to change.

GetQueuedCompletionStatusEx(), ReadDirectoryChangesW()

I am using GetQueuedCompletionStatusEx() and ReadDirectoryChangesW() to try to receive notifications of changes to multiple filesystem hierarchies.
I noticed that I would receive completion packets with error 0x10C when there would be a lot of changes at once. This error code wasn't anywhere in the header files I'd included and wasn't in the documentation ( http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx ). A little digging later, I find out that it's STATUS_NOTIFY_ENUM_DIR defined in ntstatus.h. Neither STATUS_NOTIFY_ENUM_DIR is mentioned in the documentation nor is the necessity of including ntstatus.h. MSDN indicates that it should have been ERROR_NOTIFY_ENUM_DIR. So I am wondering, is this a bug in the documentation or perhaps I am doing something wrong?
ERROR_NOTIFY_ENUM_DIR is defined in winerror.h:
//
// MessageId: ERROR_NOTIFY_ENUM_DIR
//
// MessageText:
//
// A notify change request is being completed and the information is not being returned in the caller's buffer. The caller now needs to enumerate the files to find the changes.
//
#define ERROR_NOTIFY_ENUM_DIR 1022L
However, 1022 is 0x3FE. 0x10C is 268 instead, which is not an error code that ReadDirectoryChangesW() is supposed to return. So if ReadDirectoryChangesW() is directly returning STATUS_NOTIFY_ENUM_DIR instead of translating it into ERROR_NOTIFY_ENUM_DIR, then that very well could be a bug inside of ReadDirectoryChangesW() itself, unless it is a typo in winerror.h instead.
STATUS_NOTIFY_ENUM_DIR is used by some lower-level systems, like NT_TRANSACT_NOTIFY_CHANGE and NtNotifyChangeDirectoryFile(), to indicate that the notification data is larger than the output buffer can hold. That is what ERROR_NOTIFY_ENUM_DIR means in ReadDirectoryChangesW(), as stated in its own documentation.
Some return values of other functions, like the WaitFor...() family of functions, and OverlappedIO/IOCP functions, map directly to STATUS_... codes internally, but are not documented as such because that is a private implementation detail. For example, if you look in winbase.h, there are a couple of dozen common return codes, like WAIT_OBJECT_0, WAIT_IO_COMPLETION, STILL_ACTIVE, and various EXCEPTION_..., that map directly to STATUS_... values.
That does not appear to be the case in this situation, though. According to MSDN, STATUS_NOTIFY_ENUM_DIRis indeed supposed to map to ERROR_NOTIFY_ENUM_DIR, so this would appear to be a bug:
When a kernel-mode driver is called because of an input/output (I/O) request from the Win32 subsystem, the status code returned by the kernel- mode driver will be translated to the status code's corresponding Win32 error code. The following table shows the mapping from the Windows NT status codes to Win32 error codes.
WINDOWS NT STATUS CODE WIN32 ERROR CODE
------------------------------------------------------------------
...
STATUS_NOTIFY_ENUM_DIR ERROR_NOTIFY_ENUM_DIR
...

Using GetLastError when using Dos Commands in C++

So i have a bit of code that uses Dos Commands to try to rename a folder. So
system("rename C:\\Users\\me\\SecondDir NewDir);
So this tries to rename SecondDir to NewDir. There is already a folder at that location called NewDir so it should fail. And it does. Im then using GetLastError to get the error code returned to ensure the problem is what i expect it to be. But it only ever returns ERROR_NO_MORE_FILES. Which isnt the error i should be getting, which is ERROR_ALREADY_EXISTS. Im assuming this is something to do with using the system command?
EDIT: I just checked and i even get ERROR_NO_MORE_FILES returned when a command is successful.
GetLastError will not return a meaningful value except in the circumstances where it is documented to do so. This is not one of them - the values you are getting are irrelevant and intended for someone else.
To rename a file from C you should use the C runtime rename function not use system to invoke a rename utility.
GetLastError is only meaningful immediately after calling a Win32 function which is documented to set the thread Last Error using SetLastError. The C equivalent is errno, which applies to C functions.
The rename function returns -1 on failure and sets errno.
E.g.: http://msdn.microsoft.com/en-us/library/zw5t957f(v=VS.80).aspx

First call to Windows Performance Counters (PDH) sometimes fails

I'm having a problem where sometimes my code will function correctly, but other times it will fail.
This is the first bit of PDH related code that I run:
const std::wstring pidWildcardPath = L"\\Process(*)\\ID Process";
DWORD bufferSize = 0;
LPTSTR paths = NULL;
PDH_STATUS status = PdhExpandCounterPath(
pidWildcardPath.c_str(),
paths,
&bufferSize);
checkPDHStatus(status, PDH_MORE_DATA, L"Expected request for more data.");
The result of the PdhExpandCounterPath function call is 0x800007D0 (PDH_CSTATUS_NO_MACHINE). The checkPDHStatus function is a simple function that I wrote that asserts that the status is equal to the second parameter. In this case, I expect the result to be PDH_MORE_DATA because paths is NULL and bufferSize is 0. The goal of this call is to determine the size of the buffer I must allocate to store all of the results for a subsequent call to PdhExpandCounterPath. This is described in the PDH documentation under the Remarks section.
The list of PDH error codes describes PDH_MORE_DATA as "Unable to connect to the specified computer, or the computer is offline." As you can see by the performance counter path in the code above, I am not even trying to connect to a different computer than my own.
It is interesting the way that this code fails. Sometimes it works fine and then other times, it will fail on multiple back-to-back executions of my application. I have #include <pdh.h> in my header file and I have a section in my property sheet for this DLL that looks like this:
<Tool
Name="VCLinkerTool"
AdditionalDependencies="pdh.lib"
/>
I'm not sure if it matters, but this program is built by Visual Studio 2005 and run on Windows XP. Am I doing something incorrectly?
I'm a co-worker of Dave's and have discovered the following during my investigation:
the code above runs fine when run from a logged-in interactive session
the code runs fine when initiated as a Scheduled Task AND the user is logged in at the time the scheduled task is fired off
the code FAILS only when run as a Scheduled Task AND the user is NOT logged in at the time the task starts
the code continues to fail if the user logs in after the failing task has started but while it is still running (because it is looping "endlessly" until it gets a PDH_MORE_DATA status back).
In the failing instances, the following environment variables have not been established/set for the program: APPDATA, HOMEDRIVE and HOMEPATH ... I don't think this is a problem. However, the failing program also lacks the SeCreateGlobalPrivilege from its token; the passing programs all have this privilege in the token and PERFMON shows it as "Default Enabled". The other difference is that failing program has the NT_AUTH\BATCH user group in the token, while the passing program has NT_AUTH\INTERACTIVE instead ... all other user groups and privileges are the same for both cases. I think the global privilege is coming from the interactive login, but don't know if it has any bearing on PDH operation.
I cannot find anything in the Performance Counter/PDH documentation that talks about needing any special permissions or privileges for this functionality to succeed. Is the global privilege required to use Performance Counters ?
Or is there some other context/environment difference between running Scheduled Tasks (as a specific user) when that user is/isn't logged in at the time the task starts, that would account for the PDH call succeeding/failing respectively ?
Try this format, indicating the local computer:
const std::wstring pidWildcardPath = L"\\.\Process(*)\ID Process";