[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.dotnet.framework.interop

E_NOTIMPL in GetData method when querying objectSID from Directory Object Picker

Beat Bucheli

8/7/2007 9:14:00 AM

Hi,

I'm trying to get the objectSID from the active directory objects selected
in the directory object picker dialog. But IDataObject.GetData() returns
always 0x80004001 (E_NOTIMPL) when I supply the attribute 'objectSID' in
DSOP_INIT_INFO. Without this attribute (cAttributesToFetch=0), the code
works. I also have a sample using the same flags and settings written in
Delphi that works fine. So I suppose the marshalling is incorrect, but I
don't know where. Below is an excerpt of my code.

Thanks very much for any help.
Beat


[ComImport, Guid("17D6CCD8-3B7B-11D2-B9E0-00C04FD8DBF7")]
public class DSObjectPicker {}

[ComImport, Guid("0C87E64E-3B7A-11D2-B9E0-00C04FD8DBF7"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDsObjectPicker
{
void Initialize(ref DSOP_INIT_INFO pInitInfo);
void InvokeDialog(IntPtr HWND, out IDataObject lpDataObject);
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct DSOP_INIT_INFO
{
public uint cbSize;
[MarshalAs(UnmanagedType.LPWStr)]
public string pwzTargetComputer;
public uint cDsScopeInfos;
public IntPtr aDsScopeInfos;
public uint flOptions;
public uint cAttributesToFetch;
public IntPtr apwzAttributeNames;
}

// other structs, enums, ... (skipped)

public class ObjectPickerWrapper
{
public ADObject[] ShowObjectPicker(IntPtr parentHandle)
{
DSObjectPicker picker = new DSObjectPicker();
IDsObjectPicker ipicker = (IDsObjectPicker)picker;

DSOP_SCOPE_INIT_INFO[] scopeInitInfo = new DSOP_SCOPE_INIT_INFO[1];

scopeInitInfo[0].cbSize =
(uint)Marshal.SizeOf(typeof(DSOP_SCOPE_INIT_INFO));
scopeInitInfo[0].flType =
DSOP_SCOPE_TYPE_FLAGS.DSOP_SCOPE_TYPE_GLOBAL_CATALOG;
scopeInitInfo[0].FilterFlags.Uplevel.flBothModes =
DSOP_FILTER_FLAGS_FLAGS.DSOP_FILTER_USERS; // ...

scopeInitInfo[0].FilterFlags.flDownlevel =
DSOP_DOWNLEVEL_FLAGS.DSOP_DOWNLEVEL_FILTER_USERS; // ...

scopeInitInfo[0].pwzADsPath = null;
scopeInitInfo[0].pwzDcName = null;
scopeInitInfo[0].hr = 0;

IntPtr refScopeInitInfo = Marshal.AllocHGlobal(
Marshal.SizeOf(typeof(DSOP_SCOPE_INIT_INFO)) *
scopeInitInfo.Length);
Marshal.StructureToPtr(scopeInitInfo[0], refScopeInitInfo, true);

DSOP_INIT_INFO initInfo = new DSOP_INIT_INFO();
initInfo.pwzTargetComputer = null;
initInfo.flOptions = DSOP_INIT_INFO_FLAGS.DSOP_FLAG_MULTISELECT;
initInfo.cDsScopeInfos = 1;
initInfo.aDsScopeInfos = refScopeInitInfo;

string attrName = "objectSID";
IntPtr refAttrName = Marshal.StringToHGlobalUni(attrName);
initInfo.cAttributesToFetch = 1;
initInfo.apwzAttributeNames = refAttrName; // <== marshalling /
memory layout ok??

ipicker.Initialize(ref initInfo);

// show the dialog
IDataObject dataObj = null;
ipicker.InvokeDialog(parentHandle, out dataObj);

FORMATETC fmt = new FORMATETC();
fmt.cfFormat =
(short)System.Windows.Forms.DataFormats.GetFormat("CFSTR_DSOP_DS_SELECTION_LIST").Id;
// -15497 (unsigned 50039)
fmt.ptd = IntPtr.Zero;
fmt.dwAspect = DVASPECT.DVASPECT_CONTENT;
fmt.lindex = -1;
fmt.tymed = TYMED.TYMED_HGLOBAL;

STGMEDIUM stg = new STGMEDIUM();

// int res = dataObj.QueryGetData(ref fmt); // <== HRESULT is
always 0x80004001 (E_NOTIMPL)

dataObj.GetData(ref fmt, out stg); // throws 'not implemented'
Exception from HRESULT 0x80004001 (E_NOTIMPL)

// ... processing stg... (skipped)

return new ADObject[0];
}
}



1 Answer

Beat Bucheli

8/20/2007 1:31:00 PM

0

.... the marshalling of the string array was incorrect. It can be done like
this:



public sealed class packLPArray

{

private IntPtr taskAlloc;

private readonly int _length;

private IntPtr[] _strings;



public packLPArray(string[] theArray)

{

int sizeIntPtr = IntPtr.Size;

int neededSize = 0;

if (theArray != null)

{

this._length = theArray.Length;

this._strings = new IntPtr[this._length];

neededSize = this._length * sizeIntPtr;

this.taskAlloc = Marshal.AllocCoTaskMem(neededSize);

for (int cx = this._length - 1; cx >= 0; cx--)

{

this._strings[cx] =
Marshal.StringToCoTaskMemUni(theArray[cx]);

Marshal.WriteIntPtr(this.taskAlloc, cx * sizeIntPtr,
this._strings[cx]);

}

}

}



public IntPtr arrayPtr

{

get { return this.taskAlloc; }

}



~packLPArray()

{

if (taskAlloc != IntPtr.Zero)

{

Marshal.FreeCoTaskMem(this.taskAlloc);

int cx = this._length;

while(cx-- != 0)

Marshal.FreeCoTaskMem(this._strings[cx]);

}

}

}



....

packLPArray packit = new packLPArray( new string[]
{"SamAccountName","cn","Adspath","objectsid"});

initInfo.cAttributesToFetch = 4;

initInfo.apwzAttributeNames = packit.arrayPtr;

....



Beat