none
Invalid safearray of variants? RRS feed

  • Question

  • STDMETHODIMP CMMEmulator::sendinputreport(BYTE inputreport[5], int length)
    {
    	// TODO: Add your implementation code here
    		 _TCHAR szBuffer[100];
        _stprintf_s(szBuffer, _T("%i"), inputreport[1]);
      
    	MessageBox(NULL,L"value of second byte input report",szBuffer,NULL);
    	SAFEARRAY *test = new SAFEARRAY;
    	  VARIANT HUGEP* pDescriptorData  = NULL;
    	// Create a boundary struct to pass in when we create the SafeArray
        SAFEARRAYBOUND rgsabound[1];
        ZeroMemory(rgsabound, sizeof(rgsabound));
        rgsabound[0].lLbound = 0;
        rgsabound[0].cElements = 4;
      
        // Create as an Array of Variants becuase that is what the DSF 
        // Interface->put_DeviceSpecificDescriptor is expecting an array of Variants
        test = SafeArrayCreate(VT_VARIANT, 1, rgsabound );
          test->fFeatures = 2194;
        if( test == NULL )
        {
            // if the create failed, then goto to exit
            hr = E_UNEXPECTED;
            goto Exit;
        }
        
        SafeArrayAccessData(test, (void HUGEP**)&pDescriptorData);
    
        // Step through the SAFEARRAY and populate each variant with a Byte value
        //INT descSize2 = sizeof(inputreport);
        for( INT i = 0; i < 4; ++i )
        {
           pDescriptorData[i].vt = VT_UI1;
            pDescriptorData[i].bVal = inputreport[i];
        }
    	 _TCHAR szBuffer2[100];
        _stprintf_s(szBuffer2, _T("%i"), test->fFeatures);
    	MessageBox(NULL,L"safe array type",szBuffer2,NULL);
    	piSoftHidDevice1[devindex]->QueueInputReport(test,10);
    	piSoftHidDevice1[devindex]->StartProcessing();
    	piSoftHidDevice1[devindex]->StopProcessing();
    	SafeArrayUnaccessData(test);
    	return S_OK;
    	Exit:
    SafeArrayUnaccessData(test);
     
       return hr;
    }

    as you can see above I was trying to assign the byte values to the variants inside a safearray and send this safe array to another sub/function called queueinputreport that has its safearray declared like this: queueinputreport( SAFEARRAY* psaInputReport,UINT timeoutduration). In the idl for the c++ project the safe array is defined as queueinputreport(SAFEARRAY(VARIANT), UINT timeoutduration). How can I pass a safearray correctly to queueinputreport? I have a messagebox inside queueinputreport that does tell me its values but it reports that the values are correctly passed so it confuses why it does not use that data and work. I believe this to be incorrectly formatted data being passed to the other safearray but have no clue where Iam going wrong? Can someone step in and help me out?

    P.S. Iam not good with safearrays yet so if I have done something wrong feel free to point it out. I am trying to pass a safearray to softhidreceiver.dll included with Microsoft's device simulation framework that's where I get queueinputreport.


    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 20, 2013 9:30 PM edit 6
    Saturday, July 20, 2013 8:41 PM

Answers

  • appoligize for the my initial solution, that was incorrect. 

    here i am trying to demonstrate how to pass an array of VARIANTS to a COM Dll and use it inside the dll.

    first the COM Dll(server side code), in this Component, i have created a method which will accept an array of VARIANTs from the Client side

    void PrintVariant(VARIANT *pV)
    {
      switch(pV->vt)
      {
      case VT_UI1:
        wprintf(L"  Integer: %x\r\n", pV->bVal);
        break;
      default:
        wprintf(L"  Unrecognized Type: vt=%d\r\n", pV->vt);
        break;
      }
    }
    
    STDMETHODIMP CSample::FillWithVariantAtClient(SAFEARRAY*  arrOfVariants)
    {
    	SafeArrayLock(arrOfVariants);
    
    	VARIANT *valueArray = (VARIANT *)arrOfVariants->pvData;
    
    	long lBound=0,uBound=0;
    	SafeArrayGetLBound(arrOfVariants, 1, &lBound);
    	SafeArrayGetUBound(arrOfVariants, 1, &uBound);
    
    
    	for(int i=lBound;i<=uBound;i++)
    		PrintVariant(&valueArray[i]);
    
    	SafeArrayUnlock(arrOfVariants);
    
    	//done with the array, so destroying
    	SafeArrayDestroy(arrOfVariants);
    
    	return S_OK;
    }

    Client Side Code:

    int _tmain(int argc, _TCHAR* argv[])
    {
    	CoInitialize(NULL);
    	{
    		ISamplePtr ptr;
    		ptr.CreateInstance(__uuidof(Sample));
    		
    		SAFEARRAYBOUND rgsabound;
    		rgsabound.lLbound = 0;
    		rgsabound.cElements = 4;
    
    		LPSAFEARRAY psaValues = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
    		BYTE bSampe[4] = {0x01,0x02,0x03,0x04};
    		SafeArrayLock(psaValues);
    		VARIANT *pDescriptorData = (VARIANT *)psaValues->pvData;
    
    		for( LONG i = 0; i < 4; ++i )
    		{
    		    VariantClear(&pDescriptorData[i]);
                        pDescriptorData[i].vt = VT_UI1;
                        pDescriptorData[i].bVal = bSampe[i];
    		    SafeArrayPutElement(psaValues,&i,&pDescriptorData);
    		}
    		SafeArrayUnlock(psaValues);
    
    		ptr->FillWithVariantAtClient(psaValues);
    			
    	}
    	::CoUninitialize();
    	return 0;
    }

    now i think you can do the changes for your code. 


    • Edited by Pradish.MP Sunday, July 21, 2013 6:08 PM edit
    • Marked as answer by The Thinker Thursday, August 8, 2013 8:16 PM
    Sunday, July 21, 2013 5:29 PM

All replies

  • STDMETHODIMP CMMEmulator::sendinputreport(BYTE inputreport[5], int length)
    {
    	// TODO: Add your implementation code here
    		 _TCHAR szBuffer[100];
        _stprintf_s(szBuffer, _T("%i"), inputreport[1]);
      
    	MessageBox(NULL,L"value of second byte input report",szBuffer,NULL);
    	SAFEARRAY *test = new SAFEARRAY;
    	  VARIANT HUGEP* pDescriptorData  = NULL;
    	// Create a boundary struct to pass in when we create the SafeArray
        SAFEARRAYBOUND rgsabound[1];
        ZeroMemory(rgsabound, sizeof(rgsabound));
        rgsabound[0].lLbound = 0;
        rgsabound[0].cElements = 4;
      
        // Create as an Array of Variants becuase that is what the DSF 
        // Interface->put_DeviceSpecificDescriptor is expecting an array of Variants
        test = SafeArrayCreate(VT_VARIANT, 1, rgsabound );
          test->fFeatures = 2194;
        if( test == NULL )
        {
            // if the create failed, then goto to exit
            hr = E_UNEXPECTED;
            goto Exit;
        }
        
        SafeArrayAccessData(test, (void HUGEP**)&pDescriptorData);
    
        // Step through the SAFEARRAY and populate each variant with a Byte value
        //INT descSize2 = sizeof(inputreport);
        for( INT i = 0; i < 4; ++i )
        {
           pDescriptorData[i].vt = VT_UI1;
            pDescriptorData[i].bVal = inputreport[i];
        }
    	 _TCHAR szBuffer2[100];
        _stprintf_s(szBuffer2, _T("%i"), test->fFeatures);
    	MessageBox(NULL,L"safe array type",szBuffer2,NULL);
    	piSoftHidDevice1[devindex]->QueueInputReport(test,10);
    	piSoftHidDevice1[devindex]->StartProcessing();
    	piSoftHidDevice1[devindex]->StopProcessing();
    	SafeArrayUnaccessData(test);
    	return S_OK;
    	Exit:
    SafeArrayUnaccessData(test);
     
       return hr;
    }

    as you can see above I was trying to assign the byte values to the variants inside a safearray and send this safe array to another sub/function called queueinputreport that has its safearray declared like this: queueinputreport( SAFEARRAY* psaInputReport,UINT timeoutduration). In the idl for the c++ project the safe array is defined as queueinputreport(SAFEARRAY(VARIANT), UINT timeoutduration). How can I pass a safearray correctly to queueinputreport? I have a messagebox inside queueinputreport that does tell me its values but it reports that the values are correctly passed so it confuses why it does not use that data and work. I believe this to be incorrectly formatted data being passed to the other safearray but have no clue where Iam going wrong? Can someone step in and help me out?

    P.S. Iam not good with safearrays yet so if I have done something wrong feel free to point it out. I am trying to pass a safearray to softhidreceiver.dll included with Microsoft's device simulation framework. 


    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



    additional Notes: the safearray of variants is one-dimensional.

    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 20, 2013 11:47 PM edit 3
    Saturday, July 20, 2013 9:29 PM
  • STDMETHODIMP CMMEmulator::sendinputreport(BYTE inputreport[5], int length)
    {
    	// TODO: Add your implementation code here
    		 _TCHAR szBuffer[100];
        _stprintf_s(szBuffer, _T("%i"), inputreport[1]);
      
    	MessageBox(NULL,L"value of second byte input report",szBuffer,NULL);
    	SAFEARRAY *test = new SAFEARRAY;
    	  VARIANT HUGEP* pDescriptorData  = NULL;
    	// Create a boundary struct to pass in when we create the SafeArray
        SAFEARRAYBOUND rgsabound[1];
        ZeroMemory(rgsabound, sizeof(rgsabound));
        rgsabound[0].lLbound = 0;
        rgsabound[0].cElements = 4;
      
        // Create as an Array of Variants becuase that is what the DSF 
        // Interface->put_DeviceSpecificDescriptor is expecting an array of Variants
        test = SafeArrayCreate(VT_VARIANT, 1, rgsabound );
          test->fFeatures = 2194;
        if( test == NULL )
        {
            // if the create failed, then goto to exit
            hr = E_UNEXPECTED;
            goto Exit;
        }
        
        SafeArrayAccessData(test, (void HUGEP**)&pDescriptorData);
    
        // Step through the SAFEARRAY and populate each variant with a Byte value
        //INT descSize2 = sizeof(inputreport);
        for( INT i = 0; i < 4; ++i )
        {
           pDescriptorData[i].vt = VT_UI1;
            pDescriptorData[i].bVal = inputreport[i];
        }
    	 _TCHAR szBuffer2[100];
        _stprintf_s(szBuffer2, _T("%i"), test->fFeatures);
    	MessageBox(NULL,L"safe array type",szBuffer2,NULL);
    	piSoftHidDevice1[devindex]->QueueInputReport(test,10);
    	piSoftHidDevice1[devindex]->StartProcessing();
    	piSoftHidDevice1[devindex]->StopProcessing();
    	SafeArrayUnaccessData(test);
    	return S_OK;
    	Exit:
    SafeArrayUnaccessData(test);
     
       return hr;
    }

    as you can see above I was trying to assign the byte values to the variants inside a safearray and send this safe array to another sub/function called queueinputreport that has its safearray declared like this: queueinputreport( SAFEARRAY* psaInputReport,UINT timeoutduration). In the idl for the c++ project the safe array is defined as queueinputreport(SAFEARRAY(VARIANT), UINT timeoutduration). How can I pass a safearray correctly to queueinputreport? I have a messagebox inside queueinputreport that does tell me its values but it reports that the values are correctly passed so it confuses why it does not use that data and work. I believe this to be incorrectly formatted data being passed to the other safearray but have no clue where Iam going wrong? Can someone step in and help me out?

    P.S. Iam not good with safearrays yet so if I have done something wrong feel free to point it out. I am trying to pass a safearray to softhidreceiver.dll included with Microsoft's device simulation framework. 


    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



    additional Notes: the safearray of variants is one-dimensional.

    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


    The way the data shows up in the safearray is important. for this one I need the data to be in an input report as described here: http://msdn.microsoft.com/en-us/library/ff539939.aspx. I am doing a mouse device but if I remember correctly from my discussion with the wdk guys the data should be like this in the safe array, have 4 dimensions, and needs to be of type VT_UI1 (IMPORTANT the safearray variant type needs to be VT_UI1 or BYTE format!).  I am just not for sure about how to send a one-dimensional safearray of variants that contain data in the format of VT_UI1. Anyone have any generic code samples to play around with? At this point anything that that is close to play with will help me. I just reference the data so you had an idea of what Iam sending which would be: Mouse scroll wheel? (how much to move), mouse x coordinates, mouse y coordinates, left button? (same values as right mouse click), right mouse button click? (0 for down and 1 byte value for up).

    If it were a c++ byte array the test values would be for now:

    BYTE test[4];

    test[0] =0x00;

    test[1]= 0x100;

    test[2]= 0x100;

    test[3]= 0x00;

    test[4]= 0x00;

    Edit: heres the sample code Iam calling from the wdk 7.1:

    http://msdn.microsoft.com/en-us/library/ff538334.aspx


    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 Sunday, July 21, 2013 1:09 AM edit 8
    Sunday, July 21, 2013 1:03 AM
  • can try the following changes to the above code and try, i am not 100% sure weather it will work, but you can give it a try, i have done some changes to your code 

    	_TCHAR szBuffer[100];
        _stprintf_s(szBuffer, _T("%i"), inputreport[1]);
      
    	MessageBox(NULL,L"value of second byte input report",szBuffer,NULL);
    	//SAFEARRAY *test = new SAFEARRAY;
    	VARIANT HUGEP* pDescriptorData  = NULL;
    	VariantInit(pDescriptorData);
    
    	// Create a boundary struct to pass in when we create the SafeArray
        SAFEARRAYBOUND rgsabound[1];
        ZeroMemory(rgsabound, sizeof(rgsabound));
        rgsabound[0].lLbound = 0;
        rgsabound[0].cElements = 4;
    
    	pDescriptorData->vt = VT_VARIANT | VT_ARRAY; 
    	pDescriptorData->parray = SafeArrayCreate(VT_VARIANT,1,rgsabound);
    	pDescriptorData->parray->fFeatures = 2194;
      
       
    	// Create as an Array of Variants becuase that is what the DSF 
        // Interface->put_DeviceSpecificDescriptor is expecting an array of Variants
        //test = SafeArrayCreate(VT_VARIANT, 1, rgsabound );
        //  test->fFeatures = 2194;
       // if( test == NULL )
       // {
            // if the create failed, then goto to exit
        //    hr = E_UNEXPECTED;
         //   goto Exit;
       // }
        
       // SafeArrayAccessData(test, (void HUGEP**)&pDescriptorData);
    
        // Step through the SAFEARRAY and populate each variant with a Byte value
        //INT descSize2 = sizeof(inputreport);
        for( LONG i = 0; i < 4; ++i )
        {
           pDescriptorData[i].vt = VT_UI1;
            pDescriptorData[i].bVal = inputreport[i];
    		SafeArrayPutElement(pDescriptorData->parray,&i,pDescriptorData);
        }
    
    	 _TCHAR szBuffer2[100];
        _stprintf_s(szBuffer2, _T("%i"), test->fFeatures);
    	MessageBox(NULL,L"safe array type",szBuffer2,NULL);
    	piSoftHidDevice1[devindex]->QueueInputReport(pDescriptorData->parray,10);
    	piSoftHidDevice1[devindex]->StartProcessing();
    	piSoftHidDevice1[devindex]->StopProcessing();
    	//SafeArrayUnaccessData(test);
    	return S_OK;
    	Exit:
    	//SafeArrayUnaccessData(test);
    


    • Edited by Pradish.MP Sunday, July 21, 2013 6:42 AM edit
    Sunday, July 21, 2013 6:14 AM
  • can try the following changes to the above code and try, i am not 100% sure weather it will work, but you can give it a try, i have done some changes to your code 

    	_TCHAR szBuffer[100];
        _stprintf_s(szBuffer, _T("%i"), inputreport[1]);
      
    	MessageBox(NULL,L"value of second byte input report",szBuffer,NULL);
    	//SAFEARRAY *test = new SAFEARRAY;
    	VARIANT HUGEP* pDescriptorData  = NULL;
    	VariantInit(pDescriptorData);
    
    	// Create a boundary struct to pass in when we create the SafeArray
        SAFEARRAYBOUND rgsabound[1];
        ZeroMemory(rgsabound, sizeof(rgsabound));
        rgsabound[0].lLbound = 0;
        rgsabound[0].cElements = 4;
    
    	pDescriptorData->vt = VT_VARIANT | VT_ARRAY; 
    	pDescriptorData->parray = SafeArrayCreate(VT_VARIANT,1,rgsabound);
    	pDescriptorData->parray->fFeatures = 2194;
      
       
    	// Create as an Array of Variants becuase that is what the DSF 
        // Interface->put_DeviceSpecificDescriptor is expecting an array of Variants
        //test = SafeArrayCreate(VT_VARIANT, 1, rgsabound );
        //  test->fFeatures = 2194;
       // if( test == NULL )
       // {
            // if the create failed, then goto to exit
        //    hr = E_UNEXPECTED;
         //   goto Exit;
       // }
        
       // SafeArrayAccessData(test, (void HUGEP**)&pDescriptorData);
    
        // Step through the SAFEARRAY and populate each variant with a Byte value
        //INT descSize2 = sizeof(inputreport);
        for( LONG i = 0; i < 4; ++i )
        {
           pDescriptorData[i].vt = VT_UI1;
            pDescriptorData[i].bVal = inputreport[i];
    		SafeArrayPutElement(pDescriptorData->parray,&i,pDescriptorData);
        }
    
    	 _TCHAR szBuffer2[100];
        _stprintf_s(szBuffer2, _T("%i"), test->fFeatures);
    	MessageBox(NULL,L"safe array type",szBuffer2,NULL);
    	piSoftHidDevice1[devindex]->QueueInputReport(pDescriptorData->parray,10);
    	piSoftHidDevice1[devindex]->StartProcessing();
    	piSoftHidDevice1[devindex]->StopProcessing();
    	//SafeArrayUnaccessData(test);
    	return S_OK;
    	Exit:
    	//SafeArrayUnaccessData(test);



    I get an access violation about protected memory when trying to use that code.  I will restart my application before I try anything else.

    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 21, 2013 3:46 PM
  • can try the following changes to the above code and try, i am not 100% sure weather it will work, but you can give it a try, i have done some changes to your code 

    	_TCHAR szBuffer[100];
        _stprintf_s(szBuffer, _T("%i"), inputreport[1]);
      
    	MessageBox(NULL,L"value of second byte input report",szBuffer,NULL);
    	//SAFEARRAY *test = new SAFEARRAY;
    	VARIANT HUGEP* pDescriptorData  = NULL;
    	VariantInit(pDescriptorData);
    
    	// Create a boundary struct to pass in when we create the SafeArray
        SAFEARRAYBOUND rgsabound[1];
        ZeroMemory(rgsabound, sizeof(rgsabound));
        rgsabound[0].lLbound = 0;
        rgsabound[0].cElements = 4;
    
    	pDescriptorData->vt = VT_VARIANT | VT_ARRAY; 
    	pDescriptorData->parray = SafeArrayCreate(VT_VARIANT,1,rgsabound);
    	pDescriptorData->parray->fFeatures = 2194;
      
       
    	// Create as an Array of Variants becuase that is what the DSF 
        // Interface->put_DeviceSpecificDescriptor is expecting an array of Variants
        //test = SafeArrayCreate(VT_VARIANT, 1, rgsabound );
        //  test->fFeatures = 2194;
       // if( test == NULL )
       // {
            // if the create failed, then goto to exit
        //    hr = E_UNEXPECTED;
         //   goto Exit;
       // }
        
       // SafeArrayAccessData(test, (void HUGEP**)&pDescriptorData);
    
        // Step through the SAFEARRAY and populate each variant with a Byte value
        //INT descSize2 = sizeof(inputreport);
        for( LONG i = 0; i < 4; ++i )
        {
           pDescriptorData[i].vt = VT_UI1;
            pDescriptorData[i].bVal = inputreport[i];
    		SafeArrayPutElement(pDescriptorData->parray,&i,pDescriptorData);
        }
    
    	 _TCHAR szBuffer2[100];
        _stprintf_s(szBuffer2, _T("%i"), test->fFeatures);
    	MessageBox(NULL,L"safe array type",szBuffer2,NULL);
    	piSoftHidDevice1[devindex]->QueueInputReport(pDescriptorData->parray,10);
    	piSoftHidDevice1[devindex]->StartProcessing();
    	piSoftHidDevice1[devindex]->StopProcessing();
    	//SafeArrayUnaccessData(test);
    	return S_OK;
    	Exit:
    	//SafeArrayUnaccessData(test);



    I get an access violation about protected memory when trying to use that code.  I will restart my application before I try anything else.

    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


    No, still same thing as before. I get access violation exception when calling this from dotnet and this message: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. Note: I have this c++ code in a dll that is called from dotnet. This project's code is here and open source: http://kinectmultipoint.codeplex.com. So feel free to edit it at any time and re-upload a patch to help out. This code is for an emulator/simulator I was creating using the dotnet framework but it can be change to any device by changing the report descriptors when I am done with it. My objective was to control multiple devices so the call above will be repeated. length above is really supposed to be the length of the array. I have it their for future uses but for our scenario its not needed. The code for queueinputreport is in the wdk 7.1 but I know it checks for VT_UI1 type. I'll post the code for it if you would like me to.

    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 Sunday, July 21, 2013 4:01 PM edit 5
    Sunday, July 21, 2013 3:48 PM
  • i have never used the fFeatures member of SAFEARRAY, can you comment that and line and check.

    as you are creating an array of 4 elements , but deallocating 2194...can you tell me why?

    pDescriptorData->parray->fFeatures = 2194;

    Sunday, July 21, 2013 4:25 PM
  • i have never used the fFeatures member of SAFEARRAY, can you comment that and line and check.

    as you are creating an array of 4 elements , but deallocating 2194...can you tell me why?

    pDescriptorData->parray->fFeatures = 2194;

    Heres the full queueinputreport for reference:

    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;
    	//psaInputReport->fFeatures = 0x892;
        
    	inputReport.pbInputReport = (BYTE*)CoTaskMemAlloc( cbData * sizeof(BYTE) );
         _TCHAR szBuffer3[100];
        _stprintf_s(szBuffer3, _T("%i"), psaInputReport->fFeatures);
      	MessageBox(NULL,L"array content",szBuffer3,NULL);
        // 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)
            {
    			 _TCHAR szBuffer[100];
        _stprintf_s(szBuffer, _T("%i"), pArrayData[i].bVal);
      	MessageBox(NULL,L"array content",szBuffer,NULL);	
                inputReport.pbInputReport[i-lLBound] = pArrayData[i].bVal;
    //			 _TCHAR szBuffer2[100];
       /* _stprintf_s(szBuffer2, _T("%i"), inputReport.pbInputReport[i]);
      	MessageBox(NULL,L"input report array content",szBuffer,NULL);*/
            }
            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)
        {
    		MessageBox(NULL,L"failed to queue the input",NULL,NULL);
            hr = E_FAIL;
        }
    
    Exit:
        SafeArrayUnaccessData(psaInputReport);
        if( FAILED(hr) )
        {
            CoTaskMemFree(inputReport.pbInputReport);
        }
        return hr;
    }

    If their are major errors in this code then I can correct them but this is from the offical microsoft wdk 7.1. Maybe it will help you but I was afraid to change anything unless someone knowledgeable in safearrays could safely help me change it. This is mostly the default code microsoft created except for the messagebox's which I added in for debug purposes.

    Edit: did not work commenting out the fFeatures part.


    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 Sunday, July 21, 2013 5:10 PM edit 5
    Sunday, July 21, 2013 4:50 PM
  • i have never used the fFeatures member of SAFEARRAY, can you comment that and line and check.

    as you are creating an array of 4 elements , but deallocating 2194...can you tell me why?

    pDescriptorData->parray->fFeatures = 2194;

    Heres the full queueinputreport for reference:

    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;
    	//psaInputReport->fFeatures = 0x892;
        
    	inputReport.pbInputReport = (BYTE*)CoTaskMemAlloc( cbData * sizeof(BYTE) );
         _TCHAR szBuffer3[100];
        _stprintf_s(szBuffer3, _T("%i"), psaInputReport->fFeatures);
      	MessageBox(NULL,L"array content",szBuffer3,NULL);
        // 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)
            {
    			 _TCHAR szBuffer[100];
        _stprintf_s(szBuffer, _T("%i"), pArrayData[i].bVal);
      	MessageBox(NULL,L"array content",szBuffer,NULL);	
                inputReport.pbInputReport[i-lLBound] = pArrayData[i].bVal;
    //			 _TCHAR szBuffer2[100];
       /* _stprintf_s(szBuffer2, _T("%i"), inputReport.pbInputReport[i]);
      	MessageBox(NULL,L"input report array content",szBuffer,NULL);*/
            }
            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)
        {
    		MessageBox(NULL,L"failed to queue the input",NULL,NULL);
            hr = E_FAIL;
        }
    
    Exit:
        SafeArrayUnaccessData(psaInputReport);
        if( FAILED(hr) )
        {
            CoTaskMemFree(inputReport.pbInputReport);
        }
        return hr;
    }

    If their are major errors in this code then I can correct them but this is from the offical microsoft wdk 7.1. Maybe it will help you but I was afraid to change anything unless someone knowledgeable in safearrays could safely help me change it. This is mostly the default code microsoft created except for the messagebox's which I added in for debug purposes.

    Edit: did not work commenting out the fFeatures part.


    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 about where the crash occurs from looking into the safearray problem:

    VARIANT HUGEP* pDescriptorData  = NULL;
    	VariantInit(pDescriptorData);
    
    	// Create a boundary struct to pass in when we create the SafeArray
        SAFEARRAYBOUND rgsabound[1];
       // ZeroMemory(rgsabound, sizeof(rgsabound));
        rgsabound[0].lLbound = 0;
        rgsabound[0].cElements = 4;
    	
    	pDescriptorData->vt = VT_VARIANT|VT_ARRAY; 
    	pDescriptorData->parray = SafeArrayCreate(VT_VARIANT,1,rgsabound);
    	//pDescriptorData->parray->fFeatures = 2194;
        MessageBox(NULL,L"safe array created" ,NULL,NULL);
    It does not even reach the queueinputreport before it fails. could it be the bounds are wrong or variantinit?


    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 21, 2013 5:26 PM
  • appoligize for the my initial solution, that was incorrect. 

    here i am trying to demonstrate how to pass an array of VARIANTS to a COM Dll and use it inside the dll.

    first the COM Dll(server side code), in this Component, i have created a method which will accept an array of VARIANTs from the Client side

    void PrintVariant(VARIANT *pV)
    {
      switch(pV->vt)
      {
      case VT_UI1:
        wprintf(L"  Integer: %x\r\n", pV->bVal);
        break;
      default:
        wprintf(L"  Unrecognized Type: vt=%d\r\n", pV->vt);
        break;
      }
    }
    
    STDMETHODIMP CSample::FillWithVariantAtClient(SAFEARRAY*  arrOfVariants)
    {
    	SafeArrayLock(arrOfVariants);
    
    	VARIANT *valueArray = (VARIANT *)arrOfVariants->pvData;
    
    	long lBound=0,uBound=0;
    	SafeArrayGetLBound(arrOfVariants, 1, &lBound);
    	SafeArrayGetUBound(arrOfVariants, 1, &uBound);
    
    
    	for(int i=lBound;i<=uBound;i++)
    		PrintVariant(&valueArray[i]);
    
    	SafeArrayUnlock(arrOfVariants);
    
    	//done with the array, so destroying
    	SafeArrayDestroy(arrOfVariants);
    
    	return S_OK;
    }

    Client Side Code:

    int _tmain(int argc, _TCHAR* argv[])
    {
    	CoInitialize(NULL);
    	{
    		ISamplePtr ptr;
    		ptr.CreateInstance(__uuidof(Sample));
    		
    		SAFEARRAYBOUND rgsabound;
    		rgsabound.lLbound = 0;
    		rgsabound.cElements = 4;
    
    		LPSAFEARRAY psaValues = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
    		BYTE bSampe[4] = {0x01,0x02,0x03,0x04};
    		SafeArrayLock(psaValues);
    		VARIANT *pDescriptorData = (VARIANT *)psaValues->pvData;
    
    		for( LONG i = 0; i < 4; ++i )
    		{
    		    VariantClear(&pDescriptorData[i]);
                        pDescriptorData[i].vt = VT_UI1;
                        pDescriptorData[i].bVal = bSampe[i];
    		    SafeArrayPutElement(psaValues,&i,&pDescriptorData);
    		}
    		SafeArrayUnlock(psaValues);
    
    		ptr->FillWithVariantAtClient(psaValues);
    			
    	}
    	::CoUninitialize();
    	return 0;
    }

    now i think you can do the changes for your code. 


    • Edited by Pradish.MP Sunday, July 21, 2013 6:08 PM edit
    • Marked as answer by The Thinker Thursday, August 8, 2013 8:16 PM
    Sunday, July 21, 2013 5:29 PM
  • appoligize for the my initial solution, that was incorrect. 

    here i am trying to demonstrate how to pass an array of VARIANTS to a COM Dll and use it inside the dll.

    first the COM Dll(server side code), in this Component, i have created a method which will accept an array of VARIANTs from the Client side

    void PrintVariant(VARIANT *pV)
    {
      switch(pV->vt)
      {
      case VT_UI1:
        wprintf(L"  Integer: %x\r\n", pV->bVal);
        break;
      default:
        wprintf(L"  Unrecognized Type: vt=%d\r\n", pV->vt);
        break;
      }
    }
    
    STDMETHODIMP CSample::PutArray(SAFEARRAY*  arrOfVariants)
    {
    	SafeArrayLock(arrOfVariants);
    
    	VARIANT *valueArray = (VARIANT *)arrOfVariants->pvData;
    
    	long lBound=0,uBound=0;
    	SafeArrayGetLBound(arrOfVariants, 1, &lBound);
    	SafeArrayGetUBound(arrOfVariants, 1, &uBound);
    
    
    	for(int i=lBound;i<=uBound;i++)
    		PrintVariant(&valueArray[i]);
    
    	SafeArrayUnlock(arrOfVariants);
    
    	//done with the array, so destroying
    	SafeArrayDestroy(arrOfVariants);
    
    	return S_OK;
    }

    Client Side Code:

    int _tmain(int argc, _TCHAR* argv[])
    {
    	CoInitialize(NULL);
    	{
    		ISamplePtr ptr;
    		ptr.CreateInstance(__uuidof(Sample));
    		
    		SAFEARRAYBOUND rgsabound;
    		rgsabound.lLbound = 0;
    		rgsabound.cElements = 4;
    
    		LPSAFEARRAY psaValues = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
    		BYTE bSampe[4] = {0x01,0x02,0x03,0x04};
    		SafeArrayLock(psaValues);
    		VARIANT *pDescriptorData = (VARIANT *)psaValues->pvData;
    
    		for( LONG i = 0; i < 4; ++i )
    		{
    		    VariantClear(&pDescriptorData[i]);
                        pDescriptorData[i].vt = VT_UI1;
                        pDescriptorData[i].bVal = bSampe[i];
    		    SafeArrayPutElement(psaValues,&i,&pDescriptorData);
    		}
    		SafeArrayUnlock(psaValues);
    
    		ptr->PutArray(psaValues);
    			
    	}
    	::CoUninitialize();
    	return 0;
    }

    now i think you can do the changes for your code. 

    Okay that passes just fine to the function but same result. I get it down to here in the softhidreceiver.dll which Iam calling from another atl com dll of my own:

    result = m_InputReportQueue.insert( inputReport );

    The above point of code is not being called or it fails somewhere. Edit: test values are correct. However, I can do this from vbscript and it calls just fine:

    Dim InputReport1(4)
    InputReport(0) = 0
    InputReport(1) = 50
    InputReport(2) = 50
    InputReport(3) = 0
    InputReport(4) = 0

    I was originally referencing this thread but it confuses me why it does not take the values above:

    http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/48b72e29-5589-4aa8-9547-380058da93ba/about-device-simulation-framework-dsf-for-c


    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 Sunday, July 21, 2013 7:03 PM edit 6
    Sunday, July 21, 2013 6:45 PM
  • appoligize for the my initial solution, that was incorrect. 

    here i am trying to demonstrate how to pass an array of VARIANTS to a COM Dll and use it inside the dll.

    first the COM Dll(server side code), in this Component, i have created a method which will accept an array of VARIANTs from the Client side

    void PrintVariant(VARIANT *pV)
    {
      switch(pV->vt)
      {
      case VT_UI1:
        wprintf(L"  Integer: %x\r\n", pV->bVal);
        break;
      default:
        wprintf(L"  Unrecognized Type: vt=%d\r\n", pV->vt);
        break;
      }
    }
    
    STDMETHODIMP CSample::PutArray(SAFEARRAY*  arrOfVariants)
    {
    	SafeArrayLock(arrOfVariants);
    
    	VARIANT *valueArray = (VARIANT *)arrOfVariants->pvData;
    
    	long lBound=0,uBound=0;
    	SafeArrayGetLBound(arrOfVariants, 1, &lBound);
    	SafeArrayGetUBound(arrOfVariants, 1, &uBound);
    
    
    	for(int i=lBound;i<=uBound;i++)
    		PrintVariant(&valueArray[i]);
    
    	SafeArrayUnlock(arrOfVariants);
    
    	//done with the array, so destroying
    	SafeArrayDestroy(arrOfVariants);
    
    	return S_OK;
    }

    Client Side Code:

    int _tmain(int argc, _TCHAR* argv[])
    {
    	CoInitialize(NULL);
    	{
    		ISamplePtr ptr;
    		ptr.CreateInstance(__uuidof(Sample));
    		
    		SAFEARRAYBOUND rgsabound;
    		rgsabound.lLbound = 0;
    		rgsabound.cElements = 4;
    
    		LPSAFEARRAY psaValues = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
    		BYTE bSampe[4] = {0x01,0x02,0x03,0x04};
    		SafeArrayLock(psaValues);
    		VARIANT *pDescriptorData = (VARIANT *)psaValues->pvData;
    
    		for( LONG i = 0; i < 4; ++i )
    		{
    		    VariantClear(&pDescriptorData[i]);
                        pDescriptorData[i].vt = VT_UI1;
                        pDescriptorData[i].bVal = bSampe[i];
    		    SafeArrayPutElement(psaValues,&i,&pDescriptorData);
    		}
    		SafeArrayUnlock(psaValues);
    
    		ptr->PutArray(psaValues);
    			
    	}
    	::CoUninitialize();
    	return 0;
    }

    now i think you can do the changes for your code. 

    Okay that passes just fine to the function but same result. I get it down to here in the softhidreceiver.dll which Iam calling from another atl com dll of my own:

    result = m_InputReportQueue.insert( inputReport );

    The above point of code is not being called or it fails somewhere. Edit: test values are correct. However, I can do this from vbscript and it calls just fine:

    Dim InputReport1(4)
    InputReport(0) = 0
    InputReport(1) = 50
    InputReport(2) = 50
    InputReport(3) = 0
    InputReport(4) = 0

    I was originally referencing this thread but it confuses me why it does not take the values above:

    http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/48b72e29-5589-4aa8-9547-380058da93ba/about-device-simulation-framework-dsf-for-c


    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 found out it makes it to this point at which it sends the data to the simulated device:

    ISoftUSBEndpoint::QueueINData. queueINData however does not accept the data.

    http://msdn.microsoft.com/en-us/library/ff540924.aspx


    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 Monday, July 22, 2013 1:51 AM edit 6
    Monday, July 22, 2013 1:45 AM
  • appoligize for the my initial solution, that was incorrect. 

    here i am trying to demonstrate how to pass an array of VARIANTS to a COM Dll and use it inside the dll.

    first the COM Dll(server side code), in this Component, i have created a method which will accept an array of VARIANTs from the Client side

    void PrintVariant(VARIANT *pV)
    {
      switch(pV->vt)
      {
      case VT_UI1:
        wprintf(L"  Integer: %x\r\n", pV->bVal);
        break;
      default:
        wprintf(L"  Unrecognized Type: vt=%d\r\n", pV->vt);
        break;
      }
    }
    
    STDMETHODIMP CSample::PutArray(SAFEARRAY*  arrOfVariants)
    {
    	SafeArrayLock(arrOfVariants);
    
    	VARIANT *valueArray = (VARIANT *)arrOfVariants->pvData;
    
    	long lBound=0,uBound=0;
    	SafeArrayGetLBound(arrOfVariants, 1, &lBound);
    	SafeArrayGetUBound(arrOfVariants, 1, &uBound);
    
    
    	for(int i=lBound;i<=uBound;i++)
    		PrintVariant(&valueArray[i]);
    
    	SafeArrayUnlock(arrOfVariants);
    
    	//done with the array, so destroying
    	SafeArrayDestroy(arrOfVariants);
    
    	return S_OK;
    }

    Client Side Code:

    int _tmain(int argc, _TCHAR* argv[])
    {
    	CoInitialize(NULL);
    	{
    		ISamplePtr ptr;
    		ptr.CreateInstance(__uuidof(Sample));
    		
    		SAFEARRAYBOUND rgsabound;
    		rgsabound.lLbound = 0;
    		rgsabound.cElements = 4;
    
    		LPSAFEARRAY psaValues = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
    		BYTE bSampe[4] = {0x01,0x02,0x03,0x04};
    		SafeArrayLock(psaValues);
    		VARIANT *pDescriptorData = (VARIANT *)psaValues->pvData;
    
    		for( LONG i = 0; i < 4; ++i )
    		{
    		    VariantClear(&pDescriptorData[i]);
                        pDescriptorData[i].vt = VT_UI1;
                        pDescriptorData[i].bVal = bSampe[i];
    		    SafeArrayPutElement(psaValues,&i,&pDescriptorData);
    		}
    		SafeArrayUnlock(psaValues);
    
    		ptr->PutArray(psaValues);
    			
    	}
    	::CoUninitialize();
    	return 0;
    }

    now i think you can do the changes for your code. 

    Okay that passes just fine to the function but same result. I get it down to here in the softhidreceiver.dll which Iam calling from another atl com dll of my own:

    result = m_InputReportQueue.insert( inputReport );

    The above point of code is not being called or it fails somewhere. Edit: test values are correct. However, I can do this from vbscript and it calls just fine:

    Dim InputReport1(4)
    InputReport(0) = 0
    InputReport(1) = 50
    InputReport(2) = 50
    InputReport(3) = 0
    InputReport(4) = 0

    I was originally referencing this thread but it confuses me why it does not take the values above:

    http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/48b72e29-5589-4aa8-9547-380058da93ba/about-device-simulation-framework-dsf-for-c


    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 found out it makes it to this point at which it sends the data to the simulated device:

    ISoftUSBEndpoint::QueueINData. queueINData however does not accept the data.

    http://msdn.microsoft.com/en-us/library/ff540924.aspx


    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 anymore ideas? I think I will retry your code parish I think I noticed something I forgot to put in from your code after playing around with it for a few days.

    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 29, 2013 10:16 PM
  • appoligize for the my initial solution, that was incorrect. 

    here i am trying to demonstrate how to pass an array of VARIANTS to a COM Dll and use it inside the dll.

    first the COM Dll(server side code), in this Component, i have created a method which will accept an array of VARIANTs from the Client side

    void PrintVariant(VARIANT *pV)
    {
      switch(pV->vt)
      {
      case VT_UI1:
        wprintf(L"  Integer: %x\r\n", pV->bVal);
        break;
      default:
        wprintf(L"  Unrecognized Type: vt=%d\r\n", pV->vt);
        break;
      }
    }
    
    STDMETHODIMP CSample::PutArray(SAFEARRAY*  arrOfVariants)
    {
    	SafeArrayLock(arrOfVariants);
    
    	VARIANT *valueArray = (VARIANT *)arrOfVariants->pvData;
    
    	long lBound=0,uBound=0;
    	SafeArrayGetLBound(arrOfVariants, 1, &lBound);
    	SafeArrayGetUBound(arrOfVariants, 1, &uBound);
    
    
    	for(int i=lBound;i<=uBound;i++)
    		PrintVariant(&valueArray[i]);
    
    	SafeArrayUnlock(arrOfVariants);
    
    	//done with the array, so destroying
    	SafeArrayDestroy(arrOfVariants);
    
    	return S_OK;
    }

    Client Side Code:

    int _tmain(int argc, _TCHAR* argv[])
    {
    	CoInitialize(NULL);
    	{
    		ISamplePtr ptr;
    		ptr.CreateInstance(__uuidof(Sample));
    		
    		SAFEARRAYBOUND rgsabound;
    		rgsabound.lLbound = 0;
    		rgsabound.cElements = 4;
    
    		LPSAFEARRAY psaValues = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
    		BYTE bSampe[4] = {0x01,0x02,0x03,0x04};
    		SafeArrayLock(psaValues);
    		VARIANT *pDescriptorData = (VARIANT *)psaValues->pvData;
    
    		for( LONG i = 0; i < 4; ++i )
    		{
    		    VariantClear(&pDescriptorData[i]);
                        pDescriptorData[i].vt = VT_UI1;
                        pDescriptorData[i].bVal = bSampe[i];
    		    SafeArrayPutElement(psaValues,&i,&pDescriptorData);
    		}
    		SafeArrayUnlock(psaValues);
    
    		ptr->PutArray(psaValues);
    			
    	}
    	::CoUninitialize();
    	return 0;
    }

    now i think you can do the changes for your code. 

    Okay that passes just fine to the function but same result. I get it down to here in the softhidreceiver.dll which Iam calling from another atl com dll of my own:

    result = m_InputReportQueue.insert( inputReport );

    The above point of code is not being called or it fails somewhere. Edit: test values are correct. However, I can do this from vbscript and it calls just fine:

    Dim InputReport1(4)
    InputReport(0) = 0
    InputReport(1) = 50
    InputReport(2) = 50
    InputReport(3) = 0
    InputReport(4) = 0

    I was originally referencing this thread but it confuses me why it does not take the values above:

    http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/48b72e29-5589-4aa8-9547-380058da93ba/about-device-simulation-framework-dsf-for-c


    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 found out it makes it to this point at which it sends the data to the simulated device:

    ISoftUSBEndpoint::QueueINData. queueINData however does not accept the data.

    http://msdn.microsoft.com/en-us/library/ff540924.aspx


    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 anymore ideas? I think I will retry your code parish I think I noticed something I forgot to put in from your code after playing around with it for a few days.

    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


    Please note: parish your client side code does not work because I have a com dll wrapper calling another com dll (softhidreceiver) and other unmanaged c++ libraries.

    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 29, 2013 10:20 PM
  • i tested the code and it is working fine for me. the example shows how to create an array of VARIANT containing BYTES and send it to the COM server. That's it. it will be difficult for me to understand your problem with multiple COM dlls etc, hope you understand. 

    Tuesday, July 30, 2013 6:41 AM
  • i tested the code and it is working fine for me. the example shows how to create an array of VARIANT containing BYTES and send it to the COM server. That's it. it will be difficult for me to understand your problem with multiple COM dlls etc, hope you

    parish, the actual client is the vb.net/C# app but queueinputreport (softhidreceiver) is called from the second dll (mouseemulator). That's probably why it was hard to test.

    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 30, 2013 10:17 AM edit
    Tuesday, July 30, 2013 10:16 AM
  • i tested the code and it is working fine for me. the example shows how to create an array of VARIANT containing BYTES and send it to the COM server. That's it. it will be difficult for me to understand your problem with multiple COM dlls etc, hope you

    parish, the actual client is the vb.net/C# app but queueinputreport (softhidreceiver) is called from the second dll (mouseemulator). That's probably why it was hard to test.

    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



    Parish, do you get fFeatures to be 2194? If so then I did something wrong in my code. I'll play with it some more then post my code if I get stuck.

    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

    Tuesday, July 30, 2013 6:15 PM
  • i tested the code and it is working fine for me. the example shows how to create an array of VARIANT containing BYTES and send it to the COM server. That's it. it will be difficult for me to understand your problem with multiple COM dlls etc, hope you

    parish, the actual client is the vb.net/C# app but queueinputreport (softhidreceiver) is called from the second dll (mouseemulator). That's probably why it was hard to test.

    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



    Parish, do you get fFeatures to be 2194? If so then I did something wrong in my code. I'll play with it some more then post my code if I get stuck.

    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

    Parish could you change your variant to have HUGHP? Their is another part in softhidreceiver which uses the same code except for it changes the safearray declaration in code to: SAFEARRAY HUGHP* safearraynamehere;

    I double checked the idl file and its the same as the idl declaration for queueinputreport on createreportdescriptor which does show how they access the array correctly. Heres the code for that which is very similar to yours except the declaration of the safearray is different:

    HRESULT CHIDDevice::CreateReportDescriptor()
    /*++
    Routine Description:
       Constructs the default report descriptors
    
    Arguments:
        none
    
    Return value:
        S_OK
        Otherwise from called function
    --*/
    {
        HRESULT hr                     = S_OK;
        VARIANT HUGEP* pDescriptorData = NULL;
        
        if( m_psaReportDescriptor != NULL )
        {
            SafeArrayDestroy(m_psaReportDescriptor);
            m_psaReportDescriptor = NULL;
        }
    
        BYTE           bReportDescriptorData[ ] = { 
    		  
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,                    // USAGE (Mouse)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Pointer)
    0xa1, 0x00,                    //   COLLECTION (Physical)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
    0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x75, 0x05,                    //     REPORT_SIZE (5)
    0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
    0x09, 0x30,                    //     USAGE (X)
    0x09, 0x31,                    //     USAGE (Y)
    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x02,                    //     REPORT_COUNT (2)
    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
    0xc0, 0xc0                      //   END_COLLECTION
    
    
                                                    // Consumer Controls
                                                    //    0x05,   0x0c,       // Usage Page (Consumer Controls),
                                                    //    0x09,   0x01,       // Usage (Consumer Control),
                                                    //    0xA1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x01,       //  Report Id (1)
                                                    //    0x19,   0x00,       //  Usage Minimum (0),
                                                    //    0x2a,   0x3c, 0x02, //  Usage Maximum (23c)  
                                                    //    0x15,   0x00,       //  Logical Minimum (0),
                                                    //    0x26,   0x3c, 0x02, //  Logical Maximum (23c)  
                                                    //    0x95,   0x01,       //  Report Count (1),
                                                    //    0x75,   0x10,       //  Report Size (16),
                                                    //    0x81,   0x00,       //  Input (Data, Array), 
                                                    //    0xC0,               // End Collection 
                                                    //// MS Vendor controls
                                                    //    0x06,   0xbc, 0xff, // Usage Page (Vendor 0xffbc),
                                                    //    0x09,   0x88,       // Usage (88),
                                                    //    0xa1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x02,       //  Report Id (2)
                                                    //    0x19,   0x01,       //  Usage Minimum (0x01),
                                                    //    0x29,   0xff,       //  Usage Maximum (0xff),
                                                    //    0x15,   0x00,       //  Logical Minimum (0),
                                                    //    0x25,   0x01,       //  Logical Maximum(1),
                                                    //    0x95,   0x01,       //  Report Count (1),
                                                    //    0x75,   0x08,       //  Report Size (8),
                                                    //    0x81,   0x00,       //  Input (Data, Array), 
                                                    //    0xc0,               // End Collection
                                                    //// Standby button
                                                    //    0x05,   0x01,       // Usage Page (Generic Desktop),
                                                    //    0x09,   0x80,       // Usage (System Control),
                                                    //    0xa1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x03,       //  Report Id (3)
                                                    //    0x19,   0x81,       //  Usage Minimum (0x81),
                                                    //    0x29,   0x83,       //  Usage Maximum (0x83),
                                                    //    0x25,   0x01,       //  Logical Maximum(1),
                                                    //    0x75,   0x01,       //  Report Size (1),
                                                    //    0x95,   0x03,       //  Report Count (3),
                                                    //    0x81,   0x02,       //  Input
                                                    //    0x75,   0x01,       //  Report Size (1),   
                                                    //    0x95,   0x05,       //  Report Count (5),
                                                    //    0x81,   0x01,       //  Input (Constant),
                                                    //    0xC0,               // End Collection
                                                    //// Keyboard
                                                    //    0x05,   0x01,       // Usage Page (Generic Desktop),
                                                    //    0x09,   0x06,       // Usage (Keyboard),
                                                    //    0xA1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x04,       //  Report Id (4)
                                                    //    0x05,   0x07,       //  Usage Page (Key Cdes)
                                                    //    0x19,   0xe0,       //  Usage Minimum left control
                                                    //    0x29,   0xe8,       //  Usage Maximum keyboard right gui
                                                    //    0x75,   0x01,       //  Report Size (1)
                                                    //    0x95,   0x08,       //  Report Count (8)
                                                    //    0x81,   0x02,       //  Input (Variable)
                                                    //    0x19,   0x00,       //  Usage Minimum (0)
                                                    //    0x29,   0x90,       //  Usage Maximum (90)
                                                    //    0x26,   0xff, 0x00, //  Logical Maximum (0xff)
                                                    //    0x75,   0x08,       //  Report Size (8)
                                                    //    0x95,   0x01,       //  Report Count (1)
                                                    //    0x81,   0x00,       //  Input (Data, Array),
                                                    //    0xC0                // End Collection
                                                };
        
        // Build a SafeArray Struct that will hold the size and dimension requirements that 
        // will be used during the Safe Array creation
        SAFEARRAYBOUND rgsabound[1];
        ZeroMemory(rgsabound, sizeof(rgsabound));
        rgsabound[0].lLbound = 0;
        rgsabound[0].cElements = sizeof(bReportDescriptorData);
        
        m_psaReportDescriptor = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
        
        if( m_psaReportDescriptor == NULL )
        {
            hr = E_UNEXPECTED;
            goto Exit;
        }
            
        IfFailHrGo( SafeArrayAccessData( m_psaReportDescriptor, 
                                         (void HUGEP**)&pDescriptorData));
    
        INT descSize = sizeof(bReportDescriptorData);
        for( INT i = 0; i < descSize; ++i )
        {
            pDescriptorData[i].vt = VT_UI1;
            pDescriptorData[i].bVal = bReportDescriptorData[i];
        }
    
    Exit:
        SafeArrayUnaccessData(m_psaReportDescriptor);
        return hr;
    }

    Let me explain: the code above is for creating a device without having to write more safearray code to send to tell dsf what device to create but the safearray is accessed close to how the one Iam currently doing is accessed.

    For better reference on the general flow from assemblies and dlls: dotnet client->mouseemulator wrapper dll->softhidreceiver dll. Their are also many other libraries the mouse emulator uses besides softhidreceiver but softhidreceiver is the biggest one.

    Edit: found it trying it out now crossing fingers.


    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 30, 2013 7:16 PM edit 3
    Tuesday, July 30, 2013 7:02 PM
  • i tested the code and it is working fine for me. the example shows how to create an array of VARIANT containing BYTES and send it to the COM server. That's it. it will be difficult for me to understand your problem with multiple COM dlls etc, hope you

    parish, the actual client is the vb.net/C# app but queueinputreport (softhidreceiver) is called from the second dll (mouseemulator). That's probably why it was hard to test.

    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



    Parish, do you get fFeatures to be 2194? If so then I did something wrong in my code. I'll play with it some more then post my code if I get stuck.

    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

    Parish could you change your variant to have HUGHP? Their is another part in softhidreceiver which uses the same code except for it changes the safearray declaration in code to: SAFEARRAY HUGHP* safearraynamehere;

    I double checked the idl file and its the same as the idl declaration for queueinputreport on createreportdescriptor which does show how they access the array correctly. Heres the code for that which is very similar to yours except the declaration of the safearray is different:

    HRESULT CHIDDevice::CreateReportDescriptor()
    /*++
    Routine Description:
       Constructs the default report descriptors
    
    Arguments:
        none
    
    Return value:
        S_OK
        Otherwise from called function
    --*/
    {
        HRESULT hr                     = S_OK;
        VARIANT HUGEP* pDescriptorData = NULL;
        
        if( m_psaReportDescriptor != NULL )
        {
            SafeArrayDestroy(m_psaReportDescriptor);
            m_psaReportDescriptor = NULL;
        }
    
        BYTE           bReportDescriptorData[ ] = { 
    		  
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,                    // USAGE (Mouse)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Pointer)
    0xa1, 0x00,                    //   COLLECTION (Physical)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
    0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x75, 0x05,                    //     REPORT_SIZE (5)
    0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
    0x09, 0x30,                    //     USAGE (X)
    0x09, 0x31,                    //     USAGE (Y)
    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x02,                    //     REPORT_COUNT (2)
    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
    0xc0, 0xc0                      //   END_COLLECTION
    
    
                                                    // Consumer Controls
                                                    //    0x05,   0x0c,       // Usage Page (Consumer Controls),
                                                    //    0x09,   0x01,       // Usage (Consumer Control),
                                                    //    0xA1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x01,       //  Report Id (1)
                                                    //    0x19,   0x00,       //  Usage Minimum (0),
                                                    //    0x2a,   0x3c, 0x02, //  Usage Maximum (23c)  
                                                    //    0x15,   0x00,       //  Logical Minimum (0),
                                                    //    0x26,   0x3c, 0x02, //  Logical Maximum (23c)  
                                                    //    0x95,   0x01,       //  Report Count (1),
                                                    //    0x75,   0x10,       //  Report Size (16),
                                                    //    0x81,   0x00,       //  Input (Data, Array), 
                                                    //    0xC0,               // End Collection 
                                                    //// MS Vendor controls
                                                    //    0x06,   0xbc, 0xff, // Usage Page (Vendor 0xffbc),
                                                    //    0x09,   0x88,       // Usage (88),
                                                    //    0xa1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x02,       //  Report Id (2)
                                                    //    0x19,   0x01,       //  Usage Minimum (0x01),
                                                    //    0x29,   0xff,       //  Usage Maximum (0xff),
                                                    //    0x15,   0x00,       //  Logical Minimum (0),
                                                    //    0x25,   0x01,       //  Logical Maximum(1),
                                                    //    0x95,   0x01,       //  Report Count (1),
                                                    //    0x75,   0x08,       //  Report Size (8),
                                                    //    0x81,   0x00,       //  Input (Data, Array), 
                                                    //    0xc0,               // End Collection
                                                    //// Standby button
                                                    //    0x05,   0x01,       // Usage Page (Generic Desktop),
                                                    //    0x09,   0x80,       // Usage (System Control),
                                                    //    0xa1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x03,       //  Report Id (3)
                                                    //    0x19,   0x81,       //  Usage Minimum (0x81),
                                                    //    0x29,   0x83,       //  Usage Maximum (0x83),
                                                    //    0x25,   0x01,       //  Logical Maximum(1),
                                                    //    0x75,   0x01,       //  Report Size (1),
                                                    //    0x95,   0x03,       //  Report Count (3),
                                                    //    0x81,   0x02,       //  Input
                                                    //    0x75,   0x01,       //  Report Size (1),   
                                                    //    0x95,   0x05,       //  Report Count (5),
                                                    //    0x81,   0x01,       //  Input (Constant),
                                                    //    0xC0,               // End Collection
                                                    //// Keyboard
                                                    //    0x05,   0x01,       // Usage Page (Generic Desktop),
                                                    //    0x09,   0x06,       // Usage (Keyboard),
                                                    //    0xA1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x04,       //  Report Id (4)
                                                    //    0x05,   0x07,       //  Usage Page (Key Cdes)
                                                    //    0x19,   0xe0,       //  Usage Minimum left control
                                                    //    0x29,   0xe8,       //  Usage Maximum keyboard right gui
                                                    //    0x75,   0x01,       //  Report Size (1)
                                                    //    0x95,   0x08,       //  Report Count (8)
                                                    //    0x81,   0x02,       //  Input (Variable)
                                                    //    0x19,   0x00,       //  Usage Minimum (0)
                                                    //    0x29,   0x90,       //  Usage Maximum (90)
                                                    //    0x26,   0xff, 0x00, //  Logical Maximum (0xff)
                                                    //    0x75,   0x08,       //  Report Size (8)
                                                    //    0x95,   0x01,       //  Report Count (1)
                                                    //    0x81,   0x00,       //  Input (Data, Array),
                                                    //    0xC0                // End Collection
                                                };
        
        // Build a SafeArray Struct that will hold the size and dimension requirements that 
        // will be used during the Safe Array creation
        SAFEARRAYBOUND rgsabound[1];
        ZeroMemory(rgsabound, sizeof(rgsabound));
        rgsabound[0].lLbound = 0;
        rgsabound[0].cElements = sizeof(bReportDescriptorData);
        
        m_psaReportDescriptor = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
        
        if( m_psaReportDescriptor == NULL )
        {
            hr = E_UNEXPECTED;
            goto Exit;
        }
            
        IfFailHrGo( SafeArrayAccessData( m_psaReportDescriptor, 
                                         (void HUGEP**)&pDescriptorData));
    
        INT descSize = sizeof(bReportDescriptorData);
        for( INT i = 0; i < descSize; ++i )
        {
            pDescriptorData[i].vt = VT_UI1;
            pDescriptorData[i].bVal = bReportDescriptorData[i];
        }
    
    Exit:
        SafeArrayUnaccessData(m_psaReportDescriptor);
        return hr;
    }

    Let me explain: the code above is for creating a device without having to write more safearray code to send to tell dsf what device to create but the safearray is accessed close to how the one Iam currently doing is accessed.

    For better reference on the general flow from assemblies and dlls: dotnet client->mouseemulator wrapper dll->softhidreceiver dll. Their are also many other libraries the mouse emulator uses besides softhidreceiver but softhidreceiver is the biggest one.

    Edit: found it trying it out now crossing fingers.


    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 have the full source code here for softhidreceiver parish if you wish to troubleshoot through it yourself:

    https://kinectmultipoint.codeplex.com/downloads/get/713550

    It needs a safe array of variants that are COM automation compatible (Like I said it works in vbscript just fine).  I do know my main c++ atl com dll calls softhidreceiver dll which is another atl com dll project. It appears if I change it to vb6 code it would be the equivalent to vb6's fixed size variant or vbscripts variant. If you have anymore ideas parish the source I am going from is above for queueinputreport.


    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, August 3, 2013 5:12 PM edit 2
    Saturday, August 3, 2013 5:12 PM
  • i tested the code and it is working fine for me. the example shows how to create an array of VARIANT containing BYTES and send it to the COM server. That's it. it will be difficult for me to understand your problem with multiple COM dlls etc, hope you

    parish, the actual client is the vb.net/C# app but queueinputreport (softhidreceiver) is called from the second dll (mouseemulator). That's probably why it was hard to test.

    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



    Parish, do you get fFeatures to be 2194? If so then I did something wrong in my code. I'll play with it some more then post my code if I get stuck.

    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

    Parish could you change your variant to have HUGHP? Their is another part in softhidreceiver which uses the same code except for it changes the safearray declaration in code to: SAFEARRAY HUGHP* safearraynamehere;

    I double checked the idl file and its the same as the idl declaration for queueinputreport on createreportdescriptor which does show how they access the array correctly. Heres the code for that which is very similar to yours except the declaration of the safearray is different:

    HRESULT CHIDDevice::CreateReportDescriptor()
    /*++
    Routine Description:
       Constructs the default report descriptors
    
    Arguments:
        none
    
    Return value:
        S_OK
        Otherwise from called function
    --*/
    {
        HRESULT hr                     = S_OK;
        VARIANT HUGEP* pDescriptorData = NULL;
        
        if( m_psaReportDescriptor != NULL )
        {
            SafeArrayDestroy(m_psaReportDescriptor);
            m_psaReportDescriptor = NULL;
        }
    
        BYTE           bReportDescriptorData[ ] = { 
    		  
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,                    // USAGE (Mouse)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Pointer)
    0xa1, 0x00,                    //   COLLECTION (Physical)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
    0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x75, 0x05,                    //     REPORT_SIZE (5)
    0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
    0x09, 0x30,                    //     USAGE (X)
    0x09, 0x31,                    //     USAGE (Y)
    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x02,                    //     REPORT_COUNT (2)
    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
    0xc0, 0xc0                      //   END_COLLECTION
    
    
                                                    // Consumer Controls
                                                    //    0x05,   0x0c,       // Usage Page (Consumer Controls),
                                                    //    0x09,   0x01,       // Usage (Consumer Control),
                                                    //    0xA1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x01,       //  Report Id (1)
                                                    //    0x19,   0x00,       //  Usage Minimum (0),
                                                    //    0x2a,   0x3c, 0x02, //  Usage Maximum (23c)  
                                                    //    0x15,   0x00,       //  Logical Minimum (0),
                                                    //    0x26,   0x3c, 0x02, //  Logical Maximum (23c)  
                                                    //    0x95,   0x01,       //  Report Count (1),
                                                    //    0x75,   0x10,       //  Report Size (16),
                                                    //    0x81,   0x00,       //  Input (Data, Array), 
                                                    //    0xC0,               // End Collection 
                                                    //// MS Vendor controls
                                                    //    0x06,   0xbc, 0xff, // Usage Page (Vendor 0xffbc),
                                                    //    0x09,   0x88,       // Usage (88),
                                                    //    0xa1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x02,       //  Report Id (2)
                                                    //    0x19,   0x01,       //  Usage Minimum (0x01),
                                                    //    0x29,   0xff,       //  Usage Maximum (0xff),
                                                    //    0x15,   0x00,       //  Logical Minimum (0),
                                                    //    0x25,   0x01,       //  Logical Maximum(1),
                                                    //    0x95,   0x01,       //  Report Count (1),
                                                    //    0x75,   0x08,       //  Report Size (8),
                                                    //    0x81,   0x00,       //  Input (Data, Array), 
                                                    //    0xc0,               // End Collection
                                                    //// Standby button
                                                    //    0x05,   0x01,       // Usage Page (Generic Desktop),
                                                    //    0x09,   0x80,       // Usage (System Control),
                                                    //    0xa1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x03,       //  Report Id (3)
                                                    //    0x19,   0x81,       //  Usage Minimum (0x81),
                                                    //    0x29,   0x83,       //  Usage Maximum (0x83),
                                                    //    0x25,   0x01,       //  Logical Maximum(1),
                                                    //    0x75,   0x01,       //  Report Size (1),
                                                    //    0x95,   0x03,       //  Report Count (3),
                                                    //    0x81,   0x02,       //  Input
                                                    //    0x75,   0x01,       //  Report Size (1),   
                                                    //    0x95,   0x05,       //  Report Count (5),
                                                    //    0x81,   0x01,       //  Input (Constant),
                                                    //    0xC0,               // End Collection
                                                    //// Keyboard
                                                    //    0x05,   0x01,       // Usage Page (Generic Desktop),
                                                    //    0x09,   0x06,       // Usage (Keyboard),
                                                    //    0xA1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x04,       //  Report Id (4)
                                                    //    0x05,   0x07,       //  Usage Page (Key Cdes)
                                                    //    0x19,   0xe0,       //  Usage Minimum left control
                                                    //    0x29,   0xe8,       //  Usage Maximum keyboard right gui
                                                    //    0x75,   0x01,       //  Report Size (1)
                                                    //    0x95,   0x08,       //  Report Count (8)
                                                    //    0x81,   0x02,       //  Input (Variable)
                                                    //    0x19,   0x00,       //  Usage Minimum (0)
                                                    //    0x29,   0x90,       //  Usage Maximum (90)
                                                    //    0x26,   0xff, 0x00, //  Logical Maximum (0xff)
                                                    //    0x75,   0x08,       //  Report Size (8)
                                                    //    0x95,   0x01,       //  Report Count (1)
                                                    //    0x81,   0x00,       //  Input (Data, Array),
                                                    //    0xC0                // End Collection
                                                };
        
        // Build a SafeArray Struct that will hold the size and dimension requirements that 
        // will be used during the Safe Array creation
        SAFEARRAYBOUND rgsabound[1];
        ZeroMemory(rgsabound, sizeof(rgsabound));
        rgsabound[0].lLbound = 0;
        rgsabound[0].cElements = sizeof(bReportDescriptorData);
        
        m_psaReportDescriptor = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
        
        if( m_psaReportDescriptor == NULL )
        {
            hr = E_UNEXPECTED;
            goto Exit;
        }
            
        IfFailHrGo( SafeArrayAccessData( m_psaReportDescriptor, 
                                         (void HUGEP**)&pDescriptorData));
    
        INT descSize = sizeof(bReportDescriptorData);
        for( INT i = 0; i < descSize; ++i )
        {
            pDescriptorData[i].vt = VT_UI1;
            pDescriptorData[i].bVal = bReportDescriptorData[i];
        }
    
    Exit:
        SafeArrayUnaccessData(m_psaReportDescriptor);
        return hr;
    }

    Let me explain: the code above is for creating a device without having to write more safearray code to send to tell dsf what device to create but the safearray is accessed close to how the one Iam currently doing is accessed.

    For better reference on the general flow from assemblies and dlls: dotnet client->mouseemulator wrapper dll->softhidreceiver dll. Their are also many other libraries the mouse emulator uses besides softhidreceiver but softhidreceiver is the biggest one.

    Edit: found it trying it out now crossing fingers.


    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 have the full source code here for softhidreceiver parish if you wish to troubleshoot through it yourself:

    https://kinectmultipoint.codeplex.com/downloads/get/713550

    It needs a safe array of variants that are COM automation compatible (Like I said it works in vbscript just fine).  I do know my main c++ atl com dll calls softhidreceiver dll which is another atl com dll project. It appears if I change it to vb6 code it would be the equivalent to vb6's fixed size variant or vbscripts variant. If you have anymore ideas parish the source I am going from is above for queueinputreport.


    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 think I had a memory leak or maybe the c++ code skipped over the safearray because it was of the wrong type but I used your first code sample a little modified and it acted like it was going to take it but i did not see my messagebox on the softhidreceiver.dll side.

    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, August 3, 2013 6:29 PM
  • i tested the code and it is working fine for me. the example shows how to create an array of VARIANT containing BYTES and send it to the COM server. That's it. it will be difficult for me to understand your problem with multiple COM dlls etc, hope you

    parish, the actual client is the vb.net/C# app but queueinputreport (softhidreceiver) is called from the second dll (mouseemulator). That's probably why it was hard to test.

    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



    Parish, do you get fFeatures to be 2194? If so then I did something wrong in my code. I'll play with it some more then post my code if I get stuck.

    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

    Parish could you change your variant to have HUGHP? Their is another part in softhidreceiver which uses the same code except for it changes the safearray declaration in code to: SAFEARRAY HUGHP* safearraynamehere;

    I double checked the idl file and its the same as the idl declaration for queueinputreport on createreportdescriptor which does show how they access the array correctly. Heres the code for that which is very similar to yours except the declaration of the safearray is different:

    HRESULT CHIDDevice::CreateReportDescriptor()
    /*++
    Routine Description:
       Constructs the default report descriptors
    
    Arguments:
        none
    
    Return value:
        S_OK
        Otherwise from called function
    --*/
    {
        HRESULT hr                     = S_OK;
        VARIANT HUGEP* pDescriptorData = NULL;
        
        if( m_psaReportDescriptor != NULL )
        {
            SafeArrayDestroy(m_psaReportDescriptor);
            m_psaReportDescriptor = NULL;
        }
    
        BYTE           bReportDescriptorData[ ] = { 
    		  
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,                    // USAGE (Mouse)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Pointer)
    0xa1, 0x00,                    //   COLLECTION (Physical)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
    0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x75, 0x05,                    //     REPORT_SIZE (5)
    0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
    0x09, 0x30,                    //     USAGE (X)
    0x09, 0x31,                    //     USAGE (Y)
    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x02,                    //     REPORT_COUNT (2)
    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
    0xc0, 0xc0                      //   END_COLLECTION
    
    
                                                    // Consumer Controls
                                                    //    0x05,   0x0c,       // Usage Page (Consumer Controls),
                                                    //    0x09,   0x01,       // Usage (Consumer Control),
                                                    //    0xA1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x01,       //  Report Id (1)
                                                    //    0x19,   0x00,       //  Usage Minimum (0),
                                                    //    0x2a,   0x3c, 0x02, //  Usage Maximum (23c)  
                                                    //    0x15,   0x00,       //  Logical Minimum (0),
                                                    //    0x26,   0x3c, 0x02, //  Logical Maximum (23c)  
                                                    //    0x95,   0x01,       //  Report Count (1),
                                                    //    0x75,   0x10,       //  Report Size (16),
                                                    //    0x81,   0x00,       //  Input (Data, Array), 
                                                    //    0xC0,               // End Collection 
                                                    //// MS Vendor controls
                                                    //    0x06,   0xbc, 0xff, // Usage Page (Vendor 0xffbc),
                                                    //    0x09,   0x88,       // Usage (88),
                                                    //    0xa1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x02,       //  Report Id (2)
                                                    //    0x19,   0x01,       //  Usage Minimum (0x01),
                                                    //    0x29,   0xff,       //  Usage Maximum (0xff),
                                                    //    0x15,   0x00,       //  Logical Minimum (0),
                                                    //    0x25,   0x01,       //  Logical Maximum(1),
                                                    //    0x95,   0x01,       //  Report Count (1),
                                                    //    0x75,   0x08,       //  Report Size (8),
                                                    //    0x81,   0x00,       //  Input (Data, Array), 
                                                    //    0xc0,               // End Collection
                                                    //// Standby button
                                                    //    0x05,   0x01,       // Usage Page (Generic Desktop),
                                                    //    0x09,   0x80,       // Usage (System Control),
                                                    //    0xa1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x03,       //  Report Id (3)
                                                    //    0x19,   0x81,       //  Usage Minimum (0x81),
                                                    //    0x29,   0x83,       //  Usage Maximum (0x83),
                                                    //    0x25,   0x01,       //  Logical Maximum(1),
                                                    //    0x75,   0x01,       //  Report Size (1),
                                                    //    0x95,   0x03,       //  Report Count (3),
                                                    //    0x81,   0x02,       //  Input
                                                    //    0x75,   0x01,       //  Report Size (1),   
                                                    //    0x95,   0x05,       //  Report Count (5),
                                                    //    0x81,   0x01,       //  Input (Constant),
                                                    //    0xC0,               // End Collection
                                                    //// Keyboard
                                                    //    0x05,   0x01,       // Usage Page (Generic Desktop),
                                                    //    0x09,   0x06,       // Usage (Keyboard),
                                                    //    0xA1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x04,       //  Report Id (4)
                                                    //    0x05,   0x07,       //  Usage Page (Key Cdes)
                                                    //    0x19,   0xe0,       //  Usage Minimum left control
                                                    //    0x29,   0xe8,       //  Usage Maximum keyboard right gui
                                                    //    0x75,   0x01,       //  Report Size (1)
                                                    //    0x95,   0x08,       //  Report Count (8)
                                                    //    0x81,   0x02,       //  Input (Variable)
                                                    //    0x19,   0x00,       //  Usage Minimum (0)
                                                    //    0x29,   0x90,       //  Usage Maximum (90)
                                                    //    0x26,   0xff, 0x00, //  Logical Maximum (0xff)
                                                    //    0x75,   0x08,       //  Report Size (8)
                                                    //    0x95,   0x01,       //  Report Count (1)
                                                    //    0x81,   0x00,       //  Input (Data, Array),
                                                    //    0xC0                // End Collection
                                                };
        
        // Build a SafeArray Struct that will hold the size and dimension requirements that 
        // will be used during the Safe Array creation
        SAFEARRAYBOUND rgsabound[1];
        ZeroMemory(rgsabound, sizeof(rgsabound));
        rgsabound[0].lLbound = 0;
        rgsabound[0].cElements = sizeof(bReportDescriptorData);
        
        m_psaReportDescriptor = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
        
        if( m_psaReportDescriptor == NULL )
        {
            hr = E_UNEXPECTED;
            goto Exit;
        }
            
        IfFailHrGo( SafeArrayAccessData( m_psaReportDescriptor, 
                                         (void HUGEP**)&pDescriptorData));
    
        INT descSize = sizeof(bReportDescriptorData);
        for( INT i = 0; i < descSize; ++i )
        {
            pDescriptorData[i].vt = VT_UI1;
            pDescriptorData[i].bVal = bReportDescriptorData[i];
        }
    
    Exit:
        SafeArrayUnaccessData(m_psaReportDescriptor);
        return hr;
    }

    Let me explain: the code above is for creating a device without having to write more safearray code to send to tell dsf what device to create but the safearray is accessed close to how the one Iam currently doing is accessed.

    For better reference on the general flow from assemblies and dlls: dotnet client->mouseemulator wrapper dll->softhidreceiver dll. Their are also many other libraries the mouse emulator uses besides softhidreceiver but softhidreceiver is the biggest one.

    Edit: found it trying it out now crossing fingers.


    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 have the full source code here for softhidreceiver parish if you wish to troubleshoot through it yourself:

    https://kinectmultipoint.codeplex.com/downloads/get/713550

    It needs a safe array of variants that are COM automation compatible (Like I said it works in vbscript just fine).  I do know my main c++ atl com dll calls softhidreceiver dll which is another atl com dll project. It appears if I change it to vb6 code it would be the equivalent to vb6's fixed size variant or vbscripts variant. If you have anymore ideas parish the source I am going from is above for queueinputreport.


    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 think I had a memory leak or maybe the c++ code skipped over the safearray because it was of the wrong type but I used your first code sample a little modified and it acted like it was going to take it but i did not see my messagebox on the softhidreceiver.dll side.

    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

    If I pass the variant's safe array using its parray parameter it skips over the code but when I pass the actual safearray it passes data but fails at queueinputreport. I think I will report as bug unless someone here thinks they can solve the problem. Update: I have posted my softhidreceiver com server code at the link below. For reference:

    1. softhidreceiver library - com server

    2. multimousesimulator (c++ code) - com server

    3. com client - vb.net test code

    I hope that explains this better to anyone trying to help again.

    Edit: source code is on kinectmultipoint page here: http://kinectmultipoint.codplex.com under downloads section. Its the c++ simulator code. Also, I have posted my softhidreceiver code. If it does not show up then I will reupload.


    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 Wednesday, August 7, 2013 5:06 PM edit
    Wednesday, August 7, 2013 5:03 PM
  • i tested the code and it is working fine for me. the example shows how to create an array of VARIANT containing BYTES and send it to the COM server. That's it. it will be difficult for me to understand your problem with multiple COM dlls etc, hope you

    parish, the actual client is the vb.net/C# app but queueinputreport (softhidreceiver) is called from the second dll (mouseemulator). That's probably why it was hard to test.

    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



    Parish, do you get fFeatures to be 2194? If so then I did something wrong in my code. I'll play with it some more then post my code if I get stuck.

    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

    Parish could you change your variant to have HUGHP? Their is another part in softhidreceiver which uses the same code except for it changes the safearray declaration in code to: SAFEARRAY HUGHP* safearraynamehere;

    I double checked the idl file and its the same as the idl declaration for queueinputreport on createreportdescriptor which does show how they access the array correctly. Heres the code for that which is very similar to yours except the declaration of the safearray is different:

    HRESULT CHIDDevice::CreateReportDescriptor()
    /*++
    Routine Description:
       Constructs the default report descriptors
    
    Arguments:
        none
    
    Return value:
        S_OK
        Otherwise from called function
    --*/
    {
        HRESULT hr                     = S_OK;
        VARIANT HUGEP* pDescriptorData = NULL;
        
        if( m_psaReportDescriptor != NULL )
        {
            SafeArrayDestroy(m_psaReportDescriptor);
            m_psaReportDescriptor = NULL;
        }
    
        BYTE           bReportDescriptorData[ ] = { 
    		  
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,                    // USAGE (Mouse)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Pointer)
    0xa1, 0x00,                    //   COLLECTION (Physical)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
    0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x75, 0x05,                    //     REPORT_SIZE (5)
    0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
    0x09, 0x30,                    //     USAGE (X)
    0x09, 0x31,                    //     USAGE (Y)
    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x02,                    //     REPORT_COUNT (2)
    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
    0xc0, 0xc0                      //   END_COLLECTION
    
    
                                                    // Consumer Controls
                                                    //    0x05,   0x0c,       // Usage Page (Consumer Controls),
                                                    //    0x09,   0x01,       // Usage (Consumer Control),
                                                    //    0xA1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x01,       //  Report Id (1)
                                                    //    0x19,   0x00,       //  Usage Minimum (0),
                                                    //    0x2a,   0x3c, 0x02, //  Usage Maximum (23c)  
                                                    //    0x15,   0x00,       //  Logical Minimum (0),
                                                    //    0x26,   0x3c, 0x02, //  Logical Maximum (23c)  
                                                    //    0x95,   0x01,       //  Report Count (1),
                                                    //    0x75,   0x10,       //  Report Size (16),
                                                    //    0x81,   0x00,       //  Input (Data, Array), 
                                                    //    0xC0,               // End Collection 
                                                    //// MS Vendor controls
                                                    //    0x06,   0xbc, 0xff, // Usage Page (Vendor 0xffbc),
                                                    //    0x09,   0x88,       // Usage (88),
                                                    //    0xa1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x02,       //  Report Id (2)
                                                    //    0x19,   0x01,       //  Usage Minimum (0x01),
                                                    //    0x29,   0xff,       //  Usage Maximum (0xff),
                                                    //    0x15,   0x00,       //  Logical Minimum (0),
                                                    //    0x25,   0x01,       //  Logical Maximum(1),
                                                    //    0x95,   0x01,       //  Report Count (1),
                                                    //    0x75,   0x08,       //  Report Size (8),
                                                    //    0x81,   0x00,       //  Input (Data, Array), 
                                                    //    0xc0,               // End Collection
                                                    //// Standby button
                                                    //    0x05,   0x01,       // Usage Page (Generic Desktop),
                                                    //    0x09,   0x80,       // Usage (System Control),
                                                    //    0xa1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x03,       //  Report Id (3)
                                                    //    0x19,   0x81,       //  Usage Minimum (0x81),
                                                    //    0x29,   0x83,       //  Usage Maximum (0x83),
                                                    //    0x25,   0x01,       //  Logical Maximum(1),
                                                    //    0x75,   0x01,       //  Report Size (1),
                                                    //    0x95,   0x03,       //  Report Count (3),
                                                    //    0x81,   0x02,       //  Input
                                                    //    0x75,   0x01,       //  Report Size (1),   
                                                    //    0x95,   0x05,       //  Report Count (5),
                                                    //    0x81,   0x01,       //  Input (Constant),
                                                    //    0xC0,               // End Collection
                                                    //// Keyboard
                                                    //    0x05,   0x01,       // Usage Page (Generic Desktop),
                                                    //    0x09,   0x06,       // Usage (Keyboard),
                                                    //    0xA1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x04,       //  Report Id (4)
                                                    //    0x05,   0x07,       //  Usage Page (Key Cdes)
                                                    //    0x19,   0xe0,       //  Usage Minimum left control
                                                    //    0x29,   0xe8,       //  Usage Maximum keyboard right gui
                                                    //    0x75,   0x01,       //  Report Size (1)
                                                    //    0x95,   0x08,       //  Report Count (8)
                                                    //    0x81,   0x02,       //  Input (Variable)
                                                    //    0x19,   0x00,       //  Usage Minimum (0)
                                                    //    0x29,   0x90,       //  Usage Maximum (90)
                                                    //    0x26,   0xff, 0x00, //  Logical Maximum (0xff)
                                                    //    0x75,   0x08,       //  Report Size (8)
                                                    //    0x95,   0x01,       //  Report Count (1)
                                                    //    0x81,   0x00,       //  Input (Data, Array),
                                                    //    0xC0                // End Collection
                                                };
        
        // Build a SafeArray Struct that will hold the size and dimension requirements that 
        // will be used during the Safe Array creation
        SAFEARRAYBOUND rgsabound[1];
        ZeroMemory(rgsabound, sizeof(rgsabound));
        rgsabound[0].lLbound = 0;
        rgsabound[0].cElements = sizeof(bReportDescriptorData);
        
        m_psaReportDescriptor = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
        
        if( m_psaReportDescriptor == NULL )
        {
            hr = E_UNEXPECTED;
            goto Exit;
        }
            
        IfFailHrGo( SafeArrayAccessData( m_psaReportDescriptor, 
                                         (void HUGEP**)&pDescriptorData));
    
        INT descSize = sizeof(bReportDescriptorData);
        for( INT i = 0; i < descSize; ++i )
        {
            pDescriptorData[i].vt = VT_UI1;
            pDescriptorData[i].bVal = bReportDescriptorData[i];
        }
    
    Exit:
        SafeArrayUnaccessData(m_psaReportDescriptor);
        return hr;
    }

    Let me explain: the code above is for creating a device without having to write more safearray code to send to tell dsf what device to create but the safearray is accessed close to how the one Iam currently doing is accessed.

    For better reference on the general flow from assemblies and dlls: dotnet client->mouseemulator wrapper dll->softhidreceiver dll. Their are also many other libraries the mouse emulator uses besides softhidreceiver but softhidreceiver is the biggest one.

    Edit: found it trying it out now crossing fingers.


    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 have the full source code here for softhidreceiver parish if you wish to troubleshoot through it yourself:

    https://kinectmultipoint.codeplex.com/downloads/get/713550

    It needs a safe array of variants that are COM automation compatible (Like I said it works in vbscript just fine).  I do know my main c++ atl com dll calls softhidreceiver dll which is another atl com dll project. It appears if I change it to vb6 code it would be the equivalent to vb6's fixed size variant or vbscripts variant. If you have anymore ideas parish the source I am going from is above for queueinputreport.


    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 think I had a memory leak or maybe the c++ code skipped over the safearray because it was of the wrong type but I used your first code sample a little modified and it acted like it was going to take it but i did not see my messagebox on the softhidreceiver.dll side.

    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

    If I pass the variant's safe array using its parray parameter it skips over the code but when I pass the actual safearray it passes data but fails at queueinputreport. I think I will report as bug unless someone here thinks they can solve the problem. Update: I have posted my softhidreceiver com server code at the link below. For reference:

    1. softhidreceiver library - com server

    2. multimousesimulator (c++ code) - com server

    3. com client - vb.net test code

    I hope that explains this better to anyone trying to help again.

    Edit: source code is on kinectmultipoint page here: http://kinectmultipoint.codplex.com under downloads section. Its the c++ simulator code. Also, I have posted my softhidreceiver code. If it does not show up then I will reupload.


    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 so I found out that safearraycreatevector function has the FADF_FIXEDSIZE flag always set so I was using the wrong safearraycreate function to begin with. here's the documentation on msdn I was referencing: http://msdn.microsoft.com/en-us/library/ms221558(v=vs.85).aspx/css

    "SafeArrayCreateVector is a fixed size, so the constant FADF_FIXEDSIZE is always set."

    Do I need to do anything special for static or is that set along with FADF_FIXEDSIZE usually?


    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, August 8, 2013 3:16 PM
  • i tested the code and it is working fine for me. the example shows how to create an array of VARIANT containing BYTES and send it to the COM server. That's it. it will be difficult for me to understand your problem with multiple COM dlls etc, hope you

    parish, the actual client is the vb.net/C# app but queueinputreport (softhidreceiver) is called from the second dll (mouseemulator). That's probably why it was hard to test.

    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



    Parish, do you get fFeatures to be 2194? If so then I did something wrong in my code. I'll play with it some more then post my code if I get stuck.

    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

    Parish could you change your variant to have HUGHP? Their is another part in softhidreceiver which uses the same code except for it changes the safearray declaration in code to: SAFEARRAY HUGHP* safearraynamehere;

    I double checked the idl file and its the same as the idl declaration for queueinputreport on createreportdescriptor which does show how they access the array correctly. Heres the code for that which is very similar to yours except the declaration of the safearray is different:

    HRESULT CHIDDevice::CreateReportDescriptor()
    /*++
    Routine Description:
       Constructs the default report descriptors
    
    Arguments:
        none
    
    Return value:
        S_OK
        Otherwise from called function
    --*/
    {
        HRESULT hr                     = S_OK;
        VARIANT HUGEP* pDescriptorData = NULL;
        
        if( m_psaReportDescriptor != NULL )
        {
            SafeArrayDestroy(m_psaReportDescriptor);
            m_psaReportDescriptor = NULL;
        }
    
        BYTE           bReportDescriptorData[ ] = { 
    		  
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,                    // USAGE (Mouse)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Pointer)
    0xa1, 0x00,                    //   COLLECTION (Physical)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
    0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x75, 0x05,                    //     REPORT_SIZE (5)
    0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
    0x09, 0x30,                    //     USAGE (X)
    0x09, 0x31,                    //     USAGE (Y)
    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x02,                    //     REPORT_COUNT (2)
    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
    0xc0, 0xc0                      //   END_COLLECTION
    
    
                                                    // Consumer Controls
                                                    //    0x05,   0x0c,       // Usage Page (Consumer Controls),
                                                    //    0x09,   0x01,       // Usage (Consumer Control),
                                                    //    0xA1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x01,       //  Report Id (1)
                                                    //    0x19,   0x00,       //  Usage Minimum (0),
                                                    //    0x2a,   0x3c, 0x02, //  Usage Maximum (23c)  
                                                    //    0x15,   0x00,       //  Logical Minimum (0),
                                                    //    0x26,   0x3c, 0x02, //  Logical Maximum (23c)  
                                                    //    0x95,   0x01,       //  Report Count (1),
                                                    //    0x75,   0x10,       //  Report Size (16),
                                                    //    0x81,   0x00,       //  Input (Data, Array), 
                                                    //    0xC0,               // End Collection 
                                                    //// MS Vendor controls
                                                    //    0x06,   0xbc, 0xff, // Usage Page (Vendor 0xffbc),
                                                    //    0x09,   0x88,       // Usage (88),
                                                    //    0xa1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x02,       //  Report Id (2)
                                                    //    0x19,   0x01,       //  Usage Minimum (0x01),
                                                    //    0x29,   0xff,       //  Usage Maximum (0xff),
                                                    //    0x15,   0x00,       //  Logical Minimum (0),
                                                    //    0x25,   0x01,       //  Logical Maximum(1),
                                                    //    0x95,   0x01,       //  Report Count (1),
                                                    //    0x75,   0x08,       //  Report Size (8),
                                                    //    0x81,   0x00,       //  Input (Data, Array), 
                                                    //    0xc0,               // End Collection
                                                    //// Standby button
                                                    //    0x05,   0x01,       // Usage Page (Generic Desktop),
                                                    //    0x09,   0x80,       // Usage (System Control),
                                                    //    0xa1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x03,       //  Report Id (3)
                                                    //    0x19,   0x81,       //  Usage Minimum (0x81),
                                                    //    0x29,   0x83,       //  Usage Maximum (0x83),
                                                    //    0x25,   0x01,       //  Logical Maximum(1),
                                                    //    0x75,   0x01,       //  Report Size (1),
                                                    //    0x95,   0x03,       //  Report Count (3),
                                                    //    0x81,   0x02,       //  Input
                                                    //    0x75,   0x01,       //  Report Size (1),   
                                                    //    0x95,   0x05,       //  Report Count (5),
                                                    //    0x81,   0x01,       //  Input (Constant),
                                                    //    0xC0,               // End Collection
                                                    //// Keyboard
                                                    //    0x05,   0x01,       // Usage Page (Generic Desktop),
                                                    //    0x09,   0x06,       // Usage (Keyboard),
                                                    //    0xA1,   0x01,       // Collection (Application),
                                                    //    0x85,   0x04,       //  Report Id (4)
                                                    //    0x05,   0x07,       //  Usage Page (Key Cdes)
                                                    //    0x19,   0xe0,       //  Usage Minimum left control
                                                    //    0x29,   0xe8,       //  Usage Maximum keyboard right gui
                                                    //    0x75,   0x01,       //  Report Size (1)
                                                    //    0x95,   0x08,       //  Report Count (8)
                                                    //    0x81,   0x02,       //  Input (Variable)
                                                    //    0x19,   0x00,       //  Usage Minimum (0)
                                                    //    0x29,   0x90,       //  Usage Maximum (90)
                                                    //    0x26,   0xff, 0x00, //  Logical Maximum (0xff)
                                                    //    0x75,   0x08,       //  Report Size (8)
                                                    //    0x95,   0x01,       //  Report Count (1)
                                                    //    0x81,   0x00,       //  Input (Data, Array),
                                                    //    0xC0                // End Collection
                                                };
        
        // Build a SafeArray Struct that will hold the size and dimension requirements that 
        // will be used during the Safe Array creation
        SAFEARRAYBOUND rgsabound[1];
        ZeroMemory(rgsabound, sizeof(rgsabound));
        rgsabound[0].lLbound = 0;
        rgsabound[0].cElements = sizeof(bReportDescriptorData);
        
        m_psaReportDescriptor = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
        
        if( m_psaReportDescriptor == NULL )
        {
            hr = E_UNEXPECTED;
            goto Exit;
        }
            
        IfFailHrGo( SafeArrayAccessData( m_psaReportDescriptor, 
                                         (void HUGEP**)&pDescriptorData));
    
        INT descSize = sizeof(bReportDescriptorData);
        for( INT i = 0; i < descSize; ++i )
        {
            pDescriptorData[i].vt = VT_UI1;
            pDescriptorData[i].bVal = bReportDescriptorData[i];
        }
    
    Exit:
        SafeArrayUnaccessData(m_psaReportDescriptor);
        return hr;
    }

    Let me explain: the code above is for creating a device without having to write more safearray code to send to tell dsf what device to create but the safearray is accessed close to how the one Iam currently doing is accessed.

    For better reference on the general flow from assemblies and dlls: dotnet client->mouseemulator wrapper dll->softhidreceiver dll. Their are also many other libraries the mouse emulator uses besides softhidreceiver but softhidreceiver is the biggest one.

    Edit: found it trying it out now crossing fingers.


    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 have the full source code here for softhidreceiver parish if you wish to troubleshoot through it yourself:

    https://kinectmultipoint.codeplex.com/downloads/get/713550

    It needs a safe array of variants that are COM automation compatible (Like I said it works in vbscript just fine).  I do know my main c++ atl com dll calls softhidreceiver dll which is another atl com dll project. It appears if I change it to vb6 code it would be the equivalent to vb6's fixed size variant or vbscripts variant. If you have anymore ideas parish the source I am going from is above for queueinputreport.


    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 think I had a memory leak or maybe the c++ code skipped over the safearray because it was of the wrong type but I used your first code sample a little modified and it acted like it was going to take it but i did not see my messagebox on the softhidreceiver.dll side.

    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

    If I pass the variant's safe array using its parray parameter it skips over the code but when I pass the actual safearray it passes data but fails at queueinputreport. I think I will report as bug unless someone here thinks they can solve the problem. Update: I have posted my softhidreceiver com server code at the link below. For reference:

    1. softhidreceiver library - com server

    2. multimousesimulator (c++ code) - com server

    3. com client - vb.net test code

    I hope that explains this better to anyone trying to help again.

    Edit: source code is on kinectmultipoint page here: http://kinectmultipoint.codplex.com under downloads section. Its the c++ simulator code. Also, I have posted my softhidreceiver code. If it does not show up then I will reupload.


    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 so I found out that safearraycreatevector function has the FADF_FIXEDSIZE flag always set so I was using the wrong safearraycreate function to begin with. here's the documentation on msdn I was referencing: http://msdn.microsoft.com/en-us/library/ms221558(v=vs.85).aspx/css

    "SafeArrayCreateVector is a fixed size, so the constant FADF_FIXEDSIZE is always set."

    Do I need to do anything special for static or is that set along with FADF_FIXEDSIZE usually?


    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 think I did something wrong now Iam getting more then 2194 for fFeatures. Well at least iam getting some progress and know that it might involve my safearraycreate function I use. Note: this safearray Iam trying to create above is always one dimensional so create vector is fine for our purposes if it works.

    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 Thursday, August 8, 2013 3:37 PM edit 2
    Thursday, August 8, 2013 3:36 PM