b1d0638f9d3f2e2ee7e87163446182b1870bd639
[pithos-ms-client] / trunk / Pithos.ShellExtensions / Overlays / IconOverlayBase.cs
1 #region
2 /* -----------------------------------------------------------------------
3  * <copyright file="IconOverlayBase.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.Diagnostics.Contracts;
45 using System.IO;
46
47 using System.ComponentModel.Composition;
48 using System.Linq;
49 using Microsoft.Win32;
50 using Pithos.Interfaces;
51
52 namespace Pithos.ShellExtensions.Overlays
53 {
54
55     public class IconOverlayBase : IShellIconOverlayIdentifier
56     {
57         private static readonly log4net.ILog Log = log4net.LogManager.GetLogger("Pithos.IconOverlay");
58
59         protected static string PithosPrefix = "0Pithos";
60
61         public string OverlayName { get; private set; }
62         public string IconPath { get; private set; }
63
64         [Import(typeof (IStatusChecker))] 
65         public IStatusChecker StatusChecker;
66         [Import(typeof (IPithosSettings))] 
67         public IPithosSettings Settings;
68
69
70
71         public IconOverlayBase(string iconName)
72         {
73             if (String.IsNullOrWhiteSpace(iconName))
74                 throw new ArgumentNullException("iconName","Empty iconName");
75
76             Debug.WriteLine("Icon Overlay Instance created", LogCategories.ShellOverlays);
77             IoC.Current.Compose(this);
78             
79
80             string overlayName=PithosPrefix + iconName;
81             string iconFile = iconName + "Icon.ico";
82
83
84             var iconsFolder = Settings.IconsPath;
85             var fullPath = Path.Combine(iconsFolder, iconFile);
86
87             OverlayName = overlayName;
88             IconPath = fullPath;
89
90             
91         }
92
93
94         private static bool? _isExplorer = false;
95
96
97         private bool IsExplorer
98         {
99             get
100             {
101                 if (!_isExplorer.HasValue)
102                 {
103                     var moduleName = Process.GetCurrentProcess().MainModule.ModuleName;
104                     _isExplorer = (moduleName == "explorer.exe");
105                 }
106                 return _isExplorer.Value;
107             }
108         }
109
110         public int IsMemberOf(string path, uint attributes)
111         {
112             var showOnlyInExplorer=(int)Registry.LocalMachine.GetValue(@"SOFTWARE\GRNet\Pithos\ShowOnlyInExplorer", 0);
113             if (showOnlyInExplorer!=0 && !IsExplorer)
114                 return WinError.S_FALSE;
115
116
117             if (String.IsNullOrWhiteSpace(path))
118                 throw new ArgumentNullException("path","Empty path");
119
120             Debug.WriteLine(String.Format("ICON Status check for {0} - {1}", path, GetType().Name), LogCategories.ShellOverlays);
121             
122             if (!Settings.Accounts.Any(account=>account.RootPath!=null && path.StartsWith(account.RootPath,StringComparison.InvariantCultureIgnoreCase)))
123                 return WinError.S_FALSE;
124
125             var status=StatusChecker.GetFileOverlayStatus(path);
126             var isMember = (PithosPrefix + status == OverlayName);
127             Debug.WriteLine(String.Format("[STATUS] Was {0}, expected {1} for {2}", status, OverlayName,path ), LogCategories.ShellOverlays);
128             return isMember ? WinError.S_OK : WinError.S_FALSE;
129         }
130
131         public int GetOverlayInfo(
132             IntPtr iconFileBuffer,
133             int iconFileBufferSize,
134             out int iconIndex,
135             out uint flags)
136         {
137             Contract.Requires(iconFileBuffer!=IntPtr.Zero);
138             Contract.Requires(iconFileBufferSize>0);
139
140             if (iconFileBuffer == IntPtr.Zero)
141                 throw new ArgumentNullException("iconFileBuffer","iconFileBuffer not initialized");
142             if (iconFileBufferSize<=0)
143                 throw new ArgumentException("iconFileBufferSize", "iconFileBufferSize must be greatere than 0");
144             Debug.WriteLine("Looking for icons", LogCategories.ShellOverlays);
145             Debug.WriteLine(string.Format("ICON file {0}", IconPath), LogCategories.ShellOverlays);
146             
147             int bytesCount = System.Text.Encoding.Unicode.GetByteCount(IconPath);
148             Debug.WriteLine(string.Format(" GetOverlayInfo::{0}", bytesCount), LogCategories.ShellOverlays);
149
150             MarshalHelpers.CopyToBuffer(IconPath, iconFileBuffer, iconFileBufferSize);
151
152             flags = (uint)(ISIOI.ISIOI_ICONFILE);// | ISIOI.ISIOI_ICONINDEX);
153             iconIndex = 0;
154             return WinError.S_OK;
155         }
156
157         public int  GetPriority(out int priority)
158         {
159             Debug.WriteLine("Checking for priority");
160             priority = 0;
161             return WinError.S_OK;
162         }
163
164         
165         public static void RegisterOverlay(Type type,string iconName)
166         {
167             Contract.Requires(type != null);
168             Contract.Requires(!String.IsNullOrWhiteSpace(iconName));
169
170             if (type == null)
171                 throw new ArgumentNullException("type", "type can't be null");
172             if (String.IsNullOrWhiteSpace(iconName))
173                 throw new ArgumentNullException("iconName", "iconName can't be null");
174
175             try
176             {
177                 
178                 ShellExtReg.RegisterIconOverlayIdentifier(type.GUID, iconName);
179
180                 NativeMethods.SHChangeNotify(HChangeNotifyEventID.SHCNE_ASSOCCHANGED, HChangeNotifyFlags.SHCNF_IDLIST,
181                                              IntPtr.Zero, IntPtr.Zero);
182                 Debug.WriteLine("Registered icon handler");
183             }
184             catch (Exception ex)
185             {
186                 Debug.WriteLine(ex.Message); // Log the error
187                 throw;  // Re-throw the exception
188             }
189         }
190
191         
192         public static void UnregisterOverlay(Type type,string iconName)
193         {
194             Contract.Requires(type!=null);
195             Contract.Requires(!String.IsNullOrWhiteSpace(iconName));
196
197             if (type==null)
198                 throw new ArgumentNullException("type","type can't be null");
199             if (String.IsNullOrWhiteSpace(iconName))
200                 throw new ArgumentNullException("iconName","iconName can't be null");
201             try
202             {                
203                 ShellExtReg.UnregisterIconOverlayIdentifier(type.GUID, iconName);
204                 Debug.WriteLine(String.Format("UnRegistered icon handler {0}:{1}",iconName,type.GUID), LogCategories.ShellOverlays);
205             }
206             catch (Exception ex)
207             {
208                 //Log and rethrow
209                 Log.ErrorFormat("Failed to unregister overlay {0}:{1} with error {2}",iconName,type.GUID,ex.Message); 
210                 throw;  
211             }
212         }
213     }
214
215 }