OSDN Git Service

Try to enable 64bit compile
[tortoisegit/TortoiseGitJp.git] / src / TortoiseShell / TortoiseStub.c
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2007 - TortoiseSVN\r
4 \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
9 \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
14 \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
18 //\r
19 #define _WIN32_WINNT 0x0400\r
20 #include <Windows.h>\r
21 #include <tchar.h>\r
22 #include "Debug.h"\r
23 \r
24 \r
25 const HINSTANCE NIL = (HINSTANCE)((char*)(0)-1);\r
26 \r
27 static HINSTANCE hInst = NULL;\r
28 \r
29 static HINSTANCE hTortoiseSVN = NULL;\r
30 static LPFNGETCLASSOBJECT pDllGetClassObject = NULL;\r
31 static LPFNCANUNLOADNOW pDllCanUnloadNow = NULL;\r
32 \r
33 \r
34 \r
35 \r
36 /**\r
37  * \ingroup TortoiseShell\r
38  * Check whether to load the full TortoiseSVN.dll or not.\r
39  */\r
40 static BOOL WantRealVersion(void)\r
41 {\r
42         static const WCHAR TSVNRootKey[]=_T("Software\\TortoiseSVN");\r
43         static const WCHAR ExplorerOnlyValue[]=_T("LoadDllOnlyInExplorer");\r
44 \r
45         static const WCHAR ExplorerEnvPath[]=_T("%SystemRoot%\\explorer.exe");\r
46 \r
47 \r
48         DWORD bExplorerOnly = 0;\r
49         WCHAR ModuleName[MAX_PATH] = {0};\r
50         WCHAR ExplorerPath[MAX_PATH] = {0};\r
51 \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
56 \r
57         BOOL bWantReal = TRUE;\r
58 \r
59 \r
60         TRACE(_T("WantRealVersion() - Enter\n"));\r
61 \r
62         Result = RegOpenKeyEx(HKEY_CURRENT_USER, TSVNRootKey, 0, KEY_READ, &hKey);\r
63         if (Result == ERROR_SUCCESS)\r
64         {\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
67                 {\r
68                         TRACE(_T("WantRealVersion() - Explorer Only\n"));\r
69 \r
70                         // check if the current process is in fact the explorer\r
71                         Len = GetModuleFileName(NULL, ModuleName, sizeof(ModuleName));\r
72                         if (Len)\r
73                         {\r
74                                 TRACE(_T("Process is %s\n"), ModuleName);\r
75 \r
76                                 Len = ExpandEnvironmentStrings(ExplorerEnvPath, ExplorerPath, sizeof(ExplorerPath));\r
77                                 if (Len && (Len <= sizeof(ExplorerPath)))\r
78                                 {\r
79                                         TRACE(_T("Explorer path is %s\n"), ExplorerPath);\r
80                                         bWantReal = !lstrcmpi(ModuleName, ExplorerPath);\r
81                                 }\r
82                         }\r
83                 }\r
84 \r
85                 RegCloseKey(hKey);\r
86         }\r
87 \r
88         TRACE(_T("WantRealVersion() - Exit\n"));\r
89         return bWantReal;\r
90 }\r
91 \r
92 static void LoadRealLibrary(void)\r
93 {\r
94         static const char GetClassObject[] = "DllGetClassObject";\r
95         static const char CanUnloadNow[] = "DllCanUnloadNow";\r
96 \r
97         WCHAR ModuleName[MAX_PATH] = {0};\r
98         DWORD Len = 0;\r
99 \r
100 \r
101         if (hTortoiseSVN)\r
102                 return;\r
103 \r
104         if (!WantRealVersion())\r
105         {\r
106                 TRACE(_T("LoadRealLibrary() - Bypass\n"));\r
107                 hTortoiseSVN = NIL;\r
108                 return;\r
109         }\r
110 \r
111         Len = GetModuleFileName(hInst, ModuleName, sizeof(ModuleName));\r
112         if (!Len)\r
113         {\r
114                 TRACE(_T("LoadRealLibrary() - Fail\n"));\r
115                 hTortoiseSVN = NIL;\r
116                 return;\r
117         }\r
118 \r
119         // truncate the string at the last '\' char\r
120         while(Len > 0)\r
121         {\r
122                 --Len;\r
123                 if (ModuleName[Len] == '\\')\r
124                 {\r
125                         ModuleName[Len] = '\0';\r
126                         break;\r
127                 }\r
128         }\r
129         if (Len == 0)\r
130         {\r
131                 TRACE(_T("LoadRealLibrary() - Fail\n"));\r
132                 hTortoiseSVN = NIL;\r
133                 return;\r
134         }\r
135         lstrcat(ModuleName, _T("\\TortoiseSVN.dll"));\r
136 \r
137         TRACE(_T("LoadRealLibrary() - Load %s\n"), ModuleName);\r
138 \r
139         hTortoiseSVN = LoadLibraryEx(ModuleName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);\r
140         if (!hTortoiseSVN)\r
141         {\r
142                 TRACE(_T("LoadRealLibrary() - Fail\n"));\r
143                 hTortoiseSVN = NIL;\r
144                 return;\r
145         }\r
146 \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
152         {\r
153                 TRACE(_T("LoadRealLibrary() - Fail\n"));\r
154                 FreeLibrary(hTortoiseSVN);\r
155                 hTortoiseSVN = NIL;\r
156                 return;\r
157         }\r
158         pDllCanUnloadNow = (LPFNCANUNLOADNOW)GetProcAddress(hTortoiseSVN, CanUnloadNow);\r
159         if (pDllCanUnloadNow == NULL)\r
160         {\r
161                 TRACE(_T("LoadRealLibrary() - Fail\n"));\r
162                 FreeLibrary(hTortoiseSVN);\r
163                 hTortoiseSVN = NIL;\r
164                 return;\r
165         }\r
166 }\r
167 \r
168 static void UnloadRealLibrary(void)\r
169 {\r
170         if (!hTortoiseSVN)\r
171                 return;\r
172 \r
173         if (hTortoiseSVN != NIL)\r
174                 FreeLibrary(hTortoiseSVN);\r
175 \r
176         hTortoiseSVN = NULL;\r
177         pDllGetClassObject = NULL;\r
178         pDllCanUnloadNow = NULL;\r
179 }\r
180 \r
181 \r
182 BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved)\r
183 {\r
184 #ifdef _DEBUG\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
187         // it.\r
188 \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
192 \r
193         UNREFERENCED_PARAMETER(Reserved);\r
194 \r
195         if (pathLength >= 14)\r
196         {\r
197                 if ((lstrcmpi(&buf[pathLength-14], _T("\\ShellTest.exe"))) == 0)\r
198                 {\r
199                         bInShellTest = TRUE;\r
200                 }\r
201         }\r
202 \r
203         if (!IsDebuggerPresent() && !bInShellTest)\r
204         {\r
205                 TRACE(_T("In debug load preventer\n"));\r
206                 return FALSE;\r
207         }\r
208 #else\r
209         UNREFERENCED_PARAMETER(Reserved);\r
210 #endif\r
211 \r
212 \r
213         switch(Reason)\r
214         {\r
215         case DLL_PROCESS_ATTACH:\r
216                 hInst = hInstance;\r
217                 break;\r
218 \r
219                 //case DLL_THREAD_ATTACH:\r
220                 //  break;\r
221 \r
222                 //case DLL_THREAD_DETACH:\r
223                 //  break;\r
224 \r
225                 //case DLL_PROCESS_DETACH:\r
226                 //  break;\r
227         }\r
228 \r
229         return TRUE;\r
230 }\r
231 \r
232 \r
233 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)\r
234 {\r
235         TRACE(_T("DllGetClassObject() - Enter\n"));\r
236 \r
237         LoadRealLibrary();\r
238         if (!pDllGetClassObject)\r
239         {\r
240                 if (ppv)\r
241                         *ppv = NULL;\r
242                 else\r
243                         ppv = NULL;\r
244 \r
245                 TRACE(_T("DllGetClassObject() - Bypass\n"));\r
246                 return CLASS_E_CLASSNOTAVAILABLE;\r
247         }\r
248 \r
249         TRACE(_T("DllGetClassObject() - Forward\n"));\r
250         return pDllGetClassObject(rclsid, riid, ppv);\r
251 }\r
252 \r
253 STDAPI DllCanUnloadNow(void)\r
254 {\r
255         HRESULT Result;\r
256 \r
257         TRACE(_T("DllCanUnloadNow() - Enter\n"));\r
258 \r
259         if (pDllCanUnloadNow)\r
260         {\r
261                 TRACE(_T("DllCanUnloadNow() - Forward\n"));\r
262                 Result = pDllCanUnloadNow();\r
263                 if (Result != S_OK)\r
264                         return Result;\r
265         }\r
266 \r
267         TRACE(_T("DllCanUnloadNow() - Unload\n"));\r
268         UnloadRealLibrary();\r
269         return S_OK;\r
270 }\r
271 \r