Reduce variable scope
[TortoiseGit.git] / src / TortoiseShell / TortoiseStub.cpp
bloba68725bb2fd0e56f1255d433628e7c690665b779
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2012-2013 - TortoiseGit
4 // Copyright (C) 2007, 2009, 2013 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #define _WIN32_WINNT 0x0400
21 #include <Windows.h>
22 #include <tchar.h>
23 #include "Debug.h"
25 const HINSTANCE NIL = (HINSTANCE)((char*)(0)-1);
27 static HINSTANCE hInst = NULL;
29 static HINSTANCE hTortoiseGit = NULL;
30 static LPFNGETCLASSOBJECT pDllGetClassObject = NULL;
31 static LPFNCANUNLOADNOW pDllCanUnloadNow = NULL;
33 static BOOL DebugActive(void)
35 static const WCHAR TGitRootKey[]=_T("Software\\TortoiseGit");
36 static const WCHAR ExplorerOnlyValue[]=_T("DebugShell");
38 DWORD bDebug = 0;
40 HKEY hKey = HKEY_CURRENT_USER;
41 LONG Result = ERROR;
42 DWORD Type = REG_DWORD;
43 DWORD Len = sizeof(DWORD);
45 BOOL bDebugActive = FALSE;
48 TRACE(_T("DebugActive() - Enter\n"));
50 if (IsDebuggerPresent())
52 Result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TGitRootKey, 0, KEY_READ, &hKey);
53 if (Result == ERROR_SUCCESS)
55 Result = RegQueryValueEx(hKey, ExplorerOnlyValue, NULL, &Type, (BYTE *)&bDebug, &Len);
56 if ((Result == ERROR_SUCCESS) && (Type == REG_DWORD) && (Len == sizeof(DWORD)) && bDebug)
58 TRACE(_T("DebugActive() - debug active\n"));
59 bDebugActive = TRUE;
62 RegCloseKey(hKey);
66 TRACE(_T("WantRealVersion() - Exit\n"));
67 return bDebugActive;
70 /**
71 * \ingroup TortoiseShell
72 * Check whether to load the full TortoiseGit.dll or not.
74 static BOOL WantRealVersion(void)
76 static const WCHAR TGitRootKey[]=_T("Software\\TortoiseGit");
77 static const WCHAR ExplorerOnlyValue[]=_T("LoadDllOnlyInExplorer");
79 static const WCHAR ExplorerEnvPath[]=_T("%SystemRoot%\\explorer.exe");
82 DWORD bExplorerOnly = 0;
83 WCHAR ModuleName[MAX_PATH] = {0};
84 WCHAR ExplorerPath[MAX_PATH] = {0};
86 HKEY hKey = HKEY_CURRENT_USER;
87 LONG Result = ERROR;
88 DWORD Type = REG_DWORD;
89 DWORD Len = sizeof(DWORD);
91 BOOL bWantReal = TRUE;
93 TRACE(_T("WantRealVersion() - Enter\n"));
95 Result = RegOpenKeyEx(HKEY_CURRENT_USER, TGitRootKey, 0, KEY_READ, &hKey);
96 if (Result == ERROR_SUCCESS)
98 Result = RegQueryValueEx(hKey, ExplorerOnlyValue, NULL, &Type, (BYTE *)&bExplorerOnly, &Len);
99 if ((Result == ERROR_SUCCESS) && (Type == REG_DWORD) && (Len == sizeof(DWORD)) && bExplorerOnly)
101 TRACE(_T("WantRealVersion() - Explorer Only\n"));
103 // check if the current process is in fact the explorer
104 Len = GetModuleFileName(NULL, ModuleName, _countof(ModuleName));
105 if (Len)
107 TRACE(_T("Process is %s\n"), ModuleName);
109 Len = ExpandEnvironmentStrings(ExplorerEnvPath, ExplorerPath, _countof(ExplorerPath));
110 if (Len && (Len <= _countof(ExplorerPath)))
112 TRACE(_T("Explorer path is %s\n"), ExplorerPath);
113 bWantReal = !lstrcmpi(ModuleName, ExplorerPath);
116 // we also have to allow the verclsid.exe process - that process determines
117 // first whether the shell is allowed to even use an extension.
118 Len = lstrlen(ModuleName);
119 if ((Len > 13)&&(lstrcmpi(&ModuleName[Len-13], _T("\\verclsid.exe")) == 0))
120 bWantReal = TRUE;
124 RegCloseKey(hKey);
127 TRACE(_T("WantRealVersion() - Exit\n"));
128 return bWantReal;
131 static void LoadRealLibrary(void)
133 static const char GetClassObject[] = "DllGetClassObject";
134 static const char CanUnloadNow[] = "DllCanUnloadNow";
136 WCHAR ModuleName[MAX_PATH] = {0};
137 DWORD Len = 0;
138 HINSTANCE hUseInst = hInst;
140 if (hTortoiseGit)
141 return;
143 if (!WantRealVersion())
145 TRACE(_T("LoadRealLibrary() - Bypass\n"));
146 hTortoiseGit = NIL;
147 return;
149 // if HKCU\Software\TortoiseGit\DebugShell is set, load the dlls from the location of the current process
150 // which is for our debug purposes an instance of usually TortoiseProc. That way we can force the load
151 // of the debug dlls.
152 if (DebugActive())
153 hUseInst = NULL;
154 Len = GetModuleFileName(hUseInst, ModuleName, _countof(ModuleName));
155 if (!Len)
157 TRACE(_T("LoadRealLibrary() - Fail\n"));
158 hTortoiseGit = NIL;
159 return;
162 // truncate the string at the last '\' char
163 while(Len > 0)
165 --Len;
166 if (ModuleName[Len] == '\\')
168 ModuleName[Len] = '\0';
169 break;
172 if (Len == 0)
174 TRACE(_T("LoadRealLibrary() - Fail\n"));
175 hTortoiseGit = NIL;
176 return;
178 #ifdef _WIN64
179 lstrcat(ModuleName, _T("\\TortoiseGit.dll"));
180 #else
181 lstrcat(ModuleName, _T("\\TortoiseGit32.dll"));
182 #endif
183 TRACE(_T("LoadRealLibrary() - Load %s\n"), ModuleName);
185 hTortoiseGit = LoadLibraryEx(ModuleName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
186 if (!hTortoiseGit)
188 TRACE(_T("LoadRealLibrary() - Fail\n"));
189 hTortoiseGit = NIL;
190 return;
193 TRACE(_T("LoadRealLibrary() - Success\n"));
194 pDllGetClassObject = NULL;
195 pDllCanUnloadNow = NULL;
196 pDllGetClassObject = (LPFNGETCLASSOBJECT)GetProcAddress(hTortoiseGit, GetClassObject);
197 if (pDllGetClassObject == NULL)
199 TRACE(_T("LoadRealLibrary() - Fail\n"));
200 FreeLibrary(hTortoiseGit);
201 hTortoiseGit = NIL;
202 return;
204 pDllCanUnloadNow = (LPFNCANUNLOADNOW)GetProcAddress(hTortoiseGit, CanUnloadNow);
205 if (pDllCanUnloadNow == NULL)
207 TRACE(_T("LoadRealLibrary() - Fail\n"));
208 FreeLibrary(hTortoiseGit);
209 hTortoiseGit = NIL;
210 return;
214 static void UnloadRealLibrary(void)
216 if (!hTortoiseGit)
217 return;
219 if (hTortoiseGit != NIL)
220 FreeLibrary(hTortoiseGit);
222 hTortoiseGit = NULL;
223 pDllGetClassObject = NULL;
224 pDllCanUnloadNow = NULL;
227 BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID /*Reserved*/)
229 #ifdef _DEBUG
230 // if no debugger is present, then don't load the dll.
231 // this prevents other apps from loading the dll and locking
232 // it.
234 BOOL bInShellTest = FALSE;
235 TCHAR buf[MAX_PATH + 1]; // MAX_PATH ok, the test really is for debugging anyway.
236 DWORD pathLength = GetModuleFileName(NULL, buf, MAX_PATH);
238 if (pathLength >= 14)
240 if ((lstrcmpi(&buf[pathLength-14], _T("\\ShellTest.exe"))) == 0)
242 bInShellTest = TRUE;
244 if ((_tcsicmp(&buf[pathLength-13], _T("\\verclsid.exe"))) == 0)
246 bInShellTest = TRUE;
250 if (!IsDebuggerPresent() && !bInShellTest)
252 TRACE(_T("In debug load preventer\n"));
253 return FALSE;
255 #endif
257 switch(Reason)
259 case DLL_PROCESS_ATTACH:
260 hInst = hInstance;
261 break;
263 /*case DLL_THREAD_ATTACH:
264 break;
266 case DLL_THREAD_DETACH:
267 break;
269 case DLL_PROCESS_DETACH:
270 break;*/
273 return TRUE;
276 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
278 TRACE(_T("DllGetClassObject() - Enter\n"));
280 LoadRealLibrary();
281 if (!pDllGetClassObject)
283 if (ppv)
284 *ppv = NULL;
286 TRACE(_T("DllGetClassObject() - Bypass\n"));
287 return CLASS_E_CLASSNOTAVAILABLE;
290 TRACE(_T("DllGetClassObject() - Forward\n"));
291 return pDllGetClassObject(rclsid, riid, ppv);
294 STDAPI DllCanUnloadNow(void)
296 TRACE(_T("DllCanUnloadNow() - Enter\n"));
298 if (pDllCanUnloadNow)
300 TRACE(_T("DllCanUnloadNow() - Forward\n"));
301 HRESULT Result = pDllCanUnloadNow();
302 if (Result != S_OK)
303 return Result;
306 TRACE(_T("DllCanUnloadNow() - Unload\n"));
307 UnloadRealLibrary();
308 return S_OK;