1 // TortoiseSVN - a Windows shell extension for easy version control
\r
3 // Copyright (C) 2007 - TortoiseSVN
\r
5 // This program is free software; you can redistribute it and/or
\r
6 // modify it under the terms of the GNU General Public License
\r
7 // as published by the Free Software Foundation; either version 2
\r
8 // of the License, or (at your option) any later version.
\r
10 // This program is distributed in the hope that it will be useful,
\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 // GNU General Public License for more details.
\r
15 // You should have received a copy of the GNU General Public License
\r
16 // along with this program; if not, write to the Free Software Foundation,
\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\r
19 #define _WIN32_WINNT 0x0400
\r
20 #include <Windows.h>
\r
25 const HINSTANCE NIL = (HINSTANCE)((char*)(0)-1);
\r
27 static HINSTANCE hInst = NULL;
\r
29 static HINSTANCE hTortoiseSVN = NULL;
\r
30 static LPFNGETCLASSOBJECT pDllGetClassObject = NULL;
\r
31 static LPFNCANUNLOADNOW pDllCanUnloadNow = NULL;
\r
37 * \ingroup TortoiseShell
\r
38 * Check whether to load the full TortoiseSVN.dll or not.
\r
40 static BOOL WantRealVersion(void)
\r
42 static const WCHAR TSVNRootKey[]=_T("Software\\TortoiseSVN");
\r
43 static const WCHAR ExplorerOnlyValue[]=_T("LoadDllOnlyInExplorer");
\r
45 static const WCHAR ExplorerEnvPath[]=_T("%SystemRoot%\\explorer.exe");
\r
48 DWORD bExplorerOnly = 0;
\r
49 WCHAR ModuleName[MAX_PATH] = {0};
\r
50 WCHAR ExplorerPath[MAX_PATH] = {0};
\r
52 HKEY hKey = HKEY_CURRENT_USER;
\r
53 LONG Result = ERROR;
\r
54 DWORD Type = REG_DWORD;
\r
55 DWORD Len = sizeof(DWORD);
\r
57 BOOL bWantReal = TRUE;
\r
60 TRACE(_T("WantRealVersion() - Enter\n"));
\r
62 Result = RegOpenKeyEx(HKEY_CURRENT_USER, TSVNRootKey, 0, KEY_READ, &hKey);
\r
63 if (Result == ERROR_SUCCESS)
\r
65 Result = RegQueryValueEx(hKey, ExplorerOnlyValue, NULL, &Type, (BYTE *)&bExplorerOnly, &Len);
\r
66 if ((Result == ERROR_SUCCESS) && (Type == REG_DWORD) && (Len == sizeof(DWORD)) && bExplorerOnly)
\r
68 TRACE(_T("WantRealVersion() - Explorer Only\n"));
\r
70 // check if the current process is in fact the explorer
\r
71 Len = GetModuleFileName(NULL, ModuleName, sizeof(ModuleName));
\r
74 TRACE(_T("Process is %s\n"), ModuleName);
\r
76 Len = ExpandEnvironmentStrings(ExplorerEnvPath, ExplorerPath, sizeof(ExplorerPath));
\r
77 if (Len && (Len <= sizeof(ExplorerPath)))
\r
79 TRACE(_T("Explorer path is %s\n"), ExplorerPath);
\r
80 bWantReal = !lstrcmpi(ModuleName, ExplorerPath);
\r
88 TRACE(_T("WantRealVersion() - Exit\n"));
\r
92 static void LoadRealLibrary(void)
\r
94 static const char GetClassObject[] = "DllGetClassObject";
\r
95 static const char CanUnloadNow[] = "DllCanUnloadNow";
\r
97 WCHAR ModuleName[MAX_PATH] = {0};
\r
104 if (!WantRealVersion())
\r
106 TRACE(_T("LoadRealLibrary() - Bypass\n"));
\r
107 hTortoiseSVN = NIL;
\r
111 Len = GetModuleFileName(hInst, ModuleName, sizeof(ModuleName));
\r
114 TRACE(_T("LoadRealLibrary() - Fail\n"));
\r
115 hTortoiseSVN = NIL;
\r
119 // truncate the string at the last '\' char
\r
123 if (ModuleName[Len] == '\\')
\r
125 ModuleName[Len] = '\0';
\r
131 TRACE(_T("LoadRealLibrary() - Fail\n"));
\r
132 hTortoiseSVN = NIL;
\r
135 lstrcat(ModuleName, _T("\\TortoiseSVN.dll"));
\r
137 TRACE(_T("LoadRealLibrary() - Load %s\n"), ModuleName);
\r
139 hTortoiseSVN = LoadLibraryEx(ModuleName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
\r
142 TRACE(_T("LoadRealLibrary() - Fail\n"));
\r
143 hTortoiseSVN = NIL;
\r
147 TRACE(_T("LoadRealLibrary() - Success\n"));
\r
148 pDllGetClassObject = NULL;
\r
149 pDllCanUnloadNow = NULL;
\r
150 pDllGetClassObject = (LPFNGETCLASSOBJECT)GetProcAddress(hTortoiseSVN, GetClassObject);
\r
151 if (pDllGetClassObject == NULL)
\r
153 TRACE(_T("LoadRealLibrary() - Fail\n"));
\r
154 FreeLibrary(hTortoiseSVN);
\r
155 hTortoiseSVN = NIL;
\r
158 pDllCanUnloadNow = (LPFNCANUNLOADNOW)GetProcAddress(hTortoiseSVN, CanUnloadNow);
\r
159 if (pDllCanUnloadNow == NULL)
\r
161 TRACE(_T("LoadRealLibrary() - Fail\n"));
\r
162 FreeLibrary(hTortoiseSVN);
\r
163 hTortoiseSVN = NIL;
\r
168 static void UnloadRealLibrary(void)
\r
173 if (hTortoiseSVN != NIL)
\r
174 FreeLibrary(hTortoiseSVN);
\r
176 hTortoiseSVN = NULL;
\r
177 pDllGetClassObject = NULL;
\r
178 pDllCanUnloadNow = NULL;
\r
182 BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved)
\r
185 // if no debugger is present, then don't load the dll.
\r
186 // this prevents other apps from loading the dll and locking
\r
189 BOOL bInShellTest = FALSE;
\r
190 TCHAR buf[_MAX_PATH + 1]; // MAX_PATH ok, the test really is for debugging anyway.
\r
191 DWORD pathLength = GetModuleFileName(NULL, buf, _MAX_PATH);
\r
193 UNREFERENCED_PARAMETER(Reserved);
\r
195 if (pathLength >= 14)
\r
197 if ((lstrcmpi(&buf[pathLength-14], _T("\\ShellTest.exe"))) == 0)
\r
199 bInShellTest = TRUE;
\r
203 if (!IsDebuggerPresent() && !bInShellTest)
\r
205 TRACE(_T("In debug load preventer\n"));
\r
209 UNREFERENCED_PARAMETER(Reserved);
\r
215 case DLL_PROCESS_ATTACH:
\r
219 //case DLL_THREAD_ATTACH:
\r
222 //case DLL_THREAD_DETACH:
\r
225 //case DLL_PROCESS_DETACH:
\r
233 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
\r
235 TRACE(_T("DllGetClassObject() - Enter\n"));
\r
238 if (!pDllGetClassObject)
\r
245 TRACE(_T("DllGetClassObject() - Bypass\n"));
\r
246 return CLASS_E_CLASSNOTAVAILABLE;
\r
249 TRACE(_T("DllGetClassObject() - Forward\n"));
\r
250 return pDllGetClassObject(rclsid, riid, ppv);
\r
253 STDAPI DllCanUnloadNow(void)
\r
257 TRACE(_T("DllCanUnloadNow() - Enter\n"));
\r
259 if (pDllCanUnloadNow)
\r
261 TRACE(_T("DllCanUnloadNow() - Forward\n"));
\r
262 Result = pDllCanUnloadNow();
\r
263 if (Result != S_OK)
\r
267 TRACE(_T("DllCanUnloadNow() - Unload\n"));
\r
268 UnloadRealLibrary();
\r