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

Revision 2805, 8.9 KB checked in by gtrant, 14 months ago (diff)

Update to 2013 and fixes in local compile

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Rev URL
Line 
1/*
2 * $Id$
3 * Copyright 2008-2013 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            /// <summary>
125            /// Retrieves the full path of a known folder identified by the folder's
126            /// KNOWNFOLDERID.
127            /// </summary>
128            /// <param name="guid">The KNOWNFOLDERID that identifies the folder.</param>
129            /// <returns>The DirectoryInfo for the given known folder path, or null if
130            /// an error occurred.</returns>
131            public static DirectoryInfo GetPath(Guid guid)
132            {
133                try
134                {
135                    IntPtr path = IntPtr.Zero;
136                    uint result = NativeMethods.SHGetKnownFolderPath(ref guid, 0, IntPtr.Zero,
137                        out path);
138
139                    if (result == 0)
140                    {
141                        string pathStr = Marshal.PtrToStringUni(path);
142                        Marshal.FreeCoTaskMem(path);
143
144                        return new DirectoryInfo(pathStr);
145                    }
146                    else
147                    {
148                        throw Marshal.GetExceptionForHR((int)result);
149                    }
150                }
151                catch (EntryPointNotFoundException)
152                {
153                    return null;
154                }
155                catch (FileNotFoundException)
156                {
157                    return null;
158                }
159            }
160        }
161    }
162
163    /// <summary>
164    /// Retrieves the path of a known folder as an ITEMIDLIST structure.
165    /// </summary>
166    public class ShellCIDA
167    {
168        /// <summary>
169        /// Parses the given buffer for CIDA elements
170        /// </summary>
171        /// <param name="buffer"></param>
172        public ShellCIDA(byte[] buffer)
173        {
174            int offset = 0;
175            cidl = BitConverter.ToUInt32(buffer, offset);
176            aoffset = new ShellItemIDList[cidl + 1];
177
178            for (int i = 0; i < aoffset.Length; ++i)
179            {
180                int pidlOffset = BitConverter.ToInt32(buffer, offset += sizeof(int));
181
182                //Read the size of the IDL
183                aoffset[i] = new ShellItemIDList(buffer.Skip(pidlOffset).ToArray());
184            }
185        }
186
187        /// <summary>
188        /// The number of PIDLs that are being transferred, not including the parent folder.
189        /// </summary>
190        public uint cidl
191        {
192            get;
193            private set;
194        }
195
196        /// <summary>
197        /// The first element of aoffset contains the fully-qualified PIDL of a parent folder.
198        /// If this PIDL is empty, the parent folder is the desktop. Each of the remaining
199        /// elements of the array contains an offset to one of the PIDLs to be transferred.
200        /// All of these PIDLs are relative to the PIDL of the parent folder.
201        /// </summary>
202        public ShellItemIDList[] aoffset
203        {
204            get;
205            private set;
206        }
207    }
208
209    /// <summary>
210    /// Contains a list of item identifiers.
211    /// </summary>
212    public class ShellItemIDList
213    {
214        public ShellItemIDList(byte[] buffer)
215        {
216            mkid = new ShellItemID(buffer);
217        }
218
219        public ShellItemIDList(IntPtr buffer)
220        {
221            mkid = new ShellItemID(buffer);
222        }
223
224        public ShellItemID mkid
225        {
226            get;
227            private set;
228        }
229
230        /// <summary>
231        /// The physical path to the object referenced by this IDL.
232        /// </summary>
233        /// <remarks>If this IDL references a virtual object, this will return
234        /// null.</remarks>
235        public string Path
236        {
237            get
238            {
239                IntPtr mkid = this.mkid.ToSHITEMID();
240                try
241                {
242                    StringBuilder result = new StringBuilder(NativeMethods.MaxPath);
243                    if (NativeMethods.SHGetPathFromIDList(mkid, result))
244                        return result.ToString();
245                }
246                finally
247                {
248                    Marshal.FreeHGlobal(mkid);
249                }
250
251                return null;
252            }
253        }
254
255        /// <summary>
256        /// The GUID of the virtual folder referenced by this IDL.
257        /// </summary>
258        /// <remarks>If this IDL references a physical object, this will return
259        /// <see cref="Guid.Empty"/></remarks>
260        public Guid Guid
261        {
262            get
263            {
264                Guid[] guids = new Guid[] {
265                    Shell.KnownFolderIDs.RecycleBin
266                };
267
268                foreach (Guid guid in guids)
269                {
270                    if (Shell.KnownFolderIDs.GetShellItemIdList(guid) == this)
271                        return guid;
272                }
273
274                return Guid.Empty;
275            }
276        }
277
278        public static bool operator==(ShellItemIDList lhs, ShellItemIDList rhs)
279        {
280            return lhs.mkid == rhs.mkid;
281        }
282
283        public static bool operator!=(ShellItemIDList lhs, ShellItemIDList rhs)
284        {
285            return lhs.mkid != rhs.mkid;
286        }
287
288        public override bool Equals(object obj)
289        {
290            if (obj is ShellItemIDList)
291                return this == (ShellItemIDList)obj;
292            return this.Equals(obj);
293        }
294
295        public override int GetHashCode()
296        {
297            return base.GetHashCode();
298        }
299    }
300
301    /// <summary>
302    /// Defines an item identifier. (native type: SHITEMID)
303    /// </summary>
304    public class ShellItemID
305    {
306        public ShellItemID(byte[] buffer)
307        {
308            short cb = BitConverter.ToInt16(buffer, 0);
309            abID = new byte[cb];
310            if (cb > 0)
311                Buffer.BlockCopy(buffer, sizeof(short), abID, 0, cb - sizeof(short));
312        }
313
314        public ShellItemID(IntPtr buffer)
315        {
316            short cb = Marshal.ReadInt16(buffer);
317            abID = new byte[cb];
318            if (cb > 0)
319                Marshal.Copy(new IntPtr(buffer.ToInt64() + sizeof(short)), abID, 0, cb - sizeof(short));
320        }
321
322        byte[] abID;
323
324        /// <summary>
325        /// Converts this ShellItemID to the native SHITEMID.
326        /// </summary>
327        /// <returns>A Pointer to an unmanaged block of memory which should be
328        /// freed by Marshal.FreeHGlobal upon completion.</returns>
329        internal IntPtr ToSHITEMID()
330        {
331            //Allocate the buffer
332            IntPtr result = Marshal.AllocHGlobal(abID.Length + (abID.Length == 0 ? 0 : sizeof(short)));
333
334            //Write the size of the identifier
335            Marshal.WriteInt16(result, (short)abID.Length);
336
337            //Then copy the block of memory
338            Marshal.Copy(abID, 0, new IntPtr(result.ToInt64() + 2), abID.Length);
339            return result;
340        }
341
342        public static bool operator==(ShellItemID lhs, ShellItemID rhs)
343        {
344            return lhs.abID.SequenceEqual(rhs.abID);
345        }
346
347        public static bool operator!=(ShellItemID lhs, ShellItemID rhs)
348        {
349            return !lhs.abID.SequenceEqual(rhs.abID);
350        }
351
352        public override bool Equals(object obj)
353        {
354            if (obj is ShellItemID)
355                return this == (ShellItemID)obj;
356            return this.Equals(obj);
357        }
358
359        public override int GetHashCode()
360        {
361            return base.GetHashCode();
362        }
363    }
364}
Note: See TracBrowser for help on using the repository browser.