private ADObject[] ProcessSelections(IDataObject dataObj) { if (dataObj == null) { return(null); } using (logX.loggerX.InfoCall()) { ADObject[] selections = null; // The STGMEDIUM structure is a generalized global memory handle used for data transfer operations STGMEDIUM stg = new STGMEDIUM(); stg.tymed = (uint)TYMED.TYMED_HGLOBAL; stg.hGlobal = IntPtr.Zero; stg.pUnkForRelease = IntPtr.Zero; // The FORMATETC structure is a generalized Clipboard format. FORMATETC fe = new FORMATETC(); fe.cfFormat = (short)System.Windows.Forms.DataFormats.GetFormat("CFSTR_DSOP_DS_SELECTION_LIST").Id; //The CFSTR_DSOP_DS_SELECTION_LIST clipboard format is provided by the IDataObject obtained by calling IDsObjectPicker::InvokeDialog fe.ptd = IntPtr.Zero; fe.dwAspect = (uint)DVASPECT.DVASPECT_CONTENT; fe.lindex = -1; // all of the data fe.tymed = (uint)TYMED.TYMED_HGLOBAL; //The storage medium is a global memory handle (HGLOBAL) dataObj.GetData(ref fe, ref stg); IntPtr pDsSL = PInvoke.GlobalLock(stg.hGlobal); try { // the start of our structure IntPtr current = pDsSL; // get the # of items selected logX.loggerX.Debug("Start Read Int 32"); int cnt = (int)Marshal.ReadInt32(current); logX.loggerX.Debug("Finish Read Int 32"); // if we selected at least 1 object if (cnt > 0) { selections = new ADObject[cnt]; logX.loggerX.Debug("Line: 1"); // increment the pointer so we can read the DS_SELECTION structure current = (IntPtr)((Int64)current + (Marshal.SizeOf(typeof(uint)) * 2)); //SQLsecure 3.1 (Tushar)--Fix for issue SQLSECU-1972 logX.loggerX.Debug("Line: 2"); // now loop through the structures for (int i = 0; i < cnt; i++) { // marshal the pointer to the structure DS_SELECTION s = (DS_SELECTION)Marshal.PtrToStructure(current, typeof(DS_SELECTION)); logX.loggerX.Debug("Line: 3"); // Marshal.DestroyStructure(current, typeof (DS_SELECTION)); logX.loggerX.Debug("Line: 4"); // increment the position of our pointer by the size of the structure current = (IntPtr)((Int64)current + Marshal.SizeOf(typeof(DS_SELECTION))); //SQLsecure 3.1 (Tushar)--Fix for issue SQLSECU-1972 logX.loggerX.Debug("Line: 5"); selections[i] = new ADObject(); selections[i].Name = s.pwzName; selections[i].AdsPath = s.pwzADsPath; selections[i].UPN = s.pwzUPN; selections[i].ClassName = s.pwzClass; IntPtr ptrFetched = s.pvarFetchedAttributes; logX.loggerX.Debug("Line: 6"); VARIANT vr = (VARIANT)Marshal.PtrToStructure(ptrFetched, typeof(VARIANT)); logX.loggerX.Debug("Line: 7"); string str = Marshal.PtrToStringUni(vr.bstrVal); logX.loggerX.Debug("Line: 8"); selections[i].SamAccountName = str; int vt = vr.vt; IntPtr ptrSid = (IntPtr)((Int64)ptrFetched + (Marshal.SizeOf(typeof(VARIANT)))); //SQLsecure 3.1 (Tushar)--Fix for issue SQLSECU-1972 logX.loggerX.Debug("Line: 9"); vr = (VARIANT)Marshal.PtrToStructure(ptrSid, typeof(VARIANT)); logX.loggerX.Debug("Line: 10"); IntPtr pSids = IntPtr.Zero; IntPtr pUBound = IntPtr.Zero; int hr = PInvoke.SafeArrayAccessData(vr.pArray, out pSids); logX.loggerX.Debug("Line: 11"); hr = PInvoke.SafeArrayGetUBound(vr.pArray, 1, out pUBound); logX.loggerX.Debug("Line: 12"); Byte[] sid = new Byte[pUBound.ToInt32() + 1]; logX.loggerX.Debug("Line: 13"); for (int nBytes = 0; nBytes <= pUBound.ToInt32(); nBytes++) { sid.SetValue(Marshal.ReadByte(pSids, nBytes), nBytes); } logX.loggerX.Debug("Line: 14"); selections[i].Sid = new Sid(sid); ////This is how to obtain the Sid manually via lookup instead of by attribute ////Binding to the User object //DirectoryEntry dr = new DirectoryEntry(selections[i].AdsPath); //dr.RefreshCache(); ////To get ObjectSid //selections[i].Sid = new Sid((byte[])dr.Properties["objectSid"].Value); //This will get another string value //ptrNext = (IntPtr)((int)ptrSid + (Marshal.SizeOf(typeof(VARIANT)))); //vr = (VARIANT)Marshal.PtrToStructure(ptrNext, typeof(VARIANT)); //str = Marshal.PtrToStringUni(vr.bstrVal); //build the SamAccount string with domain\SamAccountName string domain; bool isFlat; if (Path.IsWinntPath(s.pwzADsPath)) { // the browser doesn't return a SamAccountName for winnt paths // so process the path for it string samPath; Path.GetSamPathFromWinNTPath(s.pwzADsPath, out samPath); selections[i].SamAccountName = samPath; } else { //Get Domain Name and build it on to the SamAccountName Path.ExtractDomainFromPath(s.pwzADsPath, out domain, out isFlat); DOMAIN_CONTROLLER_INFO dcInfo; if (!isFlat) { uint nameInFlag = (uint)DsGetDcFlags.DS_IS_DNS_NAME; // Call DsGetDcName to get the flat domain info. uint flags = ((uint)DsGetDcFlags.DS_RETURN_FLAT_NAME | nameInFlag); uint rc = DS.DsGetDcName("", domain, flags, out dcInfo); if (rc != Win32Errors.ERROR_SUCCESS) { logX.loggerX.Error("ERROR - Failed to get flat name DC info for the domain", domain); return(null); } else { domain = dcInfo.DomainName; } } logX.loggerX.Debug("Line: 100"); selections[i].SamAccountName = Path.MakeSamPath(domain, selections[i].SamAccountName); } } } } finally { PInvoke.GlobalUnlock(pDsSL); } return(selections); } }