source: trunk/eraser/Eraser.Util/Shell.cs @ 2516

Revision 2516, 8.0 KB checked in by lowjoel, 3 years ago (diff)

Update copyrights to this year.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Rev URL
Line 
1/*
2 * $Id$
3 * Copyright 2008-2012 The Eraser Project
4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By:
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26
27using System.Runtime.InteropServices;
28using Microsoft.Win32;
29using System.IO;
30
31namespace Eraser.Util
32{
33    public static class Shell
34    {
35        /// <summary>
36        /// Gets or sets whether low disk space notifications are enabled for the
37        /// current user.
38        /// </summary>
39        public static bool LowDiskSpaceNotificationsEnabled
40        {
41            get
42            {
43                using (RegistryKey key = Registry.CurrentUser.OpenSubKey(
44                    "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"))
45                {
46                    if (key == null)
47                        return true;
48                    return !Convert.ToBoolean(key.GetValue("NoLowDiskSpaceChecks", false));
49                }
50            }
51            set
52            {
53                RegistryKey key = null;
54                try
55                {
56                    key = Registry.CurrentUser.OpenSubKey(
57                        "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", true);
58                    if (key == null)
59                        key = Registry.CurrentUser.CreateSubKey(
60                            "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer");
61                    key.SetValue("NoLowDiskSpaceChecks", !value);
62                }
63                finally
64                {
65                    if (key != null)
66                        key.Close();
67                }
68            }
69        }
70
71        /// <summary>
72        /// Parses the provided command line into its constituent arguments.
73        /// </summary>
74        /// <param name="commandLine">The command line to parse.</param>
75        /// <returns>The arguments specified in the command line</returns>
76        public static string[] ParseCommandLine(string commandLine)
77        {
78            int argc = 0;
79            IntPtr argv = NativeMethods.CommandLineToArgvW(commandLine, out argc);
80            string[] result = new string[argc];
81
82            //Get the pointers to the arguments, then read the string.
83            for (int i = 0; i < argc; ++i)
84                result[i] = Marshal.PtrToStringUni(Marshal.ReadIntPtr(argv, i * IntPtr.Size));
85
86            //Free the memory
87            NativeMethods.LocalFree(argv);
88
89            return result;
90        }
91
92        /// <summary>
93        /// A List of known folder IDs in the shell namespace.
94        /// </summary>
95        public static class KnownFolderIDs
96        {
97            /// <summary>
98            /// The Known Folder ID of the Recycle Bin
99            /// </summary>
100            public static readonly Guid RecycleBin = 
101                new Guid(0xB7534046, 0x3ECB, 0x4C18, 0xBE, 0x4E, 0x64, 0xCD, 0x4C, 0xB7, 0xD6, 0xAC);
102
103            /// <summary>
104            /// Gets the PIDL for the given Known folder ID.
105            /// </summary>
106            /// <param name="folderId">The known folder ID to query.</param>
107            /// <returns>The PIDL for the given folder.</returns>
108            public static ShellItemIDList GetShellItemIdList(Guid folderId)
109            {
110                Guid guid = folderId;
111                IntPtr pidl = IntPtr.Zero;
112                NativeMethods.SHGetKnownFolderIDList(ref guid, 0, IntPtr.Zero, out pidl);
113
114                try
115                {
116                    return new ShellItemIDList(pidl);
117                }
118                finally
119                {
120                    NativeMethods.ILFree(pidl);
121                }
122            }
123        }
124    }
125
126    /// <summary>
127    /// Retrieves the path of a known folder as an ITEMIDLIST structure.
128    /// </summary>
129    public class ShellCIDA
130    {
131        /// <summary>
132        /// Parses the given buffer for CIDA elements
133        /// </summary>
134        /// <param name="buffer"></param>
135        public ShellCIDA(byte[] buffer)
136        {
137            int offset = 0;
138            cidl = BitConverter.ToUInt32(buffer, offset);
139            aoffset = new ShellItemIDList[cidl + 1];
140
141            for (int i = 0; i < aoffset.Length; ++i)
142            {
143                int pidlOffset = BitConverter.ToInt32(buffer, offset += sizeof(int));
144
145                //Read the size of the IDL
146                aoffset[i] = new ShellItemIDList(buffer.Skip(pidlOffset).ToArray());
147            }
148        }
149
150        /// <summary>
151        /// The number of PIDLs that are being transferred, not including the parent folder.
152        /// </summary>
153        public uint cidl
154        {
155            get;
156            private set;
157        }
158
159        /// <summary>
160        /// The first element of aoffset contains the fully-qualified PIDL of a parent folder.
161        /// If this PIDL is empty, the parent folder is the desktop. Each of the remaining
162        /// elements of the array contains an offset to one of the PIDLs to be transferred.
163        /// All of these PIDLs are relative to the PIDL of the parent folder.
164        /// </summary>
165        public ShellItemIDList[] aoffset
166        {
167            get;
168            private set;
169        }
170    }
171
172    /// <summary>
173    /// Contains a list of item identifiers.
174    /// </summary>
175    public class ShellItemIDList
176    {
177        public ShellItemIDList(byte[] buffer)
178        {
179            mkid = new ShellItemID(buffer);
180        }
181
182        public ShellItemIDList(IntPtr buffer)
183        {
184            mkid = new ShellItemID(buffer);
185        }
186
187        public ShellItemID mkid
188        {
189            get;
190            private set;
191        }
192
193        /// <summary>
194        /// The physical path to the object referenced by this IDL.
195        /// </summary>
196        /// <remarks>If this IDL references a virtual object, this will return
197        /// null.</remarks>
198        public string Path
199        {
200            get
201            {
202                IntPtr mkid = this.mkid.ToSHITEMID();
203                try
204                {
205                    StringBuilder result = new StringBuilder(NativeMethods.MaxPath);
206                    if (NativeMethods.SHGetPathFromIDList(mkid, result))
207                        return result.ToString();
208                }
209                finally
210                {
211                    Marshal.FreeHGlobal(mkid);
212                }
213
214                return null;
215            }
216        }
217
218        /// <summary>
219        /// The GUID of the virtual folder referenced by this IDL.
220        /// </summary>
221        /// <remarks>If this IDL references a physical object, this will return
222        /// <see cref="Guid.Empty"/></remarks>
223        public Guid Guid
224        {
225            get
226            {
227                Guid[] guids = new Guid[] {
228                    Shell.KnownFolderIDs.RecycleBin
229                };
230
231                foreach (Guid guid in guids)
232                {
233                    if (Shell.KnownFolderIDs.GetShellItemIdList(guid) == this)
234                        return guid;
235                }
236
237                return Guid.Empty;
238            }
239        }
240
241        public static bool operator==(ShellItemIDList lhs, ShellItemIDList rhs)
242        {
243            return lhs.mkid == rhs.mkid;
244        }
245
246        public static bool operator!=(ShellItemIDList lhs, ShellItemIDList rhs)
247        {
248            return lhs.mkid != rhs.mkid;
249        }
250
251        public override bool Equals(object obj)
252        {
253            if (obj is ShellItemIDList)
254                return this == (ShellItemIDList)obj;
255            return this.Equals(obj);
256        }
257
258        public override int GetHashCode()
259        {
260            return base.GetHashCode();
261        }
262    }
263
264    /// <summary>
265    /// Defines an item identifier. (native type: SHITEMID)
266    /// </summary>
267    public class ShellItemID
268    {
269        public ShellItemID(byte[] buffer)
270        {
271            short cb = BitConverter.ToInt16(buffer, 0);
272            abID = new byte[cb];
273            if (cb > 0)
274                Buffer.BlockCopy(buffer, sizeof(short), abID, 0, cb - sizeof(short));
275        }
276
277        public ShellItemID(IntPtr buffer)
278        {
279            short cb = Marshal.ReadInt16(buffer);
280            abID = new byte[cb];
281            if (cb > 0)
282                Marshal.Copy(new IntPtr(buffer.ToInt64() + sizeof(short)), abID, 0, cb - sizeof(short));
283        }
284
285        byte[] abID;
286
287        /// <summary>
288        /// Converts this ShellItemID to the native SHITEMID.
289        /// </summary>
290        /// <returns>A Pointer to an unmanaged block of memory which should be
291        /// freed by Marshal.FreeHGlobal upon completion.</returns>
292        internal IntPtr ToSHITEMID()
293        {
294            //Allocate the buffer
295            IntPtr result = Marshal.AllocHGlobal(abID.Length + (abID.Length == 0 ? 0 : sizeof(short)));
296
297            //Write the size of the identifier
298            Marshal.WriteInt16(result, (short)abID.Length);
299
300            //Then copy the block of memory
301            Marshal.Copy(abID, 0, new IntPtr(result.ToInt64() + 2), abID.Length);
302            return result;
303        }
304
305        public static bool operator==(ShellItemID lhs, ShellItemID rhs)
306        {
307            return lhs.abID.SequenceEqual(rhs.abID);
308        }
309
310        public static bool operator!=(ShellItemID lhs, ShellItemID rhs)
311        {
312            return !lhs.abID.SequenceEqual(rhs.abID);
313        }
314
315        public override bool Equals(object obj)
316        {
317            if (obj is ShellItemID)
318                return this == (ShellItemID)obj;
319            return this.Equals(obj);
320        }
321
322        public override int GetHashCode()
323        {
324            return base.GetHashCode();
325        }
326    }
327}
Note: See TracBrowser for help on using the repository browser.