root / trunk / Pithos.ShellExtensions / ShellExtLib.cs @ bb679ec8
History | View | Annotate | Download (33.4 kB)
1 |
#region |
---|---|
2 |
/* ----------------------------------------------------------------------- |
3 |
* <copyright file="ShellExtLib.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.Diagnostics; |
44 |
using System.Text; |
45 |
using Microsoft.Win32; |
46 |
using System.Runtime.InteropServices; |
47 |
using System.Runtime.InteropServices.ComTypes; |
48 |
|
49 |
|
50 |
namespace Pithos.ShellExtensions |
51 |
{ |
52 |
#region Shell Interfaces |
53 |
[Flags] |
54 |
public enum ISIOI |
55 |
{ |
56 |
ISIOI_ICONFILE = 1, |
57 |
ISIOI_ICONINDEX = 2 |
58 |
} |
59 |
|
60 |
[ComVisible(false)] |
61 |
[ComImport] |
62 |
[Guid("0C6C4200-C589-11D0-999A-00C04FD655E1")] |
63 |
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] |
64 |
public interface IShellIconOverlayIdentifier |
65 |
{ |
66 |
|
67 |
[PreserveSig] |
68 |
int IsMemberOf( |
69 |
[MarshalAs(UnmanagedType.LPWStr)] string path, |
70 |
|
71 |
uint attributes); |
72 |
|
73 |
[PreserveSig] |
74 |
int GetOverlayInfo( |
75 |
IntPtr iconFileBuffer, |
76 |
int iconFileBufferSize, |
77 |
out int iconIndex, |
78 |
out uint flags); |
79 |
|
80 |
[PreserveSig] |
81 |
int GetPriority( |
82 |
out int priority); |
83 |
|
84 |
} |
85 |
|
86 |
|
87 |
|
88 |
[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] |
89 |
[Guid("000214e8-0000-0000-c000-000000000046")] |
90 |
internal interface IShellExtInit |
91 |
{ |
92 |
void Initialize( |
93 |
IntPtr /*LPCITEMIDLIST*/ pidlFolder, |
94 |
IntPtr /*LPDATAOBJECT*/ pDataObj, |
95 |
IntPtr /*HKEY*/ hKeyProgID); |
96 |
} |
97 |
|
98 |
|
99 |
[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] |
100 |
[Guid("000214e4-0000-0000-c000-000000000046")] |
101 |
internal interface IContextMenu |
102 |
{ |
103 |
[PreserveSig] |
104 |
int QueryContextMenu( |
105 |
IntPtr /*HMENU*/ hMenu, |
106 |
uint iMenu, |
107 |
uint idCmdFirst, |
108 |
uint idCmdLast, |
109 |
uint uFlags); |
110 |
|
111 |
void InvokeCommand(IntPtr pici); |
112 |
|
113 |
void GetCommandString( |
114 |
UIntPtr idCmd, |
115 |
uint uFlags, |
116 |
IntPtr pReserved, |
117 |
StringBuilder pszName, |
118 |
uint cchMax); |
119 |
} |
120 |
|
121 |
#endregion |
122 |
|
123 |
|
124 |
#region Shell Registration |
125 |
|
126 |
internal class ShellExtReg |
127 |
{ |
128 |
private const string _approvedKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved"; |
129 |
|
130 |
public static void RegisterIconOverlayIdentifier(Guid clsid, |
131 |
string friendlyName) |
132 |
{ |
133 |
if (clsid == Guid.Empty) |
134 |
{ |
135 |
throw new ArgumentException("clsid must not be empty"); |
136 |
} |
137 |
if (string.IsNullOrEmpty(friendlyName)) |
138 |
{ |
139 |
throw new ArgumentException("friendlyName must not be null or empty"); |
140 |
} |
141 |
|
142 |
// Create the key HKLM\SOFTWARE\TortoiseOverlays\<IconName>\Pithos={<CLSID>}. |
143 |
string keyName = string.Format(@"SOFTWARE\TortoiseOverlays\{0}", |
144 |
friendlyName); |
145 |
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(keyName,true)) |
146 |
{ |
147 |
// Set the default value of the key. |
148 |
if (key != null)//&& !string.IsNullOrEmpty(clsid.ToString("B"))) |
149 |
{ |
150 |
key.SetValue("Pithos", clsid.ToString("B"),RegistryValueKind.String); |
151 |
} |
152 |
} |
153 |
} |
154 |
|
155 |
internal static void UnregisterIconOverlayIdentifier(Guid clsid, |
156 |
string friendlyName) |
157 |
{ |
158 |
if (clsid == null) |
159 |
{ |
160 |
throw new ArgumentException("clsid must not be null"); |
161 |
} |
162 |
if (string.IsNullOrEmpty(friendlyName)) |
163 |
{ |
164 |
throw new ArgumentException("friendlyName must not be null or empty"); |
165 |
} |
166 |
|
167 |
|
168 |
string keyName = string.Format(@"SOFTWARE\TortoiseOverlays\{0}", |
169 |
friendlyName); |
170 |
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(keyName, true)) |
171 |
{ |
172 |
// Set the default value of the key. |
173 |
if (key != null)//&& !string.IsNullOrEmpty(clsid.ToString("B"))) |
174 |
{ |
175 |
key.DeleteValue("Pithos"); |
176 |
} |
177 |
} |
178 |
} |
179 |
|
180 |
|
181 |
/// <summary> |
182 |
/// Register the context menu handler. |
183 |
/// </summary> |
184 |
/// <param name="clsid">The CLSID of the component.</param> |
185 |
/// <param name="fileType"> |
186 |
/// The file type that the context menu handler is associated with. For |
187 |
/// example, '*' means all file types; '.txt' means all .txt files. The |
188 |
/// parameter must not be NULL or an empty string. |
189 |
/// </param> |
190 |
/// <param name="friendlyName">The friendly name of the component.</param> |
191 |
public static void RegisterShellExtContextMenuHandler(Guid clsid, |
192 |
string fileType, string friendlyName) |
193 |
{ |
194 |
if (clsid == Guid.Empty) |
195 |
{ |
196 |
throw new ArgumentException("clsid must not be empty"); |
197 |
} |
198 |
if (string.IsNullOrEmpty(fileType)) |
199 |
{ |
200 |
throw new ArgumentException("fileType must not be null or empty"); |
201 |
} |
202 |
|
203 |
// If fileType starts with '.', try to read the default value of the |
204 |
// HKCR\<File Type> key which contains the ProgID to which the file type |
205 |
// is linked. |
206 |
if (fileType.StartsWith(".")) |
207 |
{ |
208 |
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(fileType)) |
209 |
{ |
210 |
if (key != null) |
211 |
{ |
212 |
// If the key exists and its default value is not empty, use |
213 |
// the ProgID as the file type. |
214 |
string defaultVal = key.GetValue(null) as string; |
215 |
if (!string.IsNullOrEmpty(defaultVal)) |
216 |
{ |
217 |
fileType = defaultVal; |
218 |
} |
219 |
} |
220 |
} |
221 |
} |
222 |
|
223 |
// Create the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}. |
224 |
string keyName = string.Format(@"{0}\shellex\ContextMenuHandlers\{1}", |
225 |
fileType, friendlyName); |
226 |
using (RegistryKey key = Registry.ClassesRoot.CreateSubKey(keyName)) |
227 |
{ |
228 |
// Set the default value of the key. |
229 |
if (key != null)//&& !string.IsNullOrEmpty(clsid.ToString("B"))) |
230 |
{ |
231 |
key.SetValue(null, clsid.ToString("B")); |
232 |
} |
233 |
} |
234 |
} |
235 |
|
236 |
/// <summary> |
237 |
/// Unregister the context menu handler. |
238 |
/// </summary> |
239 |
/// <param name="clsid">The CLSID of the component.</param> |
240 |
/// <param name="fileType"> |
241 |
/// The file type that the context menu handler is associated with. For |
242 |
/// example, '*' means all file types; '.txt' means all .txt files. The |
243 |
/// parameter must not be NULL or an empty string. |
244 |
/// </param> |
245 |
public static void UnregisterShellExtContextMenuHandler(Guid clsid, |
246 |
string fileType, string friendlyName) |
247 |
{ |
248 |
if (clsid == null) |
249 |
{ |
250 |
throw new ArgumentException("clsid must not be null"); |
251 |
} |
252 |
if (string.IsNullOrEmpty(fileType)) |
253 |
{ |
254 |
throw new ArgumentException("fileType must not be null or empty"); |
255 |
} |
256 |
|
257 |
// If fileType starts with '.', try to read the default value of the |
258 |
// HKCR\<File Type> key which contains the ProgID to which the file type |
259 |
// is linked. |
260 |
if (fileType.StartsWith(".")) |
261 |
{ |
262 |
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(fileType)) |
263 |
{ |
264 |
if (key != null) |
265 |
{ |
266 |
// If the key exists and its default value is not empty, use |
267 |
// the ProgID as the file type. |
268 |
string defaultVal = key.GetValue(null) as string; |
269 |
if (!string.IsNullOrEmpty(defaultVal)) |
270 |
{ |
271 |
fileType = defaultVal; |
272 |
} |
273 |
} |
274 |
} |
275 |
} |
276 |
|
277 |
// Remove the key HKCR\<File Type>\shellex\ContextMenuHandlers\{<CLSID>}. |
278 |
string keyName = string.Format(@"{0}\shellex\ContextMenuHandlers\{1}", |
279 |
fileType, friendlyName); |
280 |
Registry.ClassesRoot.DeleteSubKeyTree(keyName, false); |
281 |
} |
282 |
|
283 |
public static void MarkApproved(Guid guid, string friendlyName) |
284 |
{ |
285 |
Debug.WriteLine(String.Format("Marking approved {0} {1}", guid, friendlyName), LogCategories.Shell); |
286 |
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(_approvedKey)) |
287 |
{ |
288 |
// Set the default value of the key. |
289 |
if (key != null)//&& !string.IsNullOrEmpty(clsid.ToString("B"))) |
290 |
{ |
291 |
key.SetValue(guid.ToString("B"), friendlyName, RegistryValueKind.String); |
292 |
} |
293 |
else |
294 |
{ |
295 |
Debug.WriteLine("Error - failed to open key " + _approvedKey,LogCategories.Shell); |
296 |
} |
297 |
} |
298 |
} |
299 |
|
300 |
public static void RemoveApproved(Guid guid) |
301 |
{ |
302 |
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(_approvedKey)) |
303 |
{ |
304 |
// Set the default value of the key. |
305 |
if (key != null)//&& !string.IsNullOrEmpty(clsid.ToString("B"))) |
306 |
{ |
307 |
key.DeleteValue(guid.ToString("B"), false); |
308 |
} |
309 |
else |
310 |
{ |
311 |
Debug.WriteLine("Error - failed to open key " + _approvedKey, LogCategories.Shell); |
312 |
} |
313 |
} |
314 |
} |
315 |
} |
316 |
|
317 |
#endregion |
318 |
|
319 |
|
320 |
#region Enums & Structs |
321 |
|
322 |
#region enum HChangeNotifyEventID |
323 |
/// <summary> |
324 |
/// Describes the event that has occurred. |
325 |
/// Typically, only one event is specified at a time. |
326 |
/// If more than one event is specified, the values contained |
327 |
/// in the <i>dwItem1</i> and <i>dwItem2</i> |
328 |
/// parameters must be the same, respectively, for all specified events. |
329 |
/// This parameter can be one or more of the following values. |
330 |
/// </summary> |
331 |
/// <remarks> |
332 |
/// <para><b>Windows NT/2000/XP:</b> <i>dwItem2</i> contains the index |
333 |
/// in the system image list that has changed. |
334 |
/// <i>dwItem1</i> is not used and should be <see langword="null"/>.</para> |
335 |
/// <para><b>Windows 95/98:</b> <i>dwItem1</i> contains the index |
336 |
/// in the system image list that has changed. |
337 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>.</para> |
338 |
/// </remarks> |
339 |
[Flags] |
340 |
enum HChangeNotifyEventID |
341 |
{ |
342 |
/// <summary> |
343 |
/// All events have occurred. |
344 |
/// </summary> |
345 |
SHCNE_ALLEVENTS = 0x7FFFFFFF, |
346 |
|
347 |
/// <summary> |
348 |
/// A file type association has changed. <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> |
349 |
/// must be specified in the <i>uFlags</i> parameter. |
350 |
/// <i>dwItem1</i> and <i>dwItem2</i> are not used and must be <see langword="null"/>. |
351 |
/// </summary> |
352 |
SHCNE_ASSOCCHANGED = 0x08000000, |
353 |
|
354 |
/// <summary> |
355 |
/// The attributes of an item or folder have changed. |
356 |
/// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
357 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
358 |
/// <i>dwItem1</i> contains the item or folder that has changed. |
359 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>. |
360 |
/// </summary> |
361 |
SHCNE_ATTRIBUTES = 0x00000800, |
362 |
|
363 |
/// <summary> |
364 |
/// A nonfolder item has been created. |
365 |
/// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
366 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
367 |
/// <i>dwItem1</i> contains the item that was created. |
368 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>. |
369 |
/// </summary> |
370 |
SHCNE_CREATE = 0x00000002, |
371 |
|
372 |
/// <summary> |
373 |
/// A nonfolder item has been deleted. |
374 |
/// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
375 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
376 |
/// <i>dwItem1</i> contains the item that was deleted. |
377 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>. |
378 |
/// </summary> |
379 |
SHCNE_DELETE = 0x00000004, |
380 |
|
381 |
/// <summary> |
382 |
/// A drive has been added. |
383 |
/// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
384 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
385 |
/// <i>dwItem1</i> contains the root of the drive that was added. |
386 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>. |
387 |
/// </summary> |
388 |
SHCNE_DRIVEADD = 0x00000100, |
389 |
|
390 |
/// <summary> |
391 |
/// A drive has been added and the Shell should create a new window for the drive. |
392 |
/// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
393 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
394 |
/// <i>dwItem1</i> contains the root of the drive that was added. |
395 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>. |
396 |
/// </summary> |
397 |
SHCNE_DRIVEADDGUI = 0x00010000, |
398 |
|
399 |
/// <summary> |
400 |
/// A drive has been removed. <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
401 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
402 |
/// <i>dwItem1</i> contains the root of the drive that was removed. |
403 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>. |
404 |
/// </summary> |
405 |
SHCNE_DRIVEREMOVED = 0x00000080, |
406 |
|
407 |
/// <summary> |
408 |
/// Not currently used. |
409 |
/// </summary> |
410 |
SHCNE_EXTENDED_EVENT = 0x04000000, |
411 |
|
412 |
/// <summary> |
413 |
/// The amount of free space on a drive has changed. |
414 |
/// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
415 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
416 |
/// <i>dwItem1</i> contains the root of the drive on which the free space changed. |
417 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>. |
418 |
/// </summary> |
419 |
SHCNE_FREESPACE = 0x00040000, |
420 |
|
421 |
/// <summary> |
422 |
/// Storage media has been inserted into a drive. |
423 |
/// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
424 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
425 |
/// <i>dwItem1</i> contains the root of the drive that contains the new media. |
426 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>. |
427 |
/// </summary> |
428 |
SHCNE_MEDIAINSERTED = 0x00000020, |
429 |
|
430 |
/// <summary> |
431 |
/// Storage media has been removed from a drive. |
432 |
/// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
433 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
434 |
/// <i>dwItem1</i> contains the root of the drive from which the media was removed. |
435 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>. |
436 |
/// </summary> |
437 |
SHCNE_MEDIAREMOVED = 0x00000040, |
438 |
|
439 |
/// <summary> |
440 |
/// A folder has been created. <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> |
441 |
/// or <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
442 |
/// <i>dwItem1</i> contains the folder that was created. |
443 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>. |
444 |
/// </summary> |
445 |
SHCNE_MKDIR = 0x00000008, |
446 |
|
447 |
/// <summary> |
448 |
/// A folder on the local computer is being shared via the network. |
449 |
/// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
450 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
451 |
/// <i>dwItem1</i> contains the folder that is being shared. |
452 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>. |
453 |
/// </summary> |
454 |
SHCNE_NETSHARE = 0x00000200, |
455 |
|
456 |
/// <summary> |
457 |
/// A folder on the local computer is no longer being shared via the network. |
458 |
/// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
459 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
460 |
/// <i>dwItem1</i> contains the folder that is no longer being shared. |
461 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>. |
462 |
/// </summary> |
463 |
SHCNE_NETUNSHARE = 0x00000400, |
464 |
|
465 |
/// <summary> |
466 |
/// The name of a folder has changed. |
467 |
/// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
468 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
469 |
/// <i>dwItem1</i> contains the previous pointer to an item identifier list (PIDL) or name of the folder. |
470 |
/// <i>dwItem2</i> contains the new PIDL or name of the folder. |
471 |
/// </summary> |
472 |
SHCNE_RENAMEFOLDER = 0x00020000, |
473 |
|
474 |
/// <summary> |
475 |
/// The name of a nonfolder item has changed. |
476 |
/// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
477 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
478 |
/// <i>dwItem1</i> contains the previous PIDL or name of the item. |
479 |
/// <i>dwItem2</i> contains the new PIDL or name of the item. |
480 |
/// </summary> |
481 |
SHCNE_RENAMEITEM = 0x00000001, |
482 |
|
483 |
/// <summary> |
484 |
/// A folder has been removed. |
485 |
/// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
486 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
487 |
/// <i>dwItem1</i> contains the folder that was removed. |
488 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>. |
489 |
/// </summary> |
490 |
SHCNE_RMDIR = 0x00000010, |
491 |
|
492 |
/// <summary> |
493 |
/// The computer has disconnected from a server. |
494 |
/// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
495 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
496 |
/// <i>dwItem1</i> contains the server from which the computer was disconnected. |
497 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>. |
498 |
/// </summary> |
499 |
SHCNE_SERVERDISCONNECT = 0x00004000, |
500 |
|
501 |
/// <summary> |
502 |
/// The contents of an existing folder have changed, |
503 |
/// but the folder still exists and has not been renamed. |
504 |
/// <see cref="HChangeNotifyFlags.SHCNF_IDLIST"/> or |
505 |
/// <see cref="HChangeNotifyFlags.SHCNF_PATH"/> must be specified in <i>uFlags</i>. |
506 |
/// <i>dwItem1</i> contains the folder that has changed. |
507 |
/// <i>dwItem2</i> is not used and should be <see langword="null"/>. |
508 |
/// If a folder has been created, deleted, or renamed, use SHCNE_MKDIR, SHCNE_RMDIR, or |
509 |
/// SHCNE_RENAMEFOLDER, respectively, instead. |
510 |
/// </summary> |
511 |
SHCNE_UPDATEDIR = 0x00001000, |
512 |
|
513 |
/// <summary> |
514 |
/// An image in the system image list has changed. |
515 |
/// <see cref="HChangeNotifyFlags.SHCNF_DWORD"/> must be specified in <i>uFlags</i>. |
516 |
/// </summary> |
517 |
SHCNE_UPDATEIMAGE = 0x00008000, |
518 |
|
519 |
} |
520 |
#endregion // enum HChangeNotifyEventID |
521 |
|
522 |
#region public enum HChangeNotifyFlags |
523 |
/// <summary> |
524 |
/// Flags that indicate the meaning of the <i>dwItem1</i> and <i>dwItem2</i> parameters. |
525 |
/// The uFlags parameter must be one of the following values. |
526 |
/// </summary> |
527 |
[Flags] |
528 |
public enum HChangeNotifyFlags |
529 |
{ |
530 |
/// <summary> |
531 |
/// The <i>dwItem1</i> and <i>dwItem2</i> parameters are DWORD values. |
532 |
/// </summary> |
533 |
SHCNF_DWORD = 0x0003, |
534 |
/// <summary> |
535 |
/// <i>dwItem1</i> and <i>dwItem2</i> are the addresses of ITEMIDLIST structures that |
536 |
/// represent the item(s) affected by the change. |
537 |
/// Each ITEMIDLIST must be relative to the desktop folder. |
538 |
/// </summary> |
539 |
SHCNF_IDLIST = 0x0000, |
540 |
/// <summary> |
541 |
/// <i>dwItem1</i> and <i>dwItem2</i> are the addresses of null-terminated strings of |
542 |
/// maximum length MAX_PATH that contain the full path names |
543 |
/// of the items affected by the change. |
544 |
/// </summary> |
545 |
SHCNF_PATHA = 0x0001, |
546 |
/// <summary> |
547 |
/// <i>dwItem1</i> and <i>dwItem2</i> are the addresses of null-terminated strings of |
548 |
/// maximum length MAX_PATH that contain the full path names |
549 |
/// of the items affected by the change. |
550 |
/// </summary> |
551 |
SHCNF_PATHW = 0x0005, |
552 |
/// <summary> |
553 |
/// <i>dwItem1</i> and <i>dwItem2</i> are the addresses of null-terminated strings that |
554 |
/// represent the friendly names of the printer(s) affected by the change. |
555 |
/// </summary> |
556 |
SHCNF_PRINTERA = 0x0002, |
557 |
/// <summary> |
558 |
/// <i>dwItem1</i> and <i>dwItem2</i> are the addresses of null-terminated strings that |
559 |
/// represent the friendly names of the printer(s) affected by the change. |
560 |
/// </summary> |
561 |
SHCNF_PRINTERW = 0x0006, |
562 |
/// <summary> |
563 |
/// The function should not return until the notification |
564 |
/// has been delivered to all affected components. |
565 |
/// As this flag modifies other data-type flags, it cannot by used by itself. |
566 |
/// </summary> |
567 |
SHCNF_FLUSH = 0x1000, |
568 |
/// <summary> |
569 |
/// The function should begin delivering notifications to all affected components |
570 |
/// but should return as soon as the notification process has begun. |
571 |
/// As this flag modifies other data-type flags, it cannot by used by itself. |
572 |
/// </summary> |
573 |
SHCNF_FLUSHNOWAIT = 0x2000 |
574 |
} |
575 |
#endregion // enum HChangeNotifyFlags |
576 |
|
577 |
internal enum GCS : uint |
578 |
{ |
579 |
GCS_VERBA = 0x00000000, |
580 |
GCS_HELPTEXTA = 0x00000001, |
581 |
GCS_VALIDATEA = 0x00000002, |
582 |
GCS_VERBW = 0x00000004, |
583 |
GCS_HELPTEXTW = 0x00000005, |
584 |
GCS_VALIDATEW = 0x00000006, |
585 |
GCS_VERBICONW = 0x00000014, |
586 |
GCS_UNICODE = 0x00000004 |
587 |
} |
588 |
|
589 |
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] |
590 |
internal struct CMINVOKECOMMANDINFO |
591 |
{ |
592 |
public uint cbSize; |
593 |
public CMIC fMask; |
594 |
public IntPtr hwnd; |
595 |
public IntPtr verb; |
596 |
[MarshalAs(UnmanagedType.LPStr)] |
597 |
public string parameters; |
598 |
[MarshalAs(UnmanagedType.LPStr)] |
599 |
public string directory; |
600 |
public int nShow; |
601 |
public uint dwHotKey; |
602 |
public IntPtr hIcon; |
603 |
} |
604 |
|
605 |
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] |
606 |
internal struct CMINVOKECOMMANDINFOEX |
607 |
{ |
608 |
public uint cbSize; |
609 |
public CMIC fMask; |
610 |
public IntPtr hwnd; |
611 |
public IntPtr verb; |
612 |
[MarshalAs(UnmanagedType.LPStr)] |
613 |
public string parameters; |
614 |
[MarshalAs(UnmanagedType.LPStr)] |
615 |
public string directory; |
616 |
public int nShow; |
617 |
public uint dwHotKey; |
618 |
public IntPtr hIcon; |
619 |
[MarshalAs(UnmanagedType.LPStr)] |
620 |
public string title; |
621 |
public IntPtr verbW; |
622 |
public string parametersW; |
623 |
public string directoryW; |
624 |
public string titleW; |
625 |
POINT ptInvoke; |
626 |
} |
627 |
|
628 |
[Flags] |
629 |
internal enum CMIC : uint |
630 |
{ |
631 |
CMIC_MASK_ICON = 0x00000010, |
632 |
CMIC_MASK_HOTKEY = 0x00000020, |
633 |
CMIC_MASK_NOASYNC = 0x00000100, |
634 |
CMIC_MASK_FLAG_NO_UI = 0x00000400, |
635 |
CMIC_MASK_UNICODE = 0x00004000, |
636 |
CMIC_MASK_NO_CONSOLE = 0x00008000, |
637 |
CMIC_MASK_ASYNCOK = 0x00100000, |
638 |
CMIC_MASK_NOZONECHECKS = 0x00800000, |
639 |
CMIC_MASK_FLAG_LOG_USAGE = 0x04000000, |
640 |
CMIC_MASK_SHIFT_DOWN = 0x10000000, |
641 |
CMIC_MASK_PTINVOKE = 0x20000000, |
642 |
CMIC_MASK_CONTROL_DOWN = 0x40000000 |
643 |
} |
644 |
|
645 |
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] |
646 |
public struct POINT |
647 |
{ |
648 |
public int X; |
649 |
public int Y; |
650 |
} |
651 |
|
652 |
internal enum CLIPFORMAT : uint |
653 |
{ |
654 |
CF_TEXT = 1, |
655 |
CF_BITMAP = 2, |
656 |
CF_METAFILEPICT = 3, |
657 |
CF_SYLK = 4, |
658 |
CF_DIF = 5, |
659 |
CF_TIFF = 6, |
660 |
CF_OEMTEXT = 7, |
661 |
CF_DIB = 8, |
662 |
CF_PALETTE = 9, |
663 |
CF_PENDATA = 10, |
664 |
CF_RIFF = 11, |
665 |
CF_WAVE = 12, |
666 |
CF_UNICODETEXT = 13, |
667 |
CF_ENHMETAFILE = 14, |
668 |
CF_HDROP = 15, |
669 |
CF_LOCALE = 16, |
670 |
CF_MAX = 17, |
671 |
|
672 |
CF_OWNERDISPLAY = 0x0080, |
673 |
CF_DSPTEXT = 0x0081, |
674 |
CF_DSPBITMAP = 0x0082, |
675 |
CF_DSPMETAFILEPICT = 0x0083, |
676 |
CF_DSPENHMETAFILE = 0x008E, |
677 |
|
678 |
CF_PRIVATEFIRST = 0x0200, |
679 |
CF_PRIVATELAST = 0x02FF, |
680 |
|
681 |
CF_GDIOBJFIRST = 0x0300, |
682 |
CF_GDIOBJLAST = 0x03FF |
683 |
} |
684 |
|
685 |
[Flags] |
686 |
internal enum CMF : uint |
687 |
{ |
688 |
CMF_NORMAL = 0x00000000, |
689 |
CMF_DEFAULTONLY = 0x00000001, |
690 |
CMF_VERBSONLY = 0x00000002, |
691 |
CMF_EXPLORE = 0x00000004, |
692 |
CMF_NOVERBS = 0x00000008, |
693 |
CMF_CANRENAME = 0x00000010, |
694 |
CMF_NODEFAULT = 0x00000020, |
695 |
CMF_INCLUDESTATIC = 0x00000040, |
696 |
CMF_ITEMMENU = 0x00000080, |
697 |
CMF_EXTENDEDVERBS = 0x00000100, |
698 |
CMF_DISABLEDVERBS = 0x00000200, |
699 |
CMF_ASYNCVERBSTATE = 0x00000400, |
700 |
CMF_OPTIMIZEFORINVOKE = 0x00000800, |
701 |
CMF_SYNCCASCADEMENU = 0x00001000, |
702 |
CMF_DONOTPICKDEFAULT = 0x00002000, |
703 |
CMF_RESERVED = 0xFFFF0000 |
704 |
} |
705 |
|
706 |
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] |
707 |
internal struct MENUITEMINFO |
708 |
{ |
709 |
public uint cbSize; |
710 |
public MIIM fMask; |
711 |
public MFT fType; |
712 |
public MFS fState; |
713 |
public uint wID; |
714 |
public IntPtr hSubMenu; |
715 |
public IntPtr hbmpChecked; |
716 |
public IntPtr hbmpUnchecked; |
717 |
public UIntPtr dwItemData; |
718 |
public string dwTypeData; |
719 |
public uint cch; |
720 |
public IntPtr hbmpItem; |
721 |
} |
722 |
|
723 |
[Flags] |
724 |
internal enum MIIM : uint |
725 |
{ |
726 |
MIIM_STATE = 0x00000001, |
727 |
MIIM_ID = 0x00000002, |
728 |
MIIM_SUBMENU = 0x00000004, |
729 |
MIIM_CHECKMARKS = 0x00000008, |
730 |
MIIM_TYPE = 0x00000010, |
731 |
MIIM_DATA = 0x00000020, |
732 |
MIIM_STRING = 0x00000040, |
733 |
MIIM_BITMAP = 0x00000080, |
734 |
MIIM_FTYPE = 0x00000100 |
735 |
} |
736 |
[Flags] |
737 |
internal enum MFT : uint |
738 |
{ |
739 |
MFT_STRING = 0x00000000, |
740 |
MFT_BITMAP = 0x00000004, |
741 |
MFT_MENUBARBREAK = 0x00000020, |
742 |
MFT_MENUBREAK = 0x00000040, |
743 |
MFT_OWNERDRAW = 0x00000100, |
744 |
MFT_RADIOCHECK = 0x00000200, |
745 |
MFT_SEPARATOR = 0x00000800, |
746 |
MFT_RIGHTORDER = 0x00002000, |
747 |
MFT_RIGHTJUSTIFY = 0x00004000 |
748 |
} |
749 |
|
750 |
[Flags] |
751 |
internal enum MFS : uint |
752 |
{ |
753 |
MFS_ENABLED = 0x00000000, |
754 |
MFS_UNCHECKED = 0x00000000, |
755 |
MFS_UNHILITE = 0x00000000, |
756 |
MFS_GRAYED = 0x00000003, |
757 |
MFS_DISABLED = 0x00000003, |
758 |
MFS_CHECKED = 0x00000008, |
759 |
MFS_HILITE = 0x00000080, |
760 |
MFS_DEFAULT = 0x00001000 |
761 |
} |
762 |
|
763 |
[Flags] |
764 |
internal enum MF: uint |
765 |
{ |
766 |
MF_BYCOMMAND = 0x00000000, |
767 |
MF_ENABLED = 0x00000000, |
768 |
MF_DISABLED = 0x00000002, |
769 |
MF_BITMAP = 0x00000004, |
770 |
MF_CHECKED = 0x00000008, |
771 |
MF_BYPOSITION = 0x00000400, |
772 |
MF_SEPARATOR = 0x00000800 |
773 |
} |
774 |
|
775 |
#endregion |
776 |
|
777 |
|
778 |
internal class NativeMethods |
779 |
{ |
780 |
/// <summary> |
781 |
/// Retrieve the names of dropped files that result from a successful drag- |
782 |
/// and-drop operation. |
783 |
/// </summary> |
784 |
/// <param name="hDrop"> |
785 |
/// Identifier of the structure that contains the file names of the dropped |
786 |
/// files. |
787 |
/// </param> |
788 |
/// <param name="iFile"> |
789 |
/// Index of the file to query. If the value of this parameter is 0xFFFFFFFF, |
790 |
/// DragQueryFile returns a count of the files dropped. |
791 |
/// </param> |
792 |
/// <param name="pszFile"> |
793 |
/// The address of a buffer that receives the file name of a dropped file |
794 |
/// when the function returns. |
795 |
/// </param> |
796 |
/// <param name="cch"> |
797 |
/// The size, in characters, of the pszFile buffer. |
798 |
/// </param> |
799 |
/// <returns>A non-zero value indicates a successful call.</returns> |
800 |
[DllImport("shell32", CharSet = CharSet.Unicode)] |
801 |
public static extern uint DragQueryFile( |
802 |
IntPtr hDrop, |
803 |
uint iFile, |
804 |
StringBuilder pszFile, |
805 |
int cch); |
806 |
|
807 |
/// <summary> |
808 |
/// Free the specified storage medium. |
809 |
/// </summary> |
810 |
/// <param name="pmedium"> |
811 |
/// Reference of the storage medium that is to be freed. |
812 |
/// </param> |
813 |
[DllImport("ole32.dll", CharSet = CharSet.Unicode)] |
814 |
public static extern void ReleaseStgMedium(ref STGMEDIUM pmedium); |
815 |
|
816 |
/// <summary> |
817 |
/// Insert a new menu item at the specified position in a menu. |
818 |
/// </summary> |
819 |
/// <param name="hMenu"> |
820 |
/// A handle to the menu in which the new menu item is inserted. |
821 |
/// </param> |
822 |
/// <param name="uItem"> |
823 |
/// The identifier or position of the menu item before which to insert the |
824 |
/// new item. The meaning of this parameter depends on the value of |
825 |
/// fByPosition. |
826 |
/// </param> |
827 |
/// <param name="fByPosition"> |
828 |
/// Controls the meaning of uItem. If this parameter is false, uItem is a |
829 |
/// menu item identifier. Otherwise, it is a menu item position. |
830 |
/// </param> |
831 |
/// <param name="mii"> |
832 |
/// A reference of a MENUITEMINFO structure that contains information about |
833 |
/// the new menu item. |
834 |
/// </param> |
835 |
/// <returns> |
836 |
/// If the function succeeds, the return value is true. |
837 |
/// </returns> |
838 |
[DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)] |
839 |
[return: MarshalAs(UnmanagedType.Bool)] |
840 |
public static extern bool InsertMenuItem( |
841 |
IntPtr hMenu, |
842 |
uint uItem, |
843 |
[MarshalAs(UnmanagedType.Bool)]bool fByPosition, |
844 |
ref MENUITEMINFO mii); |
845 |
|
846 |
[DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)] |
847 |
[return: MarshalAs(UnmanagedType.Bool)] |
848 |
public static extern bool InsertMenu( |
849 |
IntPtr hMenu, |
850 |
uint uPosition, |
851 |
MF uFlags, |
852 |
uint uIDNewItem, |
853 |
string lpNewItem); |
854 |
|
855 |
|
856 |
[DllImport("shell32", CharSet = CharSet.Unicode, SetLastError = true)] |
857 |
[return: MarshalAs(UnmanagedType.Bool)] |
858 |
public static extern bool SHGetPathFromIDList( |
859 |
IntPtr pidl, |
860 |
StringBuilder pszpath); |
861 |
|
862 |
[DllImport("shell32.dll")] |
863 |
public static extern void SHChangeNotify(HChangeNotifyEventID wEventId, |
864 |
HChangeNotifyFlags uFlags, |
865 |
IntPtr dwItem1, |
866 |
IntPtr dwItem2); |
867 |
|
868 |
[DllImport("gdi32.dll")] |
869 |
public static extern bool DeleteObject(IntPtr hObject); |
870 |
|
871 |
|
872 |
|
873 |
public static int HighWord(int number) |
874 |
{ |
875 |
return ((number & 0x80000000) == 0x80000000) ? |
876 |
(number >> 16) : ((number >> 16) & 0xffff); |
877 |
} |
878 |
|
879 |
public static int LowWord(int number) |
880 |
{ |
881 |
return number & 0xffff; |
882 |
} |
883 |
} |
884 |
|
885 |
internal static class WinError |
886 |
{ |
887 |
public const int S_OK = 0x0000; |
888 |
public const int S_FALSE = 0x0001; |
889 |
public const int E_FAIL = -2147467259; |
890 |
public const int E_INVALIDARG = -2147024809; |
891 |
public const int E_OUTOFMEMORY = -2147024882; |
892 |
public const int STRSAFE_E_INSUFFICIENT_BUFFER = -2147024774; |
893 |
|
894 |
public const uint SEVERITY_SUCCESS = 0; |
895 |
public const uint SEVERITY_ERROR = 1; |
896 |
|
897 |
/// <summary> |
898 |
/// Create an HRESULT value from component pieces. |
899 |
/// </summary> |
900 |
/// <param name="sev">The severity to be used</param> |
901 |
/// <param name="fac">The facility to be used</param> |
902 |
/// <param name="code">The error number</param> |
903 |
/// <returns>A HRESULT constructed from the above 3 values</returns> |
904 |
public static int MAKE_HRESULT(uint sev, uint fac, uint code) |
905 |
{ |
906 |
return (int)((sev << 31) | (fac << 16) | code); |
907 |
} |
908 |
} |
909 |
} |