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