Setting useUnsafeHeaderParsing for C++ WinHttp - c++

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.

Related

Minifilter PRE_OP_CALLBACK not being called

I'm trying to write a basic minifilter driver, and I have the following put together based on the examples from Minispy (as it's a lot of code, I'll link to a gist)
https://gist.github.com/anonymous/9dce7c550b028fa308a48d36c6098095
If I use WinDBG to attach to the kernel, I can see the DriverEntry being called and my registration completing successfully, and I can also see the unload happening if I call it. However I never see my PRE_OP_CALLBACK or my POST_OP_CALLBACK ever being called when I open/create a file. I'm not sure what I'm missing.
I would recommend comparing with minispy sample which works correctly
github : minispy
In DriverEntry it has a registration...
status = FltRegisterFilter( DriverObject,
&FilterRegistration,
&MiniSpyData.Filter );
as well as
status = FltStartFiltering( MiniSpyData.Filter );
I figured it out actually, it had to do with my INF file. Specifically, the following line:
Instance1.Flags = 0x1 ; Suppress automatic attachments
Removing that line, or setting it to 0, allows it to attach automatically. For my purposes, since I want to monitor all volumes, I'm setting it to 0. On the same account, the minispy example only has 0x1 set on the Instance3 flags, so this makes sense.

GPSD giving mode 0 in libgpsmm

I'm trying to use the C++ integration with GPSD on a Pi. If I run GPSMON I can verify that I have a full fix without issue, however in my C++ program I am getting a fix with mode 0, which means "MODE UPDATE NOT SEEN YET".
The program isn't erroring out at the socket connection, so I'm not sure what's causing the disconnect.
I suppose you are using libgps and libgpsmm. Your problem may be caused by a version incompatibility between gpsd daemon and libgps.
I.e. the client (libgps) may speak a different version of the "API protocol" gpsd_json than the gpsd daemon.
This may happen if you decided to build/link a static version of libgps -- which does not exactly match the version number of gpsd. Or if your client runs on a diffent machine than gpsd server.
I ran into same problem and it took me valuable time to figure out the reason:
JSON parser in libgps is designed badly. It ignores/discards JSON objects which contain name/value pairs, which are not known a priori.
So whole TPV messages from gpsd may be discarded and your client implementation shows no error message, neither libgps functions return an error code. Too bad.
Here it is (json.c, line 296+, #2016-07-27):
if (cursor->attribute == NULL) {
json_debug_trace((1,
"Unknown attribute name '%s' (attributes begin with '%s').\n",
attrbuf, attrs->attribute));
/* don't update end here, leave at attribute start */
return JSON_ERR_BADATTR;
}
And here (libgps_json.c, line 27+, #2016-07-27):
static int json_tpv_read(const char *buf, struct gps_data_t *gpsdata, const char **endptr)
{
const struct json_attr_t json_attrs_1[] = {
{"class", t_check, .dflt.check = "TPV"},
{"device", t_string, .addr.string = gpsdata->dev.path, .len = sizeof(gpsdata->dev.path)},
{"time", t_time, .addr.real = &gpsdata->fix.time, .dflt.real = NAN},
...
Use _gpsmm->enable_debug( level, stderr ) with level>=6 and compile libgps, libgpsmm with define CLIENTDEBUG_ENABLE to get the debug trace output.
git repositiory of gpsd sources tells us dates of recent incompatible changes on the gpsd_json protocol:
git commits:
2016-04-07 Add "status" to TPV for DGPS notification
2016-01-04 Address Savannah bug #46804: JSON satellite view parsing is somewhat broken.
2015-04-04 Add client-library parsing of PPS precision.
2015-01-24 In client library, "dip" member was missing from ATT parsing.
Releases:
3.11 23-Aug-2014
3.12 22-Feb-2015 incompatible
3.13 26-Feb-2015
3.14 14-Mar-2015
3.15 03-Jun-2015 incompatible
3.16 08-Jan-2016 incompatible
3.17 xx-xxx-xxxx incompatible
Do gpsd developers not care about client-server compatibility across versions? What about shared libgps library binary API/ABI stability then?
It is missing versioning functions. Very unsafe also.
(Look at the comment git comment on the 2015-04-04 change mentioned above: Data is currently discarded, pending the next gps_data_t structure break.)

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
...

MAPISendMail with Outlook sometimes results in winmail.dat

I am using MAPISendMail() in an MFC application, and am having a problem that webmail clients sometimes receive a winmail.dat attachment, instead of the "real" attachments.
I have researched a lot, and have found that others are experiencing this problem too, but have not found a solution.
I believe that the problem may be in my MapiFileDesc structure, in which I leave the lpFileType member pointing to NULL, in order to have the mail program (In my case Outlook 2010) determine the file type automatically.
lpFiletype is a MapiFileTagExt structure, and the documentation says this:
A value of NULL indicates an unknown file type or a file type determined by the operating system.
So I believe this should work for common types, such as JPEG or GIF and such.
I read that the winmail.dat is caused by Outlook sending the mail encoded with the ms-tnef encoding, which is proprietary to Microsoft. However, when sending the email, Outlook shows "HTML" as highlighted, not RTF.
Has anyone encountered this problem and properly solved it?
Sending via SMTP and such is not an option, because the user should have a copy of the message in their Sent Items folder.
Using the Outlook object model is not an option, because that would require the user has Outlook installed, and not any MAPI compatible client.
I was having similar issue.
I found a KB article that has interesting information in "One-Off Addressing" section, saying that when address is provided in the format [SMTP:SMTP Address] - then e-mail is always sent in rich text format.
For me the fix was not to set "Address" property of MapiRecipDesc object at all. Instead I put the address in Name property. The opening dialog then does not resolve the address at first, but it resolves it right before sending and then it is not sent in RTF!
I even got it working with recipient's name together with address:
MapiRecipDesc.Name = "Firstname Lastname <mail#address.com>";
I, too, was getting all attachments as WinMail.Dat files for the jclMapi.JclEmail, InternalSendOrSave routine, which is called by jclEmail.Send.
What I did was essentially follow jtmnt's answer and changed:
RealAddresses[I] := FAddress; //do not add the Recipients.AddressesType + AddressTypeDelimiter
and I changed:
lpszName := PAnsiChar('"' + AnsiString(RealNames[I])+'" <' +
AnsiString(RealAddresses[I]) + '>');
lpszAddress := '';
This worked so that I no longer was sending WinMail.dat files as attachments, instead the intended PDFs and MP3s were being sent.
What I really want to report is that I was using an OLE routine that was working fine in Windows 7 and stopped working in Windows 8. Thus, I started looking at the MAPI solutions but found this problem with Winmail.dat files being attached. I could not find any mention of this issue with OLE (with Outlook) not working properly in Windows 8.
(Both:
OutlookApp := GetActiveOleObject('Outlook.Application') and
OutlookApp := CreateOleObject('Outlook.Application')
were no longer working in Windows 8, but continued to work fine in Windows 7.)
Thanks for the solution. Thought you might want to know how to apply it to the jclMapi code and this issue with OLE in Win8.
Curious in Outlooks behavior is it does matter what length the domain name of the recipient has! If the e-mail address domain is 12 characters or more (I don’t know what the limit exactly is), then we face the problematic TNEF coding.
So: a#hutsfluts.nl goes wrong. While abacadabraandmore#hf.nl will result in plain text encoding.
I guess this is not by design….
The solution mentioned above:
Put the recepient e-mail address in MapiRecipDesc’s lpszName and let the lpszAddress point to an empty string (NOT null!) solves the problem.
Don’t ask me why, for I have no clue why this would influence the encoding.

Mystery HRESULT, 0x889000D

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.