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];
}
}