///<Summary>Given an IntPtr pointing to a CIDA, /// copy the CIDA to a new MemoryStream</Summary> private MemoryStream MakeStreamFromCIDA(IntPtr ptr) { MemoryStream returnValue; returnValue = null; //assume failure if (ptr.Equals(IntPtr.Zero)) { return(returnValue); } int nrItems = Marshal.ReadInt32(ptr, 0); if (!(nrItems > 0)) { return(returnValue); } int[] offsets = new int[nrItems + 1]; int curB = 4; //already read first 4 int i; for (i = 0; i <= nrItems; i++) { offsets[i] = Marshal.ReadInt32(ptr, curB); curB += 4; } int pidlLen = 0; object[] pidlobjs = new object[nrItems + 1]; for (i = 0; i <= nrItems; i++) { IntPtr ipt = new IntPtr(ptr.ToInt32() + offsets[i]); ExpTreeLib.CShItem.cPidl cp = new ExpTreeLib.CShItem.cPidl(ipt); pidlobjs[i] = cp.PidlBytes; pidlLen += ((byte[])(pidlobjs[i])).Length; } returnValue = new MemoryStream(pidlLen + (4 * offsets.Length) + 4); BinaryWriter BW = new BinaryWriter(returnValue); BW.Write(nrItems); for (i = 0; i <= nrItems; i++) { BW.Write(offsets[i]); } for (i = 0; i <= nrItems; i++) { BW.Write((byte[])(pidlobjs[i])); } // DumpHex(MakeStreamFromCIDA.ToArray) returnValue.Seek(0, SeekOrigin.Begin); return(returnValue); }
///<Summary>Given an IntPtr pointing to a CIDA, /// copy the CIDA to a new MemoryStream</Summary> private MemoryStream MakeStreamFromCIDA(IntPtr ptr) { MemoryStream returnValue; returnValue = null; //assume failure if (ptr.Equals(IntPtr.Zero)) { return returnValue; } int nrItems = Marshal.ReadInt32(ptr, 0); if (!(nrItems > 0)) { return returnValue; } int[] offsets = new int[nrItems + 1]; int curB = 4; //already read first 4 int i; for (i = 0; i <= nrItems; i++) { offsets[i] = Marshal.ReadInt32(ptr, curB); curB += 4; } int pidlLen = 0; object[] pidlobjs = new object[nrItems + 1]; for (i = 0; i <= nrItems; i++) { IntPtr ipt = new IntPtr(ptr.ToInt32() + offsets[i]); ExpTreeLib.CShItem.cPidl cp = new ExpTreeLib.CShItem.cPidl(ipt); pidlobjs[i] = cp.PidlBytes; pidlLen += ((byte[]) (pidlobjs[i])).Length; } returnValue = new MemoryStream(pidlLen + (4 * offsets.Length) + 4); BinaryWriter BW = new BinaryWriter(returnValue); BW.Write(nrItems); for (i = 0; i <= nrItems; i++) { BW.Write(offsets[i]); } for (i = 0; i <= nrItems; i++) { BW.Write((byte[]) (pidlobjs[i])); } // DumpHex(MakeStreamFromCIDA.ToArray) returnValue.Seek(0, SeekOrigin.Begin); return returnValue; }
///<Summary> /// Shell Folders prefer their IDragData to contain this format which is /// NOT directly supported by .Net. The underlying structure is the CIDA structure /// which is basically VB and VB.Net Hostile. ///If "Make ShortCut(s) here" is the desired or /// POSSIBLE effect of the drag, then this format is REQUIRED -- otherwise the /// Folder will interpret the DragDropEffects.Link to be "Create Document Shortcut" /// which is NEVER the desired effect in this case /// The normal CIDA contains the Absolute PIDL of the source Folder and /// Relative PIDLs for each Item in the Drag. /// I cheat a bit an provide the Absolute PIDL of the Desktop (00, a short) /// and the Absolute PIDLs for the Items (all such Absolute PIDLS ar /// relative to the Desktop. ///</Summary> ///<Credit>http://www.dotnetmonster.com/Uwe/Forum.aspx/dotnet-interop/3482/Drag-and-Drop /// The overall concept and much code taken from the above reference /// Dave Anderson's response, translated from C# to VB.Net, was the basis /// of this routine /// An AHA momemnt and a ref to the above url came from ///http://www.Planet-Source-Code.com/vb/scripts/ShowCode.asp?txtCodeId=61324%26lngWId=1 /// ///</Credit> public static System.IO.MemoryStream MakeShellIDArray(ArrayList CSIList) { System.IO.MemoryStream returnValue; //ensure that we have an arraylist of only CShItems Type AllowedType = typeof(CShItem); object oCSI; foreach (object tempLoopVar_oCSI in CSIList) { oCSI = tempLoopVar_oCSI; if (!AllowedType.Equals(oCSI.GetType())) { return(null); } } //ensure at least one item if (CSIList.Count < 1) { return(null); } //bArrays is an Array of Byte() each containing the bytes of a PIDL object[] bArrays = new object[CSIList.Count]; CShItem CSI; int i = 0; foreach (CShItem tempLoopVar_CSI in CSIList) { CSI = tempLoopVar_CSI; bArrays[i] = new ExpTreeLib.CShItem.cPidl(CSI.PIDL).PidlBytes; i++; } returnValue = new System.IO.MemoryStream(); System.IO.BinaryWriter BW = new System.IO.BinaryWriter(returnValue); BW.Write(Convert.ToUInt32(CSIList.Count)); //we don't count the parent (Desktop) int Desktop = 0; //we only use the lowval 2 bytes (VB lacks meaninful uint) int Offset; //offset into Structure of a PIDL // Calculate and write the offset to each pidl (defined as an array of uint32) // The first pidl is 2 bytes long (0 0) and represents the desktop // The 2 in the statement below is for the offset to the // folder pidl and the count field in the CIDA structure Offset = Marshal.SizeOf(typeof(UInt32)) * (bArrays.Length + 2); BW.Write(Convert.ToUInt32(Offset)); //offset to desktop pidl Offset += 2; //Marshal.SizeOf(GetType(UInt16)) 'point to the next one for (i = 0; i <= bArrays.Length - 1; i++) { BW.Write(Convert.ToUInt32(Offset)); Offset += ((byte[])(bArrays[i])).Length; } //done with the array of offsets, write the parent pidl (0 0) = Desktop BW.Write(Convert.ToUInt16(Desktop)); //Write the pidl bytes byte[] b; foreach (byte[] tempLoopVar_b in bArrays) { b = tempLoopVar_b; BW.Write(b); } //done, returning the memorystream Debug.WriteLine("Done MakeShellIDArray"); return(returnValue); }
///<Summary> /// Shell Folders prefer their IDragData to contain this format which is /// NOT directly supported by .Net. The underlying structure is the CIDA structure /// which is basically VB and VB.Net Hostile. ///If "Make ShortCut(s) here" is the desired or /// POSSIBLE effect of the drag, then this format is REQUIRED -- otherwise the /// Folder will interpret the DragDropEffects.Link to be "Create Document Shortcut" /// which is NEVER the desired effect in this case /// The normal CIDA contains the Absolute PIDL of the source Folder and /// Relative PIDLs for each Item in the Drag. /// I cheat a bit an provide the Absolute PIDL of the Desktop (00, a short) /// and the Absolute PIDLs for the Items (all such Absolute PIDLS ar /// relative to the Desktop. ///</Summary> ///<Credit>http://www.dotnetmonster.com/Uwe/Forum.aspx/dotnet-interop/3482/Drag-and-Drop /// The overall concept and much code taken from the above reference /// Dave Anderson's response, translated from C# to VB.Net, was the basis /// of this routine /// An AHA momemnt and a ref to the above url came from ///http://www.Planet-Source-Code.com/vb/scripts/ShowCode.asp?txtCodeId=61324%26lngWId=1 /// ///</Credit> public static System.IO.MemoryStream MakeShellIDArray(ArrayList CSIList) { System.IO.MemoryStream returnValue; //ensure that we have an arraylist of only CShItems Type AllowedType = typeof(CShItem); object oCSI; foreach (object tempLoopVar_oCSI in CSIList) { oCSI = tempLoopVar_oCSI; if (! AllowedType.Equals(oCSI.GetType())) { return null; } } //ensure at least one item if (CSIList.Count < 1) { return null; } //bArrays is an Array of Byte() each containing the bytes of a PIDL object[] bArrays = new object[CSIList.Count]; CShItem CSI; int i = 0; foreach (CShItem tempLoopVar_CSI in CSIList) { CSI = tempLoopVar_CSI; bArrays[i] = new ExpTreeLib.CShItem.cPidl(CSI.PIDL).PidlBytes; i++; } returnValue = new System.IO.MemoryStream(); System.IO.BinaryWriter BW = new System.IO.BinaryWriter(returnValue); BW.Write(Convert.ToUInt32(CSIList.Count)); //we don't count the parent (Desktop) int Desktop = 0; //we only use the lowval 2 bytes (VB lacks meaninful uint) int Offset; //offset into Structure of a PIDL // Calculate and write the offset to each pidl (defined as an array of uint32) // The first pidl is 2 bytes long (0 0) and represents the desktop // The 2 in the statement below is for the offset to the // folder pidl and the count field in the CIDA structure Offset = Marshal.SizeOf(typeof(UInt32)) * (bArrays.Length + 2); BW.Write(Convert.ToUInt32(Offset)); //offset to desktop pidl Offset += 2; //Marshal.SizeOf(GetType(UInt16)) 'point to the next one for (i = 0; i <= bArrays.Length - 1; i++) { BW.Write(Convert.ToUInt32(Offset)); Offset += ((byte[]) (bArrays[i])).Length; } //done with the array of offsets, write the parent pidl (0 0) = Desktop BW.Write(Convert.ToUInt16(Desktop)); //Write the pidl bytes byte[] b; foreach (byte[] tempLoopVar_b in bArrays) { b = tempLoopVar_b; BW.Write(b); } //done, returning the memorystream Debug.WriteLine("Done MakeShellIDArray"); return returnValue; }