[WinCairo][Clang] DLLLauncherMain.cpp: warning: unused function 'prependPath' and...
[WebKit-https.git] / Source / JavaScriptCore / shell / DLLLauncherMain.cpp
1 /*
2  * Copyright (C) 2012-2015 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 // This file contains code for a launcher executable for WebKit apps. When compiled into foo.exe, it
27 // will set PATH so that Apple Application Support DLLs can be found, then will load foo.dll and
28 // call its dllLauncherEntryPoint function, which should be declared like so:
29 //     extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpstCmdLine, int nCmdShow);
30 // If USE_CONSOLE_ENTRY_POINT is defined, this function will be called instead:
31 //     extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(int argc, const char* argv[]);
32
33 #include <shlwapi.h>
34 #include <string>
35 #include <vector>
36 #include <windows.h>
37
38 #if defined _M_IX86
39 #define PROCESSORARCHITECTURE "x86"
40 #elif defined _M_IA64
41 #define PROCESSORARCHITECTURE "ia64"
42 #elif defined _M_X64
43 #define PROCESSORARCHITECTURE "amd64"
44 #else
45 #define PROCESSORARCHITECTURE "*"
46 #endif
47
48 #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='" PROCESSORARCHITECTURE "' publicKeyToken='6595b64144ccf1df' language='*'\"")
49 #if defined(_MSC_VER) && (_MSC_VER >= 1600) && !defined(WIN_CAIRO)
50 #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.VC80.CRT' version='8.0.50727.6195' processorArchitecture='" PROCESSORARCHITECTURE "' publicKeyToken='1fc8b3b9a1e18e3b' language='*'\"")
51 #endif
52
53 static void enableTerminationOnHeapCorruption()
54 {
55     HEAP_INFORMATION_CLASS heapEnableTerminationOnCorruption = static_cast<HEAP_INFORMATION_CLASS>(1);
56     HeapSetInformation(0, heapEnableTerminationOnCorruption, 0, 0);
57 }
58
59 static std::wstring copyEnvironmentVariable(const std::wstring& variable)
60 {
61     DWORD length = ::GetEnvironmentVariableW(variable.c_str(), 0, 0);
62     if (!length)
63         return std::wstring();
64     std::vector<wchar_t> buffer(length);
65     if (!GetEnvironmentVariable(variable.c_str(), &buffer[0], buffer.size()) || !buffer[0])
66         return std::wstring();
67     return &buffer[0];
68 }
69
70 #if !defined(WIN_CAIRO)
71 static std::wstring getStringValue(HKEY key, const std::wstring& valueName)
72 {
73     DWORD type = 0;
74     DWORD bufferSize = 0;
75     if (::RegQueryValueExW(key, valueName.c_str(), 0, &type, 0, &bufferSize) != ERROR_SUCCESS || type != REG_SZ)
76         return std::wstring();
77
78     std::vector<wchar_t> buffer(bufferSize / sizeof(wchar_t));
79     if (::RegQueryValueExW(key, valueName.c_str(), 0, &type, reinterpret_cast<LPBYTE>(&buffer[0]), &bufferSize) != ERROR_SUCCESS)
80         return std::wstring();
81
82     return &buffer[0];
83 }
84
85 static std::wstring applePathFromRegistry(const std::wstring& key, const std::wstring& value)
86 {
87     HKEY applePathKey = 0;
88     if (::RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_READ, &applePathKey) != ERROR_SUCCESS)
89         return std::wstring();
90     std::wstring path = getStringValue(applePathKey, value);
91     ::RegCloseKey(applePathKey);
92     return path;
93 }
94
95 static std::wstring appleApplicationSupportDirectory()
96 {
97     return applePathFromRegistry(L"SOFTWARE\\Apple Inc.\\Apple Application Support", L"InstallDir");
98 }
99
100 static bool prependPath(const std::wstring& directoryToPrepend)
101 {
102     std::wstring pathVariable = L"PATH";
103     std::wstring oldPath = copyEnvironmentVariable(pathVariable);
104     std::wstring newPath = directoryToPrepend + L';' + oldPath;
105     return ::SetEnvironmentVariableW(pathVariable.c_str(), newPath.c_str());
106 }
107 #endif
108
109 static int fatalError(const std::wstring& programName, const std::wstring& message)
110 {
111     std::wstring caption = programName + L" can't open.";
112     ::MessageBoxW(0, message.c_str(), caption.c_str(), MB_ICONERROR);
113     return 1;
114 }
115
116 static bool directoryExists(const std::wstring& path)
117 {
118     DWORD attrib = ::GetFileAttributes(path.c_str());
119
120     return ((attrib != INVALID_FILE_ATTRIBUTES) && (attrib & FILE_ATTRIBUTE_DIRECTORY));
121 }
122
123 static bool modifyPath(const std::wstring& programName)
124 {
125 #ifdef WIN_CAIRO
126
127     std::wstring pathWinCairo = copyEnvironmentVariable(L"WEBKIT_LIBRARIES");
128     if (!directoryExists(pathWinCairo))
129         return true;
130 #if defined(_M_X64)
131     pathWinCairo += L"\\bin64";
132 #else
133     pathWinCairo += L"\\bin32";
134 #endif
135     if (!SetDllDirectory(pathWinCairo.c_str())) {
136         fatalError(programName, L"Failed to SetDllDirectory");
137         return false;
138     }
139     return true;
140
141 #else
142
143     const std::wstring& pathPrefix = appleApplicationSupportDirectory();
144
145     if (!directoryExists(pathPrefix)) {
146         fatalError(programName, L"Failed to determine path to AAS directory.");
147         return false;
148     }
149
150     if (prependPath(pathPrefix))
151         return true;
152
153     fatalError(programName, L"Failed to modify PATH environment variable.");
154     return false;
155 #endif
156 }
157
158 static std::wstring getLastErrorString(HRESULT hr)
159 {
160     static const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
161     static const size_t bufSize = 4096;
162
163     wchar_t errorMessage[bufSize];
164     DWORD len = ::FormatMessageW(kFlags, 0, hr, 0, errorMessage, bufSize, 0);
165     if (len >= bufSize)
166         len = bufSize - 1;
167
168     errorMessage[len] = 0;
169
170     return errorMessage;
171 }
172
173 #if USE_CONSOLE_ENTRY_POINT
174 int main(int argc, const char* argv[])
175 #else
176 int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpstrCmdLine, int nCmdShow)
177 #endif
178 {
179     enableTerminationOnHeapCorruption();
180
181     // Get the path of our executable.
182     wchar_t exePath[MAX_PATH];
183     if (!::GetModuleFileNameW(0, exePath, _countof(exePath)))
184         return fatalError(L"Unknown Program", L"Failed to determine name of executable: " + getLastErrorString(::GetLastError()));
185
186     ::PathRemoveExtensionW(exePath);
187
188     std::wstring programName = ::PathFindFileNameW(exePath);
189
190     if (!modifyPath(programName))
191         return 1;
192
193     // Load our corresponding DLL.
194     std::wstring dllName = programName + L"Lib.dll";
195     if (!::PathRemoveFileSpecW(exePath))
196         return fatalError(programName, L"::PathRemoveFileSpecW failed: " + getLastErrorString(::GetLastError()));
197     if (!::PathAppendW(exePath, dllName.c_str()))
198         return fatalError(programName, L"::PathAppendW failed: " + getLastErrorString(::GetLastError()));
199     HMODULE module = ::LoadLibraryW(exePath);
200     if (!module)
201         return fatalError(programName, L"::LoadLibraryW failed: \npath=" + std::wstring(exePath) + L"\n" + getLastErrorString(::GetLastError()));
202
203 #if USE_CONSOLE_ENTRY_POINT
204     typedef int (WINAPI*EntryPoint)(int, const char*[]);
205 #if defined _M_AMD64 || defined _WIN64
206     const char* entryPointName = "dllLauncherEntryPoint";
207 #else
208     const char* entryPointName = "_dllLauncherEntryPoint@8";
209 #endif
210 #else
211     typedef int (WINAPI*EntryPoint)(HINSTANCE, HINSTANCE, LPWSTR, int);
212 #if defined _M_AMD64 || defined _WIN64
213     const char* entryPointName = "dllLauncherEntryPoint";
214 #else
215     const char* entryPointName = "_dllLauncherEntryPoint@16";
216 #endif
217 #endif
218
219     EntryPoint entryPoint = reinterpret_cast<EntryPoint>(::GetProcAddress(module, entryPointName));
220     if (!entryPoint)
221         return fatalError(programName, L"Failed to find dllLauncherEntryPoint function: " + getLastErrorString(::GetLastError()));
222
223 #if USE_CONSOLE_ENTRY_POINT
224     return entryPoint(argc, argv);
225 #else
226     return entryPoint(hInstance, hPrevInstance, lpstrCmdLine, nCmdShow);
227 #endif
228 }