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