What is a SAFEARRAY and how do you get information from it?

Just starting out? Need help? Post your questions and find answers here.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

What is a SAFEARRAY and how do you get information from it?

Post by SFSxOI »

I'm curently working with IMAPIv2, i've run into a stumbling block with some of the items being a SAFEARRAY, like this little jewel of a C++ function in the IDiscRecorder2 Interface:

Code: Select all

get_VolumePathNames([out]  SAFEARRAY* value)
According to the msdn description at http://msdn2.microsoft.com/en-us/librar ... S.85).aspx

it says: "value
List of drive letters and NTFS mount points for the device. Each element of the list is a VARIANT of type VT_BSTR. The bstrVal member of the variant contains the path."

so I did the bstrVal member and what I get back for the
pp.variant
pp\vt = #VT_BSTR
is just a 6 digit number and when i try to convert that with Uni2Ansi(pp\bstrval) I just get a bunch of strange characters like '?+'.

Whats the secret with the SAFEARRAY thing? Is this some type of UniCode thing?
traumatic
PureBasic Expert
PureBasic Expert
Posts: 1661
Joined: Sun Apr 27, 2003 4:41 pm
Location: Germany
Contact:

Re: What is a SAFEARRAY and how do you get information from

Post by traumatic »

Good programmers don't comment their code. It was hard to write, should be hard to read.
User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Post by Shardik »

A SAFEARRAY is an array of variants and you receive a pointer to a Variant which points to the SAFEARRAY structure. I am using the following code fragment quite frequently (to query infos for administrative purposes from a Novell directory (NDS) with the Novell API [which is not shown here], because many Novell API ActiveX query functions return their result as a SAFEARRAY):

Code: Select all

Structure SAFEARRAYBOUND
  cElements.L  ; # of elements in the array dimension
  lLbound.L    ; Lower bounds of the array dimension
EndStructure

Structure SAFEARRAY
  cDims.W
  fFeatures.W
  cbElements.L
  cLocks.L
  pvData.L
  rgsabound.SAFEARRAYBOUND[60]
EndStructure

Procedure.S GetVariantString(*Variant.VARIANT)
  Protected String.S = ""

  If VariantChangeType_(*Variant, *Variant, 0, #VT_BSTR) = #S_OK
    String = PeekS(*Variant\bstrVal, -1, #PB_Unicode)
    VariantClear_(*Variant)
  Else
    Debug "VariantChangeType() failed!"
  EndIf

  ProcedureReturn String  
EndProcedure

Define *Variant.VARIANT
Define *VariantArray.SAFEARRAY

*Variant = PeekL(*value)
*VariantArray = *Variant\parray

For i = 1 To *VariantArray\rgsabound[0]\cElements
  *Variant = *VariantArray\pvData + (i - 1) * 16
  Debug GetVariantString(*Variant)
Next i
Try to use the return value

Code: Select all

*value = get_VolumePathNames(value.SAFEARRAY)
in my above example after adding your interface definitions and the other stuff.

Here you can find a fine tutorial about SAFEARRAY (unfortunately only in German, but the VisualBASIC codes and the images should be self explaining (especially figure 3) :wink:):
http://www.activevb.de/tutorials/tut_sa ... array.html
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

removed code from this post, sending corect code to tips section
Last edited by SFSxOI on Thu Jan 17, 2008 10:56 pm, edited 6 times in total.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Never mind the above post...finally got the safearray thing working. What a PITA! Why the heck does MS need to make it so difficult.

Anyway, thank you for your help folks. :)

post the working code above in the corected post.
harff182
Enthusiast
Enthusiast
Posts: 105
Joined: Thu Dec 08, 2005 4:58 pm
Location: Duesseldorf, Germany

Post by harff182 »

This code does NOT work with 2 Drives !!!!!!!!

Please, have a look at the code I put in the other thread and compare.
Sorry 4 my poor English, it's the only one I learned 40 years ago...
since 17.12.08: XPHome(SP3) + PB 4.30
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

sure it does, look at the other post. Works fine here for multiple drives on Windows Vista Ultimate.
harff182 wrote:This code does NOT work with 2 Drives !!!!!!!!

Please, have a look at the code I put in the other thread and compare.
harff182
Enthusiast
Enthusiast
Posts: 105
Joined: Thu Dec 08, 2005 4:58 pm
Location: Duesseldorf, Germany

Post by harff182 »

The code above in your post from 16 Jan 2008 1:13:14 can not work correctly on any computer IMHO, especially here, when I write this answer.

At first, the Uni2Ansi() is missing.

If I insert the Procedure, that jack pointed at in the other thread, I get this:
Debugger wrote:drive: 2 is ID: \\?\ide#cdromhl-dt-st_dvdram_gsa-4163b_______________a106____#334b354333313242313020322020202020202020#{53f56308-b6bf-11d0-94f2-00a0c91efb8b}
Media Type is Unknown or no media loaded
HL-DT-ST
DVDRAM GSA-4163B
A106
\\?\Volume{fcfbbcce-478a-11dc-bd62-806d6172696f}\
Your Drive Path is: Y:\
Environment is supported!
Device can eject and reload media!
Legacy number is: 1
Recorder is supported
\\?\ide#cdromhl-dt-st_dvdram_gsa-4163b_______________a106____#334b354333313242313020322020202020202020#{53f56308-b6bf-11d0-94f2-00a0c91efb8b}

drive: 2 is ID: \\?\ide#cdromtsstcorp_cd#dvdw_sh-s182d_______________sb06____#5&39971a7a&0&0.1.0#{53f56308-b6bf-11d0-94f2-00a0c91efb8b}
Media Type is Unknown or no media loaded
HL-DT-ST
DVDRAM GSA-4163B
A106
\\?\Volume{fcfbbcce-478a-11dc-bd62-806d6172696f}\
Your Drive Path is: Y:\
Environment is supported!
Device can eject and reload media!
Legacy number is: 1
Recorder is supported
\\?\ide#cdromhl-dt-st_dvdram_gsa-4163b_______________a106____#334b354333313242313020322020202020202020#{53f56308-b6bf-11d0-94f2-00a0c91efb8b}
[/b]
It debuggs output twice for "drive: 2", a third drive I don't have !

If I replace

Code: Select all

Debug "drive:   " +Str(count) +"   is ID:    " +Uni2Ansi(pp\bstrval)
by

Code: Select all

Debug "drive:   " +Str(x) +"   is ID:    " +Uni2Ansi(pp\bstrval)
I get this:
Debugger wrote:drive: 0 is ID: \\?\ide#cdromhl-dt-st_dvdram_gsa-4163b_______________a106____#334b354333313242313020322020202020202020#{53f56308-b6bf-11d0-94f2-00a0c91efb8b}
Media Type is Unknown or no media loaded
HL-DT-ST
DVDRAM GSA-4163B
A106
\\?\Volume{fcfbbcce-478a-11dc-bd62-806d6172696f}\
Your Drive Path is: Y:\
Environment is supported!
Device can eject and reload media!
Legacy number is: 1
Recorder is supported
\\?\ide#cdromhl-dt-st_dvdram_gsa-4163b_______________a106____#334b354333313242313020322020202020202020#{53f56308-b6bf-11d0-94f2-00a0c91efb8b}

drive: 1 is ID: \\?\ide#cdromtsstcorp_cd#dvdw_sh-s182d_______________sb06____#5&39971a7a&0&0.1.0#{53f56308-b6bf-11d0-94f2-00a0c91efb8b}
Media Type is Unknown or no media loaded
HL-DT-ST
DVDRAM GSA-4163B
A106
\\?\Volume{fcfbbcce-478a-11dc-bd62-806d6172696f}\
Your Drive Path is: Y:\
Environment is supported!
Device can eject and reload media!
Legacy number is: 1
Recorder is supported
\\?\ide#cdromhl-dt-st_dvdram_gsa-4163b_______________a106____#334b354333313242313020322020202020202020#{53f56308-b6bf-11d0-94f2-00a0c91efb8b}
Now the drives are "enumerated" correctly, but the rest of the debug-output for drive 1 is the same as for drive 0, which is not correct, as they are different models from different vendors with different media inside to test.

If someone reads and tries the code above, who has installed more than 1 drive (like me) and does not know about the other thread, he will most probably fail and be disappointed.

That, and only that, was my point, as I truely respect your work because it led me to a proc I can now use in my video-database to determine the media my movies are on.
Sorry 4 my poor English, it's the only one I learned 40 years ago...
since 17.12.08: XPHome(SP3) + PB 4.30
Post Reply