Merge branch 'master' of https://code.grnet.gr/git/pithos-ms-client
[pithos-ms-client] / trunk / Pithos.Core / NativeMethods.cs
1 #region
2 /* -----------------------------------------------------------------------
3  * <copyright file="NativeMethods.cs" company="GRNet">
4  * 
5  * Copyright 2011-2012 GRNET S.A. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or
8  * without modification, are permitted provided that the following
9  * conditions are met:
10  *
11  *   1. Redistributions of source code must retain the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer.
14  *
15  *   2. Redistributions in binary form must reproduce the above
16  *      copyright notice, this list of conditions and the following
17  *      disclaimer in the documentation and/or other materials
18  *      provided with the distribution.
19  *
20  *
21  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
22  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
25  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * The views and conclusions contained in the software and
35  * documentation are those of the authors and should not be
36  * interpreted as representing official policies, either expressed
37  * or implied, of GRNET S.A.
38  * </copyright>
39  * -----------------------------------------------------------------------
40  */
41 #endregion
42 using System;
43 using System.Collections.Generic;
44 using System.IO;
45 using System.Linq;
46 using System.Runtime.InteropServices;
47 using System.Text;
48
49 namespace Pithos.Core
50 {
51     #region Enums & Structs
52
53     #region enum HChangeNotifyEventID
54     /// <summary>
55     /// Describes the event that has occurred. 
56     /// Typically, only one event is specified at a time. 
57     /// If more than one event is specified, the values contained 
58     /// in the <i>dwItem1</i> and <i>dwItem2</i> 
59     /// parameters must be the same, respectively, for all specified events. 
60     /// This parameter can be one or more of the following values. 
61     /// </summary>
62     /// <remarks>
63     /// <para><b>Windows NT/2000/XP:</b> <i>dwItem2</i> contains the index 
64     /// in the system image list that has changed. 
65     /// <i>dwItem1</i> is not used and should be <see langword="null"/>.</para>
66     /// <para><b>Windows 95/98:</b> <i>dwItem1</i> contains the index 
67     /// in the system image list that has changed. 
68     /// <i>dwItem2</i> is not used and should be <see langword="null"/>.</para>
69     /// </remarks>
70     [Flags]
71     public enum HChangeNotifyEventID
72     {
73         /// <summary>
74         /// All events have occurred. 
75         /// </summary>
76         SHCNE_ALLEVENTS = 0x7FFFFFFF,
77
78         /// <summary>
79         /// A file type association has changed. <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> 
80         /// must be specified in the <i>uFlags</i> parameter. 
81         /// <i>dwItem1</i> and <i>dwItem2</i> are not used and must be <see langword="null"/>. 
82         /// </summary>
83         SHCNE_ASSOCCHANGED = 0x08000000,
84
85         /// <summary>
86         /// The attributes of an item or folder have changed. 
87         /// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
88         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
89         /// <i>dwItem1</i> contains the item or folder that has changed. 
90         /// <i>dwItem2</i> is not used and should be <see langword="null"/>.
91         /// </summary>
92         SHCNE_ATTRIBUTES = 0x00000800,
93
94         /// <summary>
95         /// A nonfolder item has been created. 
96         /// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
97         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
98         /// <i>dwItem1</i> contains the item that was created. 
99         /// <i>dwItem2</i> is not used and should be <see langword="null"/>.
100         /// </summary>
101         SHCNE_CREATE = 0x00000002,
102
103         /// <summary>
104         /// A nonfolder item has been deleted. 
105         /// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
106         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
107         /// <i>dwItem1</i> contains the item that was deleted. 
108         /// <i>dwItem2</i> is not used and should be <see langword="null"/>. 
109         /// </summary>
110         SHCNE_DELETE = 0x00000004,
111
112         /// <summary>
113         /// A drive has been added. 
114         /// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
115         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
116         /// <i>dwItem1</i> contains the root of the drive that was added. 
117         /// <i>dwItem2</i> is not used and should be <see langword="null"/>. 
118         /// </summary>
119         SHCNE_DRIVEADD = 0x00000100,
120
121         /// <summary>
122         /// A drive has been added and the Shell should create a new window for the drive. 
123         /// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
124         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
125         /// <i>dwItem1</i> contains the root of the drive that was added. 
126         /// <i>dwItem2</i> is not used and should be <see langword="null"/>. 
127         /// </summary>
128         SHCNE_DRIVEADDGUI = 0x00010000,
129
130         /// <summary>
131         /// A drive has been removed. <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
132         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
133         /// <i>dwItem1</i> contains the root of the drive that was removed.
134         /// <i>dwItem2</i> is not used and should be <see langword="null"/>. 
135         /// </summary>
136         SHCNE_DRIVEREMOVED = 0x00000080,
137
138         /// <summary>
139         /// Not currently used. 
140         /// </summary>
141         SHCNE_EXTENDED_EVENT = 0x04000000,
142
143         /// <summary>
144         /// The amount of free space on a drive has changed. 
145         /// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
146         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
147         /// <i>dwItem1</i> contains the root of the drive on which the free space changed.
148         /// <i>dwItem2</i> is not used and should be <see langword="null"/>. 
149         /// </summary>
150         SHCNE_FREESPACE = 0x00040000,
151
152         /// <summary>
153         /// Storage media has been inserted into a drive. 
154         /// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
155         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
156         /// <i>dwItem1</i> contains the root of the drive that contains the new media. 
157         /// <i>dwItem2</i> is not used and should be <see langword="null"/>. 
158         /// </summary>
159         SHCNE_MEDIAINSERTED = 0x00000020,
160
161         /// <summary>
162         /// Storage media has been removed from a drive. 
163         /// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
164         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
165         /// <i>dwItem1</i> contains the root of the drive from which the media was removed. 
166         /// <i>dwItem2</i> is not used and should be <see langword="null"/>. 
167         /// </summary>
168         SHCNE_MEDIAREMOVED = 0x00000040,
169
170         /// <summary>
171         /// A folder has been created. <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> 
172         /// or <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
173         /// <i>dwItem1</i> contains the folder that was created. 
174         /// <i>dwItem2</i> is not used and should be <see langword="null"/>. 
175         /// </summary>
176         SHCNE_MKDIR = 0x00000008,
177
178         /// <summary>
179         /// A folder on the local computer is being shared via the network. 
180         /// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
181         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
182         /// <i>dwItem1</i> contains the folder that is being shared. 
183         /// <i>dwItem2</i> is not used and should be <see langword="null"/>. 
184         /// </summary>
185         SHCNE_NETSHARE = 0x00000200,
186
187         /// <summary>
188         /// A folder on the local computer is no longer being shared via the network. 
189         /// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
190         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
191         /// <i>dwItem1</i> contains the folder that is no longer being shared. 
192         /// <i>dwItem2</i> is not used and should be <see langword="null"/>. 
193         /// </summary>
194         SHCNE_NETUNSHARE = 0x00000400,
195
196         /// <summary>
197         /// The name of a folder has changed. 
198         /// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
199         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
200         /// <i>dwItem1</i> contains the previous pointer to an item identifier list (PIDL) or name of the folder. 
201         /// <i>dwItem2</i> contains the new PIDL or name of the folder. 
202         /// </summary>
203         SHCNE_RENAMEFOLDER = 0x00020000,
204
205         /// <summary>
206         /// The name of a nonfolder item has changed. 
207         /// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
208         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
209         /// <i>dwItem1</i> contains the previous PIDL or name of the item. 
210         /// <i>dwItem2</i> contains the new PIDL or name of the item. 
211         /// </summary>
212         SHCNE_RENAMEITEM = 0x00000001,
213
214         /// <summary>
215         /// A folder has been removed. 
216         /// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
217         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
218         /// <i>dwItem1</i> contains the folder that was removed. 
219         /// <i>dwItem2</i> is not used and should be <see langword="null"/>. 
220         /// </summary>
221         SHCNE_RMDIR = 0x00000010,
222
223         /// <summary>
224         /// The computer has disconnected from a server. 
225         /// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
226         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
227         /// <i>dwItem1</i> contains the server from which the computer was disconnected. 
228         /// <i>dwItem2</i> is not used and should be <see langword="null"/>. 
229         /// </summary>
230         SHCNE_SERVERDISCONNECT = 0x00004000,
231
232         /// <summary>
233         /// The contents of an existing folder have changed, 
234         /// but the folder still exists and has not been renamed. 
235         /// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or 
236         /// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. 
237         /// <i>dwItem1</i> contains the folder that has changed. 
238         /// <i>dwItem2</i> is not used and should be <see langword="null"/>. 
239         /// If a folder has been created, deleted, or renamed, use SHCNE_MKDIR, SHCNE_RMDIR, or 
240         /// SHCNE_RENAMEFOLDER, respectively, instead. 
241         /// </summary>
242         SHCNE_UPDATEDIR = 0x00001000,
243
244         SHCNE_UPDATEITEM = 0x00002000,
245
246         /// <summary>
247         /// An image in the system image list has changed. 
248         /// <see cref="HChangeNotifyFlags.SHCNF_DWORD"/> must be specified in <i>uFlags</i>. 
249         /// </summary>
250         SHCNE_UPDATEIMAGE = 0x00008000,
251
252     }
253     #endregion // enum HChangeNotifyEventID
254
255     #region public enum HChangeNotifyFlags
256     /// <summary>
257     /// Flags that indicate the meaning of the <i>dwItem1</i> and <i>dwItem2</i> parameters. 
258     /// The uFlags parameter must be one of the following values.
259     /// </summary>
260     [Flags]
261     public enum HChangeNotifyFlags
262     {
263         /// <summary>
264         /// The <i>dwItem1</i> and <i>dwItem2</i> parameters are DWORD values. 
265         /// </summary>
266         SHCNF_DWORD = 0x0003,
267         /// <summary>
268         /// <i>dwItem1</i> and <i>dwItem2</i> are the addresses of ITEMIDLIST structures that 
269         /// represent the item(s) affected by the change. 
270         /// Each ITEMIDLIST must be relative to the desktop folder. 
271         /// </summary>
272         SHCNF_IDLIST = 0x0000,
273         /// <summary>
274         /// <i>dwItem1</i> and <i>dwItem2</i> are the addresses of null-terminated strings of 
275         /// maximum length MAX_PATH that contain the full path names 
276         /// of the items affected by the change. 
277         /// </summary>
278         SHCNF_PATHA = 0x0001,
279         /// <summary>
280         /// <i>dwItem1</i> and <i>dwItem2</i> are the addresses of null-terminated strings of 
281         /// maximum length MAX_PATH that contain the full path names 
282         /// of the items affected by the change. 
283         /// </summary>
284         SHCNF_PATHW = 0x0005,
285         /// <summary>
286         /// <i>dwItem1</i> and <i>dwItem2</i> are the addresses of null-terminated strings that 
287         /// represent the friendly names of the printer(s) affected by the change. 
288         /// </summary>
289         SHCNF_PRINTERA = 0x0002,
290         /// <summary>
291         /// <i>dwItem1</i> and <i>dwItem2</i> are the addresses of null-terminated strings that 
292         /// represent the friendly names of the printer(s) affected by the change. 
293         /// </summary>
294         SHCNF_PRINTERW = 0x0006,
295         /// <summary>
296         /// The function should not return until the notification 
297         /// has been delivered to all affected components. 
298         /// As this flag modifies other data-type flags, it cannot by used by itself.
299         /// </summary>
300         SHCNF_FLUSH = 0x1000,
301         /// <summary>
302         /// The function should begin delivering notifications to all affected components 
303         /// but should return as soon as the notification process has begun. 
304         /// As this flag modifies other data-type flags, it cannot by used by itself.
305         /// </summary>
306         SHCNF_FLUSHNOWAIT = 0x2000
307     }
308     #endregion // enum HChangeNotifyFlags
309
310
311     #endregion
312
313     public static class NativeMethods
314     {
315         [DllImport("shell32.dll")]
316         public static extern void SHChangeNotify(HChangeNotifyEventID wEventId,
317                                            HChangeNotifyFlags uFlags,
318                                            IntPtr dwItem1,
319                                            IntPtr dwItem2);
320
321         public static void RaiseChangeNotification(string path)
322         {
323             if (String.IsNullOrWhiteSpace(path))
324                 throw new ArgumentNullException("path", "The path parameter must not be emtpy");
325
326             if (!Directory.Exists(path) && !File.Exists(path))
327                 return;
328
329
330             IntPtr pathPointer = Marshal.StringToCoTaskMemAuto(path);
331
332             try
333             {
334                 NativeMethods.SHChangeNotify(HChangeNotifyEventID.SHCNE_UPDATEITEM,
335                                              HChangeNotifyFlags.SHCNF_PATHW | HChangeNotifyFlags.SHCNF_FLUSHNOWAIT,
336                                              pathPointer, IntPtr.Zero);
337             }
338             finally
339             {
340                 Marshal.FreeHGlobal(pathPointer);
341             }
342
343         }
344     }
345
346
347 }