mIRC Home    About    Download    Register    News    Help

Topic Options
#259631 - 05/01/17 03:38 PM VT_ARRAY when retrieving COM results
FroggieDaFrog Online
Hoopy frood

Registered: 16/04/10
Posts: 784
Loc: USA
As far as I can tell, mIRC does not support VT_ARRAY(binary byte arrays) when it comes to retrieving data from a COM. It'd be great to see this added, especially with the inclusion of com bvar support.

When $com().result is called, if
...the output ISN'T a bvar, convert to string
...the output IS a bvar, fill the bvar with the binary data

The use case:
Using an MS/Windows provided HTTP request object, namely SERVERXMLHttpRequest to retrieve data from a website, the body can be retrieved using .responseBody as a byte array but mIRC is unable to handle such a result, resulting in the returned value being null


Edited by FroggieDaFrog (05/01/17 03:44 PM)
_________________________
I am SReject
My Stuff

Top
#259659 - 07/01/17 05:24 AM Re: VT_ARRAY when retrieving COM results [Re: FroggieDaFrog]
FroggieDaFrog Online
Hoopy frood

Registered: 16/04/10
Posts: 784
Loc: USA
a use-case code example
Code:
alias example {
  var %Error


  ;; Create an instance of MS provided http requester
  ;; and use it to request http://example.com
  .comopen example MSXML2.SERVERXMLHttp.6.0
  if (!$com(example) || $comerr) {
    %Error = Unable to create an instance of MSXML2.SERVERXMLHttp.6.0
  }
  elseif (!$com(example, open, 1, bstr, GET, bstr, http://example.com, bool, false) || $comerr) {
    %Error = Unable to initialize the request
  }
  elseif (!$com(example, send, 1) || $comerr) {
    %Error = Request failed
  }
  else {



    ;; To get the response as purely text, this works flawlessly
    if (!$com(example, responseText, 2) || $comerr) {
      %Error = Failed to retrieve response text
    }
    else {
      noop $com(example, &example).result
      echo -s Reponse Text( $+ $bvar(&example, 0) $+ ): $bvar(&example, 1, 4000).text
      echo -s -
      bunset &example
    }


    ;; But to retrieve the response body as binary data
    ;; This echos an empty string due to mIRC being unable
    ;; to handle VT_ARRAYs
    if (!$com(example, responseBody, 2) || $comerr) {
      %Error = Failed to retrieve response text
    }
    else {
      noop $com(example, &example).result
      echo -s Reponse Body( $+ $bvar(&example, 0) $+ ): $bvar(&example, 1, 4000).text
      echo -s -
      bunset &example
    }

  }


  ;; Handle errors
  :Error
  if ($error) {
    %Error = $v1
    reseterror
  }
  if ($com(example)) {
    .comclose example
  }
  if (%Error) {
    echo -s Error: $v1
  }
}
_________________________
I am SReject
My Stuff

Top
#259662 - 07/01/17 02:00 PM Re: VT_ARRAY when retrieving COM results [Re: FroggieDaFrog]
westor Offline
Hoopy frood

Registered: 27/12/08
Posts: 1438
Loc: Greece
WOW !!! this is crazy good idea, i hope this will be added in next releases...
_________________________
Need Online mIRC help or an mIRC Scripting Freelancer? -> http://westor.ucoz.com/contact <-

Top
#259687 - 12/01/17 09:03 AM Re: VT_ARRAY when retrieving COM results [Re: FroggieDaFrog]
Khaled Offline


Planetary brain

Registered: 04/12/02
Posts: 3841
Loc: London, UK
mIRC currently handles twenty variant types. In the case of the example you provided, the variant type is VT_UI1, which is a single byte, so it would be easy enough to copy it into a binary variable. For multibyte types, the binary variable would need to be filled with multibyte values and the scripter would have to know the byte size of the type in order to parse the binary variable. In the case of VT_BSTR, the binary variable would need to be filled with multiple, consecutive strings (that are first converted from BSTR to UTF-8), each terminated with a NULL character, and the scripter would need to parse the binary variable accordingly.

The byte sizes for the variant types are:
1: VT_I1, VT_UI1
2: VT_I2, VT_UI2, VT_BOOL
4: VT_I4, VT_UI4, VT_R4, VT_INT, VT_UINT, VT_ERROR
8: VT_I8, VT_UI8, VT_R8, VT_CY, VT_DATE, VT_DECIMAL
?: VT_BSTR, VT_DISPATCH, VT_UNKNOWN

So far, I have tested VT_UI1 with the example you provided. Do you have examples that return arrays of other variant types? And one that returns an array of VT_BSTR?

Top
#259690 - 12/01/17 12:52 PM Re: VT_ARRAY when retrieving COM results [Re: Khaled]
FroggieDaFrog Online
Hoopy frood

Registered: 16/04/10
Posts: 784
Loc: USA
My main concern was for VT_UI1 typed VT_ARRAYs as many MS-provided objects return strings in this type(why not just a BSTR; only MS knows).

I do not have examples of VB_BSTR or other types in use and my search has come up empty, if I do stumble up on such I'll be sure to let you know.


Edited by FroggieDaFrog (12/01/17 12:52 PM)
_________________________
I am SReject
My Stuff

Top
#259692 - 12/01/17 04:15 PM Re: VT_ARRAY when retrieving COM results [Re: FroggieDaFrog]
Khaled Offline


Planetary brain

Registered: 04/12/02
Posts: 3841
Loc: London, UK
No problem, I found a way to create arrays of different variant types to test the array parsing code and it seems to handle arrays of VT_BSTR and other types fine. This should be in the next beta.

Top
#259703 - 13/01/17 02:26 PM Re: VT_ARRAY when retrieving COM results [Re: Khaled]
FroggieDaFrog Online
Hoopy frood

Registered: 16/04/10
Posts: 784
Loc: USA
To add to this feature request is there a chance you would add some way for us to pass data into a COM instance as a VT_ARRAY containing VT_UI1 items? Again, this is how many MS-provided objects represent raw byte data(such as the contents of a non-text file).


Something along the lines of:
Code:
;; Where <TYPE> is the contained items' type
$com(name, member, method, array [&]type[* varname], &bvar|inputString)

ex:
$com(name, member, method, array &ui1, &bvar)

Personally I'd only consider fixed-length array-item types for this and have checks to make sure the amount of bytes in the input is divisible by the fixed-length of the item-type prior to making the COM call.


Edited by FroggieDaFrog (13/01/17 03:16 PM)
_________________________
I am SReject
My Stuff

Top
#259706 - 13/01/17 07:53 PM Re: VT_ARRAY when retrieving COM results [Re: FroggieDaFrog]
Khaled Offline


Planetary brain

Registered: 04/12/02
Posts: 3841
Loc: London, UK
Okay, it looks like I will need to leave this, and the original request, for the next version as they both require critical changes to the COM routines. On to-do list however.

Top
#259743 - 20/01/17 11:56 AM Re: VT_ARRAY when retrieving COM results [Re: FroggieDaFrog]
Khaled Offline


Planetary brain

Registered: 04/12/02
Posts: 3841
Loc: London, UK
Can you provide an example $com() call that passes an array of ui1 into a COM instance? Ideally, a method that I can use to verify that the array is being passed correctly.

Top
#259744 - 20/01/17 02:27 PM Re: VT_ARRAY when retrieving COM results [Re: Khaled]
FroggieDaFrog Online
Hoopy frood

Registered: 16/04/10
Posts: 784
Loc: USA
If I read correctly you are looking for an example of passing a UI1 array INTO a com instance, correct? If so the below example will write the specified data to file for you to verify:

Code:
alias ui1_inputTest {

  ;; DATA TO PASS INTO THE THE COM AS A UI1 ARRAY  
  bset -t &ui1_data 1 this is some data to send as ui1_array
  
  
  comopen ui1_test ADODB.Stream
  if (!$com(ui1_test) || $comerr) {
    echo -a failed to create stream instance
  }
  elseif (!$com(ui1_test, open, 1) || $comerr) {
    echo -a Failed to open stream
  }
  elseif (!$com(ui1_test, type, 4, integer, 1) || $comerr) {
    echo -a Failed to set the read/write type to binary
  }

  
  ;; THIS LINE PASSES A UI1 ARRAY INTO THE COM
  elseif (!$com(ui1_test, write, 1, array &ui1, &ui1_data) || $comerr) {
    echo -a Failed to write data to stream
  }
  
  
  elseif (!$com(ui1_test, position, 4, integer, 0) || $comerr) {
    echo -a Failed to reset position
  }
  elseif (!$com(ui1_test, saveToFile, 1, bstr, $mircdirui1_text.dat, integer, 2) || $comerr) {
    echo -a Failed to save to file
  }
  elseif (!$com(ui1_test, close, 1) || $comerr) {
    echo -a Failed to close stream
  }
  else {
    echo -a All done; check $mircdirui1_text.dat to see what was wrote
  }
  
  if ($com(ui1_test)) .comclose ui1_test
}


Edited by Khaled (20/01/17 06:59 PM)
_________________________
I am SReject
My Stuff

Top
#259746 - 20/01/17 07:13 PM Re: VT_ARRAY when retrieving COM results [Re: FroggieDaFrog]
Khaled Offline


Planetary brain

Registered: 04/12/02
Posts: 3841
Loc: London, UK
Thanks, both of your examples appear to be working with the new array support, so it is looking good. For the time being, I have limited array support to one dimensional VT_UI1/VT_I1 arrays. This should be in the next beta.

Top
#259752 - 22/01/17 07:47 PM Re: VT_ARRAY when retrieving COM results [Re: Khaled]
FroggieDaFrog Online
Hoopy frood

Registered: 16/04/10
Posts: 784
Loc: USA
This is very much appreciated
_________________________
I am SReject
My Stuff

Top
#259784 - 26/01/17 12:44 PM Re: VT_ARRAY when retrieving COM results [Re: FroggieDaFrog]
Khaled Offline


Planetary brain

Registered: 04/12/02
Posts: 3841
Loc: London, UK
I have uploaded a beta with these changes. It required changes to the way $com() results are handled, so $com() will need some general testing, in addition to testing the above changes, to make sure that it is working correctly.

Top
#259789 - 26/01/17 08:40 PM Re: VT_ARRAY when retrieving COM results [Re: Khaled]
FroggieDaFrog Online
Hoopy frood

Registered: 16/04/10
Posts: 784
Loc: USA
So far, the changes haven't effected my pre-existing scripts, and the additions are working marvelously. Thank you
_________________________
I am SReject
My Stuff

Top