2007-12-16 Dimitri Glazkov <dimitri@glazkov.com>
[WebKit-https.git] / WebKitTools / FindSafari / FindSafari.cpp
1 /*
2  * Copyright (C) 2007 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include <shlwapi.h>
30 #include <stdio.h>
31 #include <tchar.h>
32 #include <windows.h>
33
34 #define LOG(header, ...) \
35     do { \
36         _ftprintf(stderr, header); \
37         _ftprintf(stderr, __VA_ARGS__); \
38     } while (0)
39 #define LOG_WARNING(...) LOG(TEXT("WARNING: "), __VA_ARGS__)
40 #define LOG_ERROR(...) LOG(TEXT("ERROR: "), __VA_ARGS__)
41
42 static TCHAR* getStringValue(HKEY key, LPCTSTR valueName)
43 {
44     DWORD type = 0;
45     DWORD bufferSize = 0;
46     if (RegQueryValueEx(key, valueName, 0, &type, 0, &bufferSize) != ERROR_SUCCESS || type != REG_SZ)
47         return 0;
48
49     TCHAR* buffer = (TCHAR*)malloc(bufferSize);
50     if (RegQueryValueEx(key, 0, 0, &type, reinterpret_cast<LPBYTE>(buffer), &bufferSize) != ERROR_SUCCESS) {
51         free(buffer);
52         return 0;
53     }
54
55     return buffer;
56 }
57
58 static LPOLESTR getWebViewCLSID()
59 {
60     LPCTSTR webViewProgID = TEXT("WebKit.WebView");
61
62     CLSID clsid = CLSID_NULL;
63     HRESULT hr = CLSIDFromProgID(webViewProgID, &clsid);
64     if (FAILED(hr)) {
65         LOG_WARNING(TEXT("Failed to get CLSID for %s\n"), webViewProgID);
66         return 0;
67     }
68
69     LPOLESTR clsidString = 0;
70     if (FAILED(StringFromCLSID(clsid, &clsidString))) {
71         LOG_WARNING(TEXT("Failed to get string representation of CLSID for WebView\n"));
72         return 0;
73     }
74
75     return clsidString;
76 }
77
78 static TCHAR* getInstalledWebKitDirectory()
79 {
80     LPCTSTR keyPrefix = TEXT("SOFTWARE\\Classes\\CLSID\\");
81     LPCTSTR keySuffix = TEXT("\\InprocServer32");
82
83     LPOLESTR clsid = getWebViewCLSID();
84     if (!clsid)
85         return 0;
86
87     size_t keyBufferLength = _tcslen(keyPrefix) + _tcslen(clsid) + _tcslen(keySuffix) + 1;
88     TCHAR* keyString = (TCHAR*)malloc(keyBufferLength * sizeof(TCHAR));
89
90     int ret = _sntprintf_s(keyString, keyBufferLength, keyBufferLength - 1, TEXT("%s%s%s"), keyPrefix, clsid, keySuffix);
91     CoTaskMemFree(clsid);
92     if (ret == -1) {
93         LOG_WARNING(TEXT("Failed to construct InprocServer32 key\n"));
94         return 0;
95     }
96
97     HKEY serverKey = 0;
98     LONG error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyString, 0, KEY_READ, &serverKey);
99     free(keyString);
100     if (error != ERROR_SUCCESS) {
101         LOG_WARNING(TEXT("Failed to open registry key %s\n"), keyString);
102         return 0;
103     }
104
105     TCHAR* webKitPath = getStringValue(serverKey, 0);
106     RegCloseKey(serverKey);
107     if (!webKitPath) {
108         LOG_WARNING(TEXT("Couldn't retrieve value for registry key %s\n"), keyString);
109         return 0;
110     }
111
112     TCHAR* startOfFileName = PathFindFileName(webKitPath);
113     if (startOfFileName == webKitPath) {
114         LOG_WARNING(TEXT("Couldn't find filename from path %s\n"), webKitPath);
115         free(webKitPath);
116         return 0;
117     }
118
119     *startOfFileName = '\0';
120     return webKitPath;
121 }
122
123 int _tmain(int argc, TCHAR* argv[])
124 {
125     TCHAR* path = getInstalledWebKitDirectory();
126     if (!path) {
127         LOG_ERROR(TEXT("Couldn't determine installed Safari path\n"));
128         return 1;
129     }
130
131     bool printLauncher = false;
132     bool printEnvironment = false;
133     bool debugger = false;
134
135     for (int i = 1; i < argc; ++i) {
136         if (!_tcscmp(argv[i], TEXT("/printSafariLauncher"))) {
137             printLauncher = true;
138             continue;
139         }
140         if (!_tcscmp(argv[i], TEXT("/printSafariEnvironment"))) {
141             printEnvironment = true;
142             continue;
143         }
144         if (!_tcscmp(argv[i], TEXT("/debugger"))) {
145             debugger = true;
146             continue;
147         }
148     }
149
150     // printLauncher is inclusive of printEnvironment, so do not
151     // leave both enabled:
152     if (printLauncher && printEnvironment)
153         printEnvironment = false;
154
155     if (!printLauncher && !printEnvironment) {
156         _tprintf(TEXT("%s\n"), path);
157         free(path);
158         return 0;
159     }
160
161     LPCTSTR lines[] = {
162         TEXT("@echo off"),
163         TEXT("mkdir 2>NUL \"%%TMP%%\\WebKitNightly\\Safari.resources\""),
164         TEXT("xcopy /y /i /d \"%sSafari.exe\" \"%%TMP%%\\WebKitNightly\""),
165         TEXT("xcopy /y /i /d /e \"%sSafari.resources\" \"%%TMP%%\\WebKitNightly\\Safari.resources\""),
166         TEXT("set PATH=%%CD%%;%s;%%PATH%%"),
167     };
168
169     LPCTSTR command = TEXT("\"%TMP%\\WebKitNightly\\Safari.exe\" /customWebKit");
170
171     LPCTSTR launchLines[] = {
172         TEXT("%s"),
173     };
174
175     LPCTSTR debuggerLines[] = {
176         TEXT("if exist \"%%DevEnvDir%%\\VCExpress.exe\" ("),
177         TEXT("\"%%DevEnvDir%%\\VCExpress.exe\" /debugExe %s"),
178         TEXT(") else ("),
179         TEXT("\"%%DevEnvDir%%\\devenv.exe\" /debugExe %s"),
180         TEXT(")"),
181     };
182
183     for (int i = 0; i < ARRAYSIZE(lines); ++i) {
184         _tprintf(lines[i], path);
185         _tprintf(TEXT("\n"));
186     }
187
188     LPCTSTR* endLines = debugger ? debuggerLines : launchLines;
189
190     // Don't print launch command if we just want the environment set up...
191     if (!printEnvironment) {
192        for (unsigned i = 0; i < (debugger ? ARRAYSIZE(debuggerLines) : ARRAYSIZE(launchLines)); ++i) {
193            _tprintf(endLines[i], command);
194            _tprintf(TEXT("\n"));
195        }
196     }
197
198     free(path);
199     return 0;
200 }