Question

I am trying to extend the azure WinHttpRequest python binding to be able to modify the request options. Ideally, I'd simply like to set the global options through winhttp.dll WinHttpSetOptions function, but I can't quite figure out how to do that. Anyway, I decided to venture on this approach, but am getting a "NULL COM pointer access" error. Is it something to do with the invalid ordinal I have assigned to the _put_Option declaration? i.e. the (30, 'put_Option') or is it simply that the symbol can't be found? I am using the IWinHttpRequest documentation for guidance:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa383998(v=vs.85).aspx

class _WinHttpRequestOption(object):
    MaxResponseHeaderSize = 15


class _WinHttpRequestExtension(_WinHttpRequest):
    _put_Option = WINFUNCTYPE(HRESULT, c_int, VARIANT)(30, 'put_Option')

    def _SetOption(self, name, value):
        logging.getLogger(self.__class__.__name__).debug(
            "SetOption %s = %s" % (name, value)
        )

        enum_name = getattr(_WinHttpRequestOption, name)

        var_value = VARIANT()
        var_value.vt = VT_I4
        var_value.vdata.lval = long(value)

        _WinHttpRequestExtension._put_Option(self, enum_name, var_value)

Oh yeah, the code that sets the property:

http_request = _WinHttpRequestExtension()
http_request._SetOption("MaxResponseHeaderSize", 128 * 1024)

Update:

Found this link:

https://chromium.googlesource.com/chromium/deps/perl/+/master%5E/c/i686-w64-mingw32/include/httprequestid.h

It defined a dispatch ID for the function. Since I am no Windows developer, I have no idea what a dispatch ID is. Although replacing my ordinal with this still doesn't work.

#define DISPID_HTTPREQUEST_BASE 0x00000001
#define DISPID_HTTPREQUEST_OPTION (DISPID_HTTPREQUEST_BASE + 5)

_put_Option = WINFUNCTYPE(HRESULT, c_int, VARIANT)(6, 'Option')

Also

I found this, which would indicate self is not a reference to the correct thing. Look at the COM error in this code. if (!this->b_ptr || *(void **)this->b_ptr == NULL) {

#ifdef MS_WIN32
if (self->index) {
    /* It's a COM method */
    CDataObject *this;
    this = (CDataObject *)PyTuple_GetItem(inargs, 0); /* borrowed ref! */
    if (!this) {
        PyErr_SetString(PyExc_ValueError,
                        "native com method call without 'this' parameter");
        return NULL;
    }
    if (!CDataObject_Check(this)) {
        PyErr_SetString(PyExc_TypeError,
                        "Expected a COM this pointer as first argument");
        return NULL;
    }
    /* there should be more checks? No, in Python */
    /* First arg is an pointer to an interface instance */
    if (!this->b_ptr || *(void **)this->b_ptr == NULL) {
        PyErr_SetString(PyExc_ValueError,
                        "NULL COM pointer access");
        return NULL;
    }

I can get the "Expected a COM this pointer as first argument" error if I do this:

_WinHttpRequestExtension._put_Option(super(_WinHttpRequestExtension, self), enum_name, var_value)
Was it helpful?

Solution

Finally figured out that I was accessing methods on the object before it had been CoInitialised(). Moving the calls beyond the call to CoInitialise seems to have got me further, but now I get the error:

ValueError: Procedure probably called with too many arguments (16 bytes in excess)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top