none
problem passing safe array

    Question

  • I have a safe array I need to pass from vb.net to unmanaged c++ code. How do I pass a safe array with a subtype of VT_UI1?  I have only cause the code to crash my program when it gets to passing the safe array. I know the safe array works from directly unmanaged c++ or vbscript but I think that the program gets an unexpected type and so it crashs.

    Heres what I have so far:

     <MarshalAsAttribute(UnmanagedType.BStr)> Dim InputReport1(4) As Object
    '...... other code in-between here.
        'device report to send to computer (x,y coordinates, left or right clicks, and scrolling).
            'file contents:
            'number of devices
            'x for dev1
            'y for dev1
            'left click for dev1
            'x for dev2
            'y for dev2
            'left click for dev2
    
            Dim x(40), y(40) As Integer
            x(usernum) = xcoord
            y(usernum) = ycoord
            MsgBox(x(usernum))
            If x(usernum) <= 255 And y(usernum) <= 255 Then
                InputReport1(0) = CByte(0)
                InputReport1(1) = CByte(x(usernum))
                InputReport1(2) = CByte(y(usernum))
                InputReport1(3) = CByte(0)
                InputReport1(4) = CByte(0)
            End If
            GenericHIDDev(usernum).QueueInputReport(InputReport1, 10)
            GenericHIDDev(usernum).StartProcessing()

    The first statement is how Iam defining my variable. It crashs when it gets to QueueInputReport because the data is invalid because if I dim it as byte it returns invalid type error.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    • Edited by The Thinker Tuesday, July 09, 2013 11:50 PM
    Tuesday, July 09, 2013 11:44 PM

All replies

  • Hi,

    Maybe you can refer :http://social.msdn.microsoft.com/Forums/vstudio/en-US/e85d1e7a-2dc3-479c-b0f9-cd1962797839/safearray-to-send-data-vb-to-c-activex.

    In addtion,  you can read this article: http://msdn.microsoft.com/en-us/library/vstudio/dd293608.aspx


    I made a similar thread in c++ interop forums just in-case they figure out first. But the second forum post is close but not the same scenario.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Wednesday, July 10, 2013 11:16 PM
  • With VBnet make sure you declare the arra using from 0 to 3 like the code below.  If you declare the array as 4 basic will actually create 5 items.

    <MarshalAsAttribute(UnmanagedType.I1)>

    Dim InputReport1(0 To 3) As Object

    Usually when you get a crash the when using mix language programming the error is often in the return parameter.  So make sure your return parameter is declared properly.  If you are using a Bstring make sure you add the '\0' at the end.   A Bstring is not the same as a VBnet string.  If the C++ code is using BString then I would return an array of bytes and make sure in VBnet you add the extra character for the '\0'.


    jdweng

    Thursday, July 11, 2013 2:43 AM
  • With VBnet make sure you declare the arra using from 0 to 3 like the code below.  If you declare the array as 4 basic will actually create 5 items.

    <MarshalAsAttribute(UnmanagedType.I1)>

    Dim InputReport1(0 To 3) As Object

    Usually when you get a crash the when using mix language programming the error is often in the return parameter.  So make sure your return parameter is declared properly.  If you are using a Bstring make sure you add the '\0' at the end.   A Bstring is not the same as a VBnet string.  If the C++ code is using BString then I would return an array of bytes and make sure in VBnet you add the extra character for the '\0'.


    jdweng

    The c++ code is using byte here is the c++ queueinput report in question above:

    STDMETHODIMP CHIDDevice::QueueInputReport( SAFEARRAY* psaInputReport, UINT timeoutDuration )
    /*++
    Routine Description:
       Queues additional input reports
    
    Arguments:
        IdleTimeout - used to set the value of the log level
    
    Return value:
        S_OK
    --*/
    {
        VARIANT HUGEP*      pArrayData  = NULL;
        ULONG               cbData      = 0;
        LONG                lLBound     = 0;
        LONG                lUBound     = 0;
        HRESULT             hr          = S_OK;
        HID_INPUT_REPORT    inputReport;
        BOOLEAN             result      = TRUE;
    
        // Initialize Structure
        inputReport.timeout = timeoutDuration;
        inputReport.cbInputReport = 0;
        inputReport.pbInputReport = NULL;
    
        // Get SAFEARRAY size
        IfFailHrGo(SafeArrayGetLBound(psaInputReport, 1, &lLBound));
        IfFailHrGo(SafeArrayGetUBound(psaInputReport, 1, &lUBound));
        IfFalseHrGo(lUBound > lLBound, E_UNEXPECTED);
        cbData = lUBound - lLBound + 1;
    
        inputReport.pbInputReport = (BYTE*)CoTaskMemAlloc( cbData * sizeof(BYTE) );
        
        // If the memory Allocation fails, then fail and exit
        if( inputReport.pbInputReport == NULL )
        {
            hr = E_UNEXPECTED;
            goto Exit;
        }
        
        IfFailHrGo( SafeArrayAccessData( psaInputReport, 
                                         (void HUGEP**)&pArrayData ) );
    
        // Step through the SAFEARRAY and populating only BYTE input report
        // and bail out if the type is not correct
        for( LONG i = lLBound; i <= lUBound; ++i )
        {
            if (pArrayData[i].vt == VT_UI1)
            {
                inputReport.pbInputReport[i-lLBound] = pArrayData[i].bVal;
            }
            else
            {
                hr = E_FAIL;
    
                goto Exit;
            }
        }
        
        inputReport.cbInputReport = cbData;
        
        // Add the report to the input queue (does a shallow copy so no need to free the array data)
        result = m_InputReportQueue.insert( inputReport );
        if (result == FALSE)
        {
            hr = E_FAIL;
        }
    
    Exit:
        SafeArrayUnaccessData(psaInputReport);
        if( FAILED(hr) )
        {
            CoTaskMemFree(inputReport.pbInputReport);
        }
        return hr;
    }


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Thursday, July 11, 2013 2:26 PM
  • The MarshalAsAttribute of InputReport1 has no effect because your code does not marshal that field as part of a structure.  So it does not matter that UnmanagedType.BStr is wrong.

    How did you declare the QueueInputReport method in IDL?

    What are the values of psaInputReport->fFeatures and psaInputReport->cbElements?  If SafeArrayGetVartype succeeds, which VARTYPE does it find?


    Thursday, July 11, 2013 9:04 PM
  • The MarshalAsAttribute of InputReport1 has no effect because your code does not marshal that field as part of a structure.  So it does not matter that UnmanagedType.BStr is wrong.

    How did you declare the QueueInputReport method in IDL?

    What are the values of psaInputReport->fFeatures and psaInputReport->cbElements?  If SafeArrayGetVartype succeeds, which VARTYPE does it find?


    Okay I know that the queue inputreport takes a safearray which I have also tried in place of unmanaged.BStr. This safearray used in the c++ code above is of type VT_UI1  if the array is not of that type it fails and properly reports back its of the wrong type. As you can see from comments in the c++ code it does take a format of BYTE*. The rest is irrelevant. Note: I know the function code in c++ is not to blame it has to be my vb.net code because I can call the function from c++ or vbscript just fine. I have posted the vbscript code section I have converted to vb.net that works:

    Dim InputReport1(4)

    InputReport1(0) = CByte(0) InputReport1(1) = CByte(100) InputReport1(2) = CByte(100) InputReport1(3) = CByte(0) InputReport1(4) = CByte(0) GenericHIDDev(i).QueueInputReport(InputReport1), 10 GenericHIDDev(i).StartProcessing

    Thats all that was in the vbscript and it works. I saw a similar post and they got the problem resolved by dimming their byte array like this:

    Dim b as byte()

    How would I use a byte array that way?

    Heres the idl definition for queueinputreport for the c++ dll:

     HRESULT QueueInputReport( [in]SAFEARRAY(VARIANT) psaInputReport, [in]UINT timeoutDuration );
            [
                id(6),
                helpstring("Method: Starts processing Queue'd Input reports")
            ]

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    • Edited by The Thinker Friday, July 12, 2013 1:35 AM edit 2
    Thursday, July 11, 2013 10:29 PM
  • 
    


    The MarshalAsAttribute of InputReport1 has no effect because your code does not marshal that field as part of a structure.  So it does not matter that UnmanagedType.BStr is wrong.

    How did you declare the QueueInputReport method in IDL?

    What are the values of psaInputReport->fFeatures and psaInputReport->cbElements?  If SafeArrayGetVartype succeeds, which VARTYPE does it find?


    Okay I know that the queue inputreport takes a safearray which I have also tried in place of unmanaged.BStr. This safearray used in the c++ code above is of type VT_UI1  if the array is not of that type it fails and properly reports back its of the wrong type. As you can see from comments in the c++ code it does take a format of BYTE*. The rest is irrelevant. Note: I know the function code in c++ is not to blame it has to be my vb.net code because I can call the function from c++ or vbscript just fine. I have posted the vbscript code section I have converted to vb.net that works:

    Dim InputReport1

    InputReport1(0) = CByte(0) InputReport1(1) = CByte(100) InputReport1(2) = CByte(100) InputReport1(3) = CByte(0) InputReport1(4) = CByte(0) GenericHIDDev(i).QueueInputReport(InputReport1), 10 GenericHIDDev(i).StartProcessing

    Thats all that was in the vbscript and it works. I saw a similar post and they got the problem resolved by dimming their byte array like this:

    Dim b as byte()

    How would I use a byte array that way?

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    Heres the idl definition for queueinputreport for the c++ dll:

     HRESULT QueueInputReport( [in]SAFEARRAY(VARIANT) psaInputReport, [in]UINT timeoutDuration );
            [
                id(6),
                helpstring("Method: Starts processing Queue'd Input reports")
            ]


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    okay I found out according to this documentation that VT_UI1 is an unsigned byte because the description it gives is the same as a byte in vb.net: http://msdn.microsoft.com/en-us/library/cc235119.aspx

    But when I pass it like this in vb.net as byte it returns safearray type mismatch exception:

    Dim InputReport1(4) as Byte
    
    InputReport1(0) = CByte(0)
    InputReport1(1) = CByte(100)
    InputReport1(2) = CByte(100)
    InputReport1(3) = CByte(0)
    InputReport1(4) = CByte(0)
    
    GenericHIDDev(i).QueueInputReport(InputReport1), 10
    GenericHIDDev(i).StartProcessing

    byte description:

    http://msdn.microsoft.com/en-us/library/system.byte.aspx 
    quote: "Represents an 8-bit unsigned integer". (from above link with system.byte in the url).

    other link it quotes that VT_UI1 is a "1-byte unsigned integer".

    I do not get it why did dimming it as a byte not work then? do I need to marshal the byte as a safearray first?

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    • Edited by The Thinker Friday, July 12, 2013 12:34 AM edit 3
    Friday, July 12, 2013 12:29 AM
  • 
    


    The MarshalAsAttribute of InputReport1 has no effect because your code does not marshal that field as part of a structure.  So it does not matter that UnmanagedType.BStr is wrong.

    How did you declare the QueueInputReport method in IDL?

    What are the values of psaInputReport->fFeatures and psaInputReport->cbElements?  If SafeArrayGetVartype succeeds, which VARTYPE does it find?


    Okay I know that the queue inputreport takes a safearray which I have also tried in place of unmanaged.BStr. This safearray used in the c++ code above is of type VT_UI1  if the array is not of that type it fails and properly reports back its of the wrong type. As you can see from comments in the c++ code it does take a format of BYTE*. The rest is irrelevant. Note: I know the function code in c++ is not to blame it has to be my vb.net code because I can call the function from c++ or vbscript just fine. I have posted the vbscript code section I have converted to vb.net that works:

    Dim InputReport1

    InputReport1(0) = CByte(0) InputReport1(1) = CByte(100) InputReport1(2) = CByte(100) InputReport1(3) = CByte(0) InputReport1(4) = CByte(0) GenericHIDDev(i).QueueInputReport(InputReport1), 10 GenericHIDDev(i).StartProcessing

    Thats all that was in the vbscript and it works. I saw a similar post and they got the problem resolved by dimming their byte array like this:

    Dim b as byte()

    How would I use a byte array that way?

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    Heres the idl definition for queueinputreport for the c++ dll:

     HRESULT QueueInputReport( [in]SAFEARRAY(VARIANT) psaInputReport, [in]UINT timeoutDuration );
            [
                id(6),
                helpstring("Method: Starts processing Queue'd Input reports")
            ]


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    okay I found out according to this documentation that VT_UI1 is an unsigned byte because the description it gives is the same as a byte in vb.net: http://msdn.microsoft.com/en-us/library/cc235119.aspx

    But when I pass it like this in vb.net as byte it returns safearray type mismatch exception:

    Dim InputReport1(4) as Byte
    
    InputReport1(0) = CByte(0)
    InputReport1(1) = CByte(100)
    InputReport1(2) = CByte(100)
    InputReport1(3) = CByte(0)
    InputReport1(4) = CByte(0)
    
    GenericHIDDev(i).QueueInputReport(InputReport1), 10
    GenericHIDDev(i).StartProcessing

    byte description:

    http://msdn.microsoft.com/en-us/library/system.byte.aspx 
    quote: "Represents an 8-bit unsigned integer". (from above link with system.byte in the url).

    other link it quotes that VT_UI1 is a "1-byte unsigned integer".

    I do not get it why did dimming it as a byte not work then? do I need to marshal the byte as a safearray first?

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    okay the only time I get it to work is when I pass it as an object with the CByte statements in the reference but then it crashs out to BSOD. :{ However, if I dim it as a byte array it does not call the unmanaged code and errors out with safearraytypemismatchexception.

    is their a pointer in unmanaged Iam missing somewhere?

    Okay heres the fFeatures of psainputreport which returns code:

    2176 which equal 0x880 in hex.


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    • Edited by The Thinker Friday, July 12, 2013 1:34 AM edit 2
    Friday, July 12, 2013 1:24 AM
  • The C++ code looks like it comes from the src\test\dsf\usb\GenericHID\HIDDevice.cpp file in the Windows Driver Kit (WDK). Device Simulation Framework (DSF) has been deprecated in WDK 8, and DSF from WDK 7 is said to cause BSOD on Windows 8.  Are you using Windows 8?

    I don't know why the call would work from VBScript but fail from VB.NET.  There are a few bugs in the C++ code, but I don't think they cause the problem:

    • pArrayData[i] is wrong because i counts from lLBound to lUBound but pArrayData points to the first element.  Use pArrayData[i-lLBound] instead, or make i count from 0 to cbData-1.  However, in SAFEARRAYs marshaled from managed code, the lower bound is usually 0 anyway.
    • If the function detects an error, it calls SafeArrayUnaccessData even if SafeArrayAccessData failed or was not called.

    As implemented, the CHIDDevice::QueueInputReport function expects a SAFEARRAY of VARIANTs in which each VARIANT has type VT_UI1.  If you wanted to pass a Byte() from VB.NET instead, you could change type of the parameter to SAFEARRAY(BYTE) in SoftHIDReceiver.idl, change the type of pArrayData to BYTE HUGEP*, and replace the loop with memcpy.  However, I don't recommend that.  Because you're getting a BSOD, the call must already reach the driver.

    Instead, I suggest:

    • Run the code under a user-mode debugger and compare the contents of inputReport when called from VBScript vs. when called from VB.NET.
    • Attach a kernel debugger and analyze the BSOD.
    Friday, July 12, 2013 4:54 PM
  • The C++ code looks like it comes from the src\test\dsf\usb\GenericHID\HIDDevice.cpp file in the Windows Driver Kit (WDK). Device Simulation Framework (DSF) has been deprecated in WDK 8, and DSF from WDK 7 is said to cause BSOD on Windows 8.  Are you using Windows 8?

    I don't know why the call would work from VBScript but fail from VB.NET.  There are a few bugs in the C++ code, but I don't think they cause the problem:

    • pArrayData[i] is wrong because i counts from lLBound to lUBound but pArrayData points to the first element.  Use pArrayData[i-lLBound] instead, or make i count from 0 to cbData-1.  However, in SAFEARRAYs marshaled from managed code, the lower bound is usually 0 anyway.
    • If the function detects an error, it calls SafeArrayUnaccessData even if SafeArrayAccessData failed or was not called.

    As implemented, the CHIDDevice::QueueInputReport function expects a SAFEARRAY of VARIANTs in which each VARIANT has type VT_UI1.  If you wanted to pass a Byte() from VB.NET instead, you could change type of the parameter to SAFEARRAY(BYTE) in SoftHIDReceiver.idl, change the type of pArrayData to BYTE HUGEP*, and replace the loop with memcpy.  However, I don't recommend that.  Because you're getting a BSOD, the call must already reach the driver.

    Instead, I suggest:

    • Run the code under a user-mode debugger and compare the contents of inputReport when called from VBScript vs. when called from VB.NET.
    • Attach a kernel debugger and analyze the BSOD.

    I know the bluescreen is on softusbk.sys which is weird because i thought that was the keyboard section of the system components it installs. I was browsing the wdk forums and they were saying much different things about running dsf on windows 8 but no Iam running it on windows 7 right now (it depends because doran and some of the other guys were saying something completely different and that windows 8 had a very similar driver model). Edit: how would you suggest attaching a kernel debugger? The exception I get in bluescreen is SYSTEM_SERVICE_EXCEPTION.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    • Edited by The Thinker Friday, July 12, 2013 6:11 PM edit 4
    Friday, July 12, 2013 6:03 PM
  • The C++ code looks like it comes from the src\test\dsf\usb\GenericHID\HIDDevice.cpp file in the Windows Driver Kit (WDK). Device Simulation Framework (DSF) has been deprecated in WDK 8, and DSF from WDK 7 is said to cause BSOD on Windows 8.  Are you using Windows 8?

    I don't know why the call would work from VBScript but fail from VB.NET.  There are a few bugs in the C++ code, but I don't think they cause the problem:

    • pArrayData[i] is wrong because i counts from lLBound to lUBound but pArrayData points to the first element.  Use pArrayData[i-lLBound] instead, or make i count from 0 to cbData-1.  However, in SAFEARRAYs marshaled from managed code, the lower bound is usually 0 anyway.
    • If the function detects an error, it calls SafeArrayUnaccessData even if SafeArrayAccessData failed or was not called.

    As implemented, the CHIDDevice::QueueInputReport function expects a SAFEARRAY of VARIANTs in which each VARIANT has type VT_UI1.  If you wanted to pass a Byte() from VB.NET instead, you could change type of the parameter to SAFEARRAY(BYTE) in SoftHIDReceiver.idl, change the type of pArrayData to BYTE HUGEP*, and replace the loop with memcpy.  However, I don't recommend that.  Because you're getting a BSOD, the call must already reach the driver.

    Instead, I suggest:

    • Run the code under a user-mode debugger and compare the contents of inputReport when called from VBScript vs. when called from VB.NET.
    • Attach a kernel debugger and analyze the BSOD.


    I know the bluescreen is on softusbk.sys which is weird because i thought that was the keyboard section of the system components it installs. I was browsing the wdk forums and they were saying much different things about running dsf on windows 8 but no Iam running it on windows 7 right now (it depends because doran and some of the other guys were saying something completely different and that windows 8 had a very similar driver model). Edit: how would you suggest attaching a kernel debugger? The exception I get in bluescreen is SYSTEM_SERVICE_EXCEPTION.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    I got this information from the dump file with bluescreen view:

    071113-33992-01.dmp 7/11/2013 9:37:38 PM SYSTEM_SERVICE_EXCEPTION 0x0000003b 00000000`c0000005 fffff880`0b05aa06 fffff880`0d3491b0 00000000`00000000 SOFTUSBK.SYS SOFTUSBK.SYS+5aa06     x64 ntoskrnl.exe+75c00     C:\windows\Minidump\071113-33992-01.dmp 2 15 7601 285,992 7/11/2013 9:39:09 PM 

    The part in bold is the parameter with details of the exception that cause the bug check.


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Here is the exception returned by the windbg software with the minidump file loaded into at the time of the crash yesterday:

    EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.

    Edit: looks like an access violation after research but you think Iam passing the variable incorrectly to the unmanaged code or should I make your suggestions to the unmanaged code and test again?


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr



    • Edited by The Thinker Friday, July 12, 2013 6:38 PM edit 3
    Friday, July 12, 2013 6:30 PM
  • The C++ code looks like it comes from the src\test\dsf\usb\GenericHID\HIDDevice.cpp file in the Windows Driver Kit (WDK). Device Simulation Framework (DSF) has been deprecated in WDK 8, and DSF from WDK 7 is said to cause BSOD on Windows 8.  Are you using Windows 8?

    I don't know why the call would work from VBScript but fail from VB.NET.  There are a few bugs in the C++ code, but I don't think they cause the problem:

    • pArrayData[i] is wrong because i counts from lLBound to lUBound but pArrayData points to the first element.  Use pArrayData[i-lLBound] instead, or make i count from 0 to cbData-1.  However, in SAFEARRAYs marshaled from managed code, the lower bound is usually 0 anyway.
    • If the function detects an error, it calls SafeArrayUnaccessData even if SafeArrayAccessData failed or was not called.

    As implemented, the CHIDDevice::QueueInputReport function expects a SAFEARRAY of VARIANTs in which each VARIANT has type VT_UI1.  If you wanted to pass a Byte() from VB.NET instead, you could change type of the parameter to SAFEARRAY(BYTE) in SoftHIDReceiver.idl, change the type of pArrayData to BYTE HUGEP*, and replace the loop with memcpy.  However, I don't recommend that.  Because you're getting a BSOD, the call must already reach the driver.

    Instead, I suggest:

    • Run the code under a user-mode debugger and compare the contents of inputReport when called from VBScript vs. when called from VB.NET.
    • Attach a kernel debugger and analyze the BSOD.


    I know the bluescreen is on softusbk.sys which is weird because i thought that was the keyboard section of the system components it installs. I was browsing the wdk forums and they were saying much different things about running dsf on windows 8 but no Iam running it on windows 7 right now (it depends because doran and some of the other guys were saying something completely different and that windows 8 had a very similar driver model). Edit: how would you suggest attaching a kernel debugger? The exception I get in bluescreen is SYSTEM_SERVICE_EXCEPTION.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    I got this information from the dump file with bluescreen view:

    071113-33992-01.dmp 7/11/2013 9:37:38 PM SYSTEM_SERVICE_EXCEPTION 0x0000003b 00000000`c0000005 fffff880`0b05aa06 fffff880`0d3491b0 00000000`00000000 SOFTUSBK.SYS SOFTUSBK.SYS+5aa06     x64 ntoskrnl.exe+75c00     C:\windows\Minidump\071113-33992-01.dmp 2 15 7601 285,992 7/11/2013 9:39:09 PM 

    The part in bold is the parameter with details of the exception that cause the bug check.


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Here is the exception returned by the windbg software with the minidump file loaded into at the time of the crash yesterday:

    EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.

    Edit: looks like an access violation after research but you think Iam passing the variable incorrectly to the unmanaged code or should I make your suggestions to the unmanaged code and test again?


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    Maybe something is wrong with the memory allocation then?

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Friday, July 12, 2013 7:07 PM
  • The C++ code looks like it comes from the src\test\dsf\usb\GenericHID\HIDDevice.cpp file in the Windows Driver Kit (WDK). Device Simulation Framework (DSF) has been deprecated in WDK 8, and DSF from WDK 7 is said to cause BSOD on Windows 8.  Are you using Windows 8?

    I don't know why the call would work from VBScript but fail from VB.NET.  There are a few bugs in the C++ code, but I don't think they cause the problem:

    • pArrayData[i] is wrong because i counts from lLBound to lUBound but pArrayData points to the first element.  Use pArrayData[i-lLBound] instead, or make i count from 0 to cbData-1.  However, in SAFEARRAYs marshaled from managed code, the lower bound is usually 0 anyway.
    • If the function detects an error, it calls SafeArrayUnaccessData even if SafeArrayAccessData failed or was not called.

    As implemented, the CHIDDevice::QueueInputReport function expects a SAFEARRAY of VARIANTs in which each VARIANT has type VT_UI1.  If you wanted to pass a Byte() from VB.NET instead, you could change type of the parameter to SAFEARRAY(BYTE) in SoftHIDReceiver.idl, change the type of pArrayData to BYTE HUGEP*, and replace the loop with memcpy.  However, I don't recommend that.  Because you're getting a BSOD, the call must already reach the driver.

    Instead, I suggest:

    • Run the code under a user-mode debugger and compare the contents of inputReport when called from VBScript vs. when called from VB.NET.
    • Attach a kernel debugger and analyze the BSOD.


    I know the bluescreen is on softusbk.sys which is weird because i thought that was the keyboard section of the system components it installs. I was browsing the wdk forums and they were saying much different things about running dsf on windows 8 but no Iam running it on windows 7 right now (it depends because doran and some of the other guys were saying something completely different and that windows 8 had a very similar driver model). Edit: how would you suggest attaching a kernel debugger? The exception I get in bluescreen is SYSTEM_SERVICE_EXCEPTION.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    I got this information from the dump file with bluescreen view:

    071113-33992-01.dmp 7/11/2013 9:37:38 PM SYSTEM_SERVICE_EXCEPTION 0x0000003b 00000000`c0000005 fffff880`0b05aa06 fffff880`0d3491b0 00000000`00000000 SOFTUSBK.SYS SOFTUSBK.SYS+5aa06     x64 ntoskrnl.exe+75c00     C:\windows\Minidump\071113-33992-01.dmp 2 15 7601 285,992 7/11/2013 9:39:09 PM 

    The part in bold is the parameter with details of the exception that cause the bug check.


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Here is the exception returned by the windbg software with the minidump file loaded into at the time of the crash yesterday:

    EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.

    Edit: looks like an access violation after research but you think Iam passing the variable incorrectly to the unmanaged code or should I make your suggestions to the unmanaged code and test again?


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    Maybe something is wrong with the memory allocation then?

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    okay the safearray type is different when I run it from the vbscript. It is 2194 which is 0x892 in hex.  but when I run it from managed code I get 2176 which is 0x880. This is fFeatures of the safearray you asked me to report on earlier which i put into a messagebox. Edit: that means dotnet is doing something wrong with passing the data to unmanaged code or I have not given it enough marshalling information.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr




    • Edited by The Thinker Friday, July 12, 2013 10:23 PM edit 5
    Friday, July 12, 2013 8:13 PM
  • I don't think the different fFeatures flags are a problem.  VBScript is passing the extra flags FADF_STATIC = 0x0002 and FADF_FIXEDSIZE = 0x0010.  These flags don't matter because the C++ code doesn't try to resize or free the array.

    Instead, you could try:

    • Check the COM apartment type.  The .NET Framework uses the MTA by default (unless overridden with STAThreadAttribute in the Main method, or by calling Thread.SetApartmentState), but I think Windows Script Host uses STA.  Because src\test\dsf\usb\GenericHID\HIDDevice.rgs sets val ThreadingModel = s 'Apartment', COM should create the HIDDevice objects in an STA in any case; but the marshaling from MTA to STA can reveal latent bugs.  So, move your VB.NET code to an STA thread and see if that helps.
    • The sample code in src\test\dsf\usb\GenericHID\TestGenericHid.wsf calls many more methods than the VB.NET code you posted.  Perhaps you omitted some of those calls and that caused the BSOD.  Try removing calls from the VBScript code so that it matches your VB.NET code; does the VBScript code then cause a BSOD too?
    Saturday, July 13, 2013 10:53 AM
  • I don't think the different fFeatures flags are a problem.  VBScript is passing the extra flags FADF_STATIC = 0x0002 and FADF_FIXEDSIZE = 0x0010.  These flags don't matter because the C++ code doesn't try to resize or free the array.

    Instead, you could try:

    • Check the COM apartment type.  The .NET Framework uses the MTA by default (unless overridden with STAThreadAttribute in the Main method, or by calling Thread.SetApartmentState), but I think Windows Script Host uses STA.  Because src\test\dsf\usb\GenericHID\HIDDevice.rgs sets val ThreadingModel = s 'Apartment', COM should create the HIDDevice objects in an STA in any case; but the marshaling from MTA to STA can reveal latent bugs.  So, move your VB.NET code to an STA thread and see if that helps.
    • The sample code in src\test\dsf\usb\GenericHID\TestGenericHid.wsf calls many more methods than the VB.NET code you posted.  Perhaps you omitted some of those calls and that caused the BSOD.  Try removing calls from the VBScript code so that it matches your VB.NET code; does the VBScript code then cause a BSOD too?

    Change the report descriptors to reportdescriptorsmouse variable and plug in my code and it works into the default code. just replace x(usernum) and y(usernum) with static values too. Trying this out hope it works but not sure.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Saturday, July 13, 2013 6:14 PM
  • I don't think the different fFeatures flags are a problem.  VBScript is passing the extra flags FADF_STATIC = 0x0002 and FADF_FIXEDSIZE = 0x0010.  These flags don't matter because the C++ code doesn't try to resize or free the array.

    Instead, you could try:

    • Check the COM apartment type.  The .NET Framework uses the MTA by default (unless overridden with STAThreadAttribute in the Main method, or by calling Thread.SetApartmentState), but I think Windows Script Host uses STA.  Because src\test\dsf\usb\GenericHID\HIDDevice.rgs sets val ThreadingModel = s 'Apartment', COM should create the HIDDevice objects in an STA in any case; but the marshaling from MTA to STA can reveal latent bugs.  So, move your VB.NET code to an STA thread and see if that helps.
    • The sample code in src\test\dsf\usb\GenericHID\TestGenericHid.wsf calls many more methods than the VB.NET code you posted.  Perhaps you omitted some of those calls and that caused the BSOD.  Try removing calls from the VBScript code so that it matches your VB.NET code; does the VBScript code then cause a BSOD too?


    Change the report descriptors to reportdescriptorsmouse variable and plug in my code and it works into the default code. just replace x(usernum) and y(usernum) with static values too. Trying this out hope it works but not sure.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    I forgot to mention Iam calling this from a dll. The source code is here: http://kinectmultipoint.codeplex.com. click on the dsf mouse wrapper library vb.net version under downloads. Its the same code I have now. I released that version 4 days ago but I have not changed it. See if you can see whats wrong. The dsf runtime is important but I also changed softhidreceiver.dll's buildhiddescriptors safearray to the correct device so I would not have to use create custom report descriptors and create custom hid descriptors functions like the script uses.

    Look at how I just changed the testgenerichid.wsf file to multiple devices? Edit:Iam having trouble with changing to STA. So far this is what I have done:

    1. put the below code into form load event.

    2. put the below code into my.application.startup event.

    Thread.CurrentThread.SetApartmentState(ApartmentState.STA)
    


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr






    • Edited by The Thinker Saturday, July 13, 2013 9:56 PM edit 4
    Saturday, July 13, 2013 8:06 PM
  • I don't think the different fFeatures flags are a problem.  VBScript is passing the extra flags FADF_STATIC = 0x0002 and FADF_FIXEDSIZE = 0x0010.  These flags don't matter because the C++ code doesn't try to resize or free the array.

    Instead, you could try:

    • Check the COM apartment type.  The .NET Framework uses the MTA by default (unless overridden with STAThreadAttribute in the Main method, or by calling Thread.SetApartmentState), but I think Windows Script Host uses STA.  Because src\test\dsf\usb\GenericHID\HIDDevice.rgs sets val ThreadingModel = s 'Apartment', COM should create the HIDDevice objects in an STA in any case; but the marshaling from MTA to STA can reveal latent bugs.  So, move your VB.NET code to an STA thread and see if that helps.
    • The sample code in src\test\dsf\usb\GenericHID\TestGenericHid.wsf calls many more methods than the VB.NET code you posted.  Perhaps you omitted some of those calls and that caused the BSOD.  Try removing calls from the VBScript code so that it matches your VB.NET code; does the VBScript code then cause a BSOD too?


    Change the report descriptors to reportdescriptorsmouse variable and plug in my code and it works into the default code. just replace x(usernum) and y(usernum) with static values too. Trying this out hope it works but not sure.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    I forgot to mention Iam calling this from a dll. The source code is here: http://kinectmultipoint.codeplex.com. click on the dsf mouse wrapper library vb.net version under downloads. Its the same code I have now. I released that version 4 days ago but I have not changed it. See if you can see whats wrong. The dsf runtime is important but I also changed softhidreceiver.dll's buildhiddescriptors safearray to the correct device so I would not have to use create custom report descriptors and create custom hid descriptors functions like the script uses.

    Look at how I just changed the testgenerichid.wsf file to multiple devices? Edit:Iam having trouble with changing to STA. So far this is what I have done:

    1. put the below code into form load event.

    2. put the below code into my.application.startup event.

    Thread.CurrentThread.SetApartmentState(ApartmentState.STA)


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr







    Okay since pbInputReport accepts byte format I created a byte function called devInputReportBytes  in my unmanaged c++ com dll which I send in a parameter which is of BYTE format (now char array but was originally byte). I think it might be working now but I will up the mouse values in testing to make sure. But if it works I will mark your post about using bytes as answer.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Sunday, July 14, 2013 10:25 PM
  • I don't think the different fFeatures flags are a problem.  VBScript is passing the extra flags FADF_STATIC = 0x0002 and FADF_FIXEDSIZE = 0x0010.  These flags don't matter because the C++ code doesn't try to resize or free the array.

    Instead, you could try:

    • Check the COM apartment type.  The .NET Framework uses the MTA by default (unless overridden with STAThreadAttribute in the Main method, or by calling Thread.SetApartmentState), but I think Windows Script Host uses STA.  Because src\test\dsf\usb\GenericHID\HIDDevice.rgs sets val ThreadingModel = s 'Apartment', COM should create the HIDDevice objects in an STA in any case; but the marshaling from MTA to STA can reveal latent bugs.  So, move your VB.NET code to an STA thread and see if that helps.
    • The sample code in src\test\dsf\usb\GenericHID\TestGenericHid.wsf calls many more methods than the VB.NET code you posted.  Perhaps you omitted some of those calls and that caused the BSOD.  Try removing calls from the VBScript code so that it matches your VB.NET code; does the VBScript code then cause a BSOD too?


    Change the report descriptors to reportdescriptorsmouse variable and plug in my code and it works into the default code. just replace x(usernum) and y(usernum) with static values too. Trying this out hope it works but not sure.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    I forgot to mention Iam calling this from a dll. The source code is here: http://kinectmultipoint.codeplex.com. click on the dsf mouse wrapper library vb.net version under downloads. Its the same code I have now. I released that version 4 days ago but I have not changed it. See if you can see whats wrong. The dsf runtime is important but I also changed softhidreceiver.dll's buildhiddescriptors safearray to the correct device so I would not have to use create custom report descriptors and create custom hid descriptors functions like the script uses.

    Look at how I just changed the testgenerichid.wsf file to multiple devices? Edit:Iam having trouble with changing to STA. So far this is what I have done:

    1. put the below code into form load event.

    2. put the below code into my.application.startup event.

    Thread.CurrentThread.SetApartmentState(ApartmentState.STA)


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr







    Okay since pbInputReport accepts byte format I created a byte function called devInputReportBytes  in my unmanaged c++ com dll which I send in a parameter which is of BYTE format (now char array but was originally byte). I think it might be working now but I will up the mouse values in testing to make sure. But if it works I will mark your post about using bytes as answer.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    Darn it accepts it but does not move the mouse. Let me look through and see what i did wrong.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Heres the updated vb.net code I tried that does let me send to the safearray but does not move the mouse device:

     Public Function sendinputreport(xcoord As Integer, ycoord As Integer, leftclick As Boolean, rightclick As Boolean) As Boolean
            'device report to send to computer (x,y coordinates, left or right clicks, and scrolling).
            'file contents:
            'number of devices
            'x for dev1
            'y for dev1
            'left click for dev1
            'x for dev2
            'y for dev2
            'left click for dev2
    
            Dim x(40), y(40) As Integer
            x(usernum) = xcoord
            y(usernum) = ycoord
            MsgBox(x(usernum))
            Dim InputReport1() As Object = New Object(4) {CByte(0), CByte(x(usernum)), CByte(y(usernum)), CByte(0), CByte(0)}
            Dim InputReportMain As System.Array = Array.CreateInstance(GetType(Byte), 5)
            InputReportMain = InputReport1
            'InputReport1(0) = CByte(0)
            'InputReport1(1) = CByte(x(usernum))
            'InputReport1(2) = CByte(y(usernum))
            'InputReport1(3) = CByte(0)
            'InputReport1(4) = CByte(0)
    
            'make sure byte is below 255 because thats the max it can be in integer or other format.
            If x(usernum) <= 255 And y(usernum) <= 255 Then
                'InputReportMain.SetValue(CByte(0), 0)
                'InputReportMain.SetValue(CByte(100), 1)
                'InputReportMain.SetValue(CByte(100), 2)
                'InputReportMain.SetValue(CByte(0), 3)
                'InputReportMain.SetValue(CByte(0), 4)
                'GenericHIDDev(usernum).devInputReportBytes(InputReport1)
                GenericHIDDev(usernum).QueueInputReport(InputReportMain, 10)
                GenericHIDDev(usernum).StartProcessing()
            End If
    
            sendinputreport = True
        End Function

    I think either my timeout for sending the inputreport is too high or I have problems with the way the c++ side is handling the data. Because I verified via messagebox the data was passed correctly.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Monday, July 15, 2013 5:07 PM
  • I don't think the different fFeatures flags are a problem.  VBScript is passing the extra flags FADF_STATIC = 0x0002 and FADF_FIXEDSIZE = 0x0010.  These flags don't matter because the C++ code doesn't try to resize or free the array.

    Instead, you could try:

    • Check the COM apartment type.  The .NET Framework uses the MTA by default (unless overridden with STAThreadAttribute in the Main method, or by calling Thread.SetApartmentState), but I think Windows Script Host uses STA.  Because src\test\dsf\usb\GenericHID\HIDDevice.rgs sets val ThreadingModel = s 'Apartment', COM should create the HIDDevice objects in an STA in any case; but the marshaling from MTA to STA can reveal latent bugs.  So, move your VB.NET code to an STA thread and see if that helps.
    • The sample code in src\test\dsf\usb\GenericHID\TestGenericHid.wsf calls many more methods than the VB.NET code you posted.  Perhaps you omitted some of those calls and that caused the BSOD.  Try removing calls from the VBScript code so that it matches your VB.NET code; does the VBScript code then cause a BSOD too?


    Change the report descriptors to reportdescriptorsmouse variable and plug in my code and it works into the default code. just replace x(usernum) and y(usernum) with static values too. Trying this out hope it works but not sure.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    I forgot to mention Iam calling this from a dll. The source code is here: http://kinectmultipoint.codeplex.com. click on the dsf mouse wrapper library vb.net version under downloads. Its the same code I have now. I released that version 4 days ago but I have not changed it. See if you can see whats wrong. The dsf runtime is important but I also changed softhidreceiver.dll's buildhiddescriptors safearray to the correct device so I would not have to use create custom report descriptors and create custom hid descriptors functions like the script uses.

    Look at how I just changed the testgenerichid.wsf file to multiple devices? Edit:Iam having trouble with changing to STA. So far this is what I have done:

    1. put the below code into form load event.

    2. put the below code into my.application.startup event.

    Thread.CurrentThread.SetApartmentState(ApartmentState.STA)


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr







    Okay since pbInputReport accepts byte format I created a byte function called devInputReportBytes  in my unmanaged c++ com dll which I send in a parameter which is of BYTE format (now char array but was originally byte). I think it might be working now but I will up the mouse values in testing to make sure. But if it works I will mark your post about using bytes as answer.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    Darn it accepts it but does not move the mouse. Let me look through and see what i did wrong.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Heres the updated vb.net code I tried that does let me send to the safearray but does not move the mouse device:

     Public Function sendinputreport(xcoord As Integer, ycoord As Integer, leftclick As Boolean, rightclick As Boolean) As Boolean
            'device report to send to computer (x,y coordinates, left or right clicks, and scrolling).
            'file contents:
            'number of devices
            'x for dev1
            'y for dev1
            'left click for dev1
            'x for dev2
            'y for dev2
            'left click for dev2
    
            Dim x(40), y(40) As Integer
            x(usernum) = xcoord
            y(usernum) = ycoord
            MsgBox(x(usernum))
            Dim InputReport1() As Object = New Object(4) {CByte(0), CByte(x(usernum)), CByte(y(usernum)), CByte(0), CByte(0)}
            Dim InputReportMain As System.Array = Array.CreateInstance(GetType(Byte), 5)
            InputReportMain = InputReport1
            'InputReport1(0) = CByte(0)
            'InputReport1(1) = CByte(x(usernum))
            'InputReport1(2) = CByte(y(usernum))
            'InputReport1(3) = CByte(0)
            'InputReport1(4) = CByte(0)
    
            'make sure byte is below 255 because thats the max it can be in integer or other format.
            If x(usernum) <= 255 And y(usernum) <= 255 Then
                'InputReportMain.SetValue(CByte(0), 0)
                'InputReportMain.SetValue(CByte(100), 1)
                'InputReportMain.SetValue(CByte(100), 2)
                'InputReportMain.SetValue(CByte(0), 3)
                'InputReportMain.SetValue(CByte(0), 4)
                'GenericHIDDev(usernum).devInputReportBytes(InputReport1)
                GenericHIDDev(usernum).QueueInputReport(InputReportMain, 10)
                GenericHIDDev(usernum).StartProcessing()
            End If
    
            sendinputreport = True
        End Function

    I think either my timeout for sending the inputreport is too high or I have problems with the way the c++ side is handling the data. Because I verified via messagebox the data was passed correctly.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    I thought of one more possiblity which is that it appears its passing the data similarily this time but the driver or c++ code is just not accepting the format instead of crashing. The fFeatures for the safearray is still 2176. Anyone know how to declare a fixedlength array and static array in vb.net? Edit: I just used vbscript and it passes exactly the same data as the updated code above except those parameters are missing. Any chance anyone know how to make a variable static and of fixed length?

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    • Edited by The Thinker Tuesday, July 16, 2013 12:09 AM edit 3
    Monday, July 15, 2013 6:58 PM
  • I don't think the different fFeatures flags are a problem.  VBScript is passing the extra flags FADF_STATIC = 0x0002 and FADF_FIXEDSIZE = 0x0010.  These flags don't matter because the C++ code doesn't try to resize or free the array.

    Instead, you could try:

    • Check the COM apartment type.  The .NET Framework uses the MTA by default (unless overridden with STAThreadAttribute in the Main method, or by calling Thread.SetApartmentState), but I think Windows Script Host uses STA.  Because src\test\dsf\usb\GenericHID\HIDDevice.rgs sets val ThreadingModel = s 'Apartment', COM should create the HIDDevice objects in an STA in any case; but the marshaling from MTA to STA can reveal latent bugs.  So, move your VB.NET code to an STA thread and see if that helps.
    • The sample code in src\test\dsf\usb\GenericHID\TestGenericHid.wsf calls many more methods than the VB.NET code you posted.  Perhaps you omitted some of those calls and that caused the BSOD.  Try removing calls from the VBScript code so that it matches your VB.NET code; does the VBScript code then cause a BSOD too?


    Change the report descriptors to reportdescriptorsmouse variable and plug in my code and it works into the default code. just replace x(usernum) and y(usernum) with static values too. Trying this out hope it works but not sure.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    I forgot to mention Iam calling this from a dll. The source code is here: http://kinectmultipoint.codeplex.com. click on the dsf mouse wrapper library vb.net version under downloads. Its the same code I have now. I released that version 4 days ago but I have not changed it. See if you can see whats wrong. The dsf runtime is important but I also changed softhidreceiver.dll's buildhiddescriptors safearray to the correct device so I would not have to use create custom report descriptors and create custom hid descriptors functions like the script uses.

    Look at how I just changed the testgenerichid.wsf file to multiple devices? Edit:Iam having trouble with changing to STA. So far this is what I have done:

    1. put the below code into form load event.

    2. put the below code into my.application.startup event.

    Thread.CurrentThread.SetApartmentState(ApartmentState.STA)


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr







    Okay since pbInputReport accepts byte format I created a byte function called devInputReportBytes  in my unmanaged c++ com dll which I send in a parameter which is of BYTE format (now char array but was originally byte). I think it might be working now but I will up the mouse values in testing to make sure. But if it works I will mark your post about using bytes as answer.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    Darn it accepts it but does not move the mouse. Let me look through and see what i did wrong.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Heres the updated vb.net code I tried that does let me send to the safearray but does not move the mouse device:

     Public Function sendinputreport(xcoord As Integer, ycoord As Integer, leftclick As Boolean, rightclick As Boolean) As Boolean
            'device report to send to computer (x,y coordinates, left or right clicks, and scrolling).
            'file contents:
            'number of devices
            'x for dev1
            'y for dev1
            'left click for dev1
            'x for dev2
            'y for dev2
            'left click for dev2
    
            Dim x(40), y(40) As Integer
            x(usernum) = xcoord
            y(usernum) = ycoord
            MsgBox(x(usernum))
            Dim InputReport1() As Object = New Object(4) {CByte(0), CByte(x(usernum)), CByte(y(usernum)), CByte(0), CByte(0)}
            Dim InputReportMain As System.Array = Array.CreateInstance(GetType(Byte), 5)
            InputReportMain = InputReport1
            'InputReport1(0) = CByte(0)
            'InputReport1(1) = CByte(x(usernum))
            'InputReport1(2) = CByte(y(usernum))
            'InputReport1(3) = CByte(0)
            'InputReport1(4) = CByte(0)
    
            'make sure byte is below 255 because thats the max it can be in integer or other format.
            If x(usernum) <= 255 And y(usernum) <= 255 Then
                'InputReportMain.SetValue(CByte(0), 0)
                'InputReportMain.SetValue(CByte(100), 1)
                'InputReportMain.SetValue(CByte(100), 2)
                'InputReportMain.SetValue(CByte(0), 3)
                'InputReportMain.SetValue(CByte(0), 4)
                'GenericHIDDev(usernum).devInputReportBytes(InputReport1)
                GenericHIDDev(usernum).QueueInputReport(InputReportMain, 10)
                GenericHIDDev(usernum).StartProcessing()
            End If
    
            sendinputreport = True
        End Function

    I think either my timeout for sending the inputreport is too high or I have problems with the way the c++ side is handling the data. Because I verified via messagebox the data was passed correctly.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    I thought of one more possiblity which is that it appears its passing the data similarily this time but the driver or c++ code is just not accepting the format instead of crashing. The fFeatures for the safearray is still 2176. Anyone know how to declare a fixedlength array and static array in vb.net? Edit: I just used vbscript and it passes exactly the same data as the updated code above except those parameters are missing. Any chance anyone know how to make a variable static and of fixed length?

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr



    anyone have any ideas? Iam going to submit this as a bug if no-one can solve it.

    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr

    Thursday, July 18, 2013 5:48 PM