webengine/osswebengine/WebKit/win/WebKitDLL.cpp
changeset 0 dd21522fd290
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebKit/win/WebKitDLL.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "WebKitDLL.h"
+
+#include "IWebURLResponse.h"
+#include "ProgIDMacros.h"
+#include "WebKit.h"
+#include "WebKitClassFactory.h"
+#include "resource.h"
+#pragma warning( push, 0 )
+#include <WebCore/COMPtr.h>
+#include <WebCore/IconDatabase.h>
+#include <WebCore/Page.h>
+#include <WebCore/SharedBuffer.h>
+#include <WebCore/Widget.h>
+#include <wtf/Vector.h>
+#pragma warning(pop)
+#include <tchar.h>
+#include <olectl.h>
+
+ULONG gLockCount;
+ULONG gClassCount;
+HINSTANCE gInstance;
+
+#define FOR_EACH_CLASS(macro) \
+    macro(CFDictionaryPropertyBag) \
+    macro(WebCache) \
+    macro(WebDebugProgram) \
+    macro(WebDownload) \
+    macro(WebError) \
+    macro(WebHistory) \
+    macro(WebHistoryItem) \
+    macro(WebIconDatabase) \
+    macro(WebJavaScriptCollector) \
+    macro(WebKitStatistics) \
+    macro(WebMutableURLRequest) \
+    macro(WebNotificationCenter) \
+    macro(WebPreferences) \
+    macro(WebScrollBar) \
+    macro(WebURLCredential) \
+    macro(WebURLProtectionSpace) \
+    macro(WebURLRequest) \
+    macro(WebURLResponse) \
+    macro(WebView)
+
+#define CLSID_FOR_CLASS(cls) CLSID_##cls,
+
+static CLSID gRegCLSIDs[] = {
+    FOR_EACH_CLASS(CLSID_FOR_CLASS)
+};
+
+void shutDownWebKit()
+{
+    WebCore::iconDatabase()->close();
+}
+
+STDAPI_(BOOL) DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID /*lpReserved*/)
+{
+    switch (ul_reason_for_call) {
+        case DLL_PROCESS_ATTACH:
+            gLockCount = gClassCount = 0;
+            gInstance = hModule;
+            WebCore::Page::setInstanceHandle(hModule);
+            return TRUE;
+
+        case DLL_PROCESS_DETACH:
+            shutDownWebKit();
+            break;
+
+        case DLL_THREAD_ATTACH:
+        case DLL_THREAD_DETACH:
+            break;
+    }
+    return FALSE;
+}
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
+{
+    bool found = false;
+    for (int i = 0; i < ARRAYSIZE(gRegCLSIDs); i++) {
+        if (IsEqualGUID(rclsid, gRegCLSIDs[i])) {
+            found = true;
+            break;
+        }
+    }
+    if (!found)
+        return E_FAIL;
+
+    if (!IsEqualGUID(riid, IID_IUnknown) && !IsEqualGUID(riid, IID_IClassFactory))
+        return E_NOINTERFACE;
+
+    WebKitClassFactory* factory = new WebKitClassFactory(rclsid);
+    *ppv = reinterpret_cast<LPVOID>(factory);
+    if (!factory)
+        return E_OUTOFMEMORY;
+
+    factory->AddRef();
+    return S_OK;
+}
+
+STDAPI DllCanUnloadNow(void)
+{
+    if (!gClassCount && !gLockCount)
+        return S_OK;
+    
+    return S_FALSE;
+}
+
+#if __BUILDBOT__
+#define VERSION_INDEPENDENT_PROGID(className) VERSION_INDEPENDENT_PRODUCTION_PROGID(className)
+#else
+#define VERSION_INDEPENDENT_PROGID(className) VERSION_INDEPENDENT_OPENSOURCE_PROGID(className)
+#endif
+#define CURRENT_VERSIONED_PROGID(className) VERSIONED_PROGID(VERSION_INDEPENDENT_PROGID(className), CURRENT_PROGID_VERSION)
+#define VERSIONED_303_PROGID(className) VERSIONED_PROGID(VERSION_INDEPENDENT_PROGID(className), 3)
+
+// FIXME: The last line of this macro only here for the benefit of Safari 3.0.3. Once a newer version
+// is released, the last line should be removed and gSlotsPerEntry should be decremented by 1.
+//key                                                                                       value name              value }
+#define KEYS_FOR_CLASS(cls) \
+{ TEXT("CLSID\\{########-####-####-####-############}"),                                    0,                      TEXT(#cls) }, \
+{ TEXT("CLSID\\{########-####-####-####-############}\\InprocServer32"),                    0,                      (LPCTSTR)-1 }, \
+{ TEXT("CLSID\\{########-####-####-####-############}\\InprocServer32"),                    TEXT("ThreadingModel"), TEXT("Apartment") }, \
+{ TEXT("CLSID\\{########-####-####-####-############}\\ProgID"),                            0,                      CURRENT_VERSIONED_PROGID(cls) }, \
+{ CURRENT_VERSIONED_PROGID(cls),                                                            0,                      TEXT(#cls) }, \
+{ CURRENT_VERSIONED_PROGID(cls) TEXT("\\CLSID"),                                            0,                      TEXT("{########-####-####-####-############}") }, \
+{ TEXT("CLSID\\{########-####-####-####-############}\\VersionIndependentProgID"),          0,                      VERSION_INDEPENDENT_PROGID(cls) }, \
+{ VERSION_INDEPENDENT_PROGID(cls),                                                          0,                      TEXT(#cls) }, \
+{ VERSION_INDEPENDENT_PROGID(cls) TEXT("\\CLSID"),                                          0,                      TEXT("{########-####-####-####-############}") }, \
+{ VERSION_INDEPENDENT_PROGID(cls) TEXT("\\CurVer"),                                         0,                      STRINGIFIED_VERSION(CURRENT_PROGID_VERSION) }, \
+{ VERSIONED_303_PROGID(cls),                                                                0,                      TEXT(#cls) }, \
+{ VERSIONED_303_PROGID(cls) TEXT("\\CLSID"),                                                0,                      TEXT("{########-####-####-####-############}") }, \
+// end of macro
+
+static const int gSlotsPerEntry = 12;
+static LPCTSTR gRegTable[][3] = {
+    FOR_EACH_CLASS(KEYS_FOR_CLASS)
+};
+
+static void substituteGUID(LPTSTR str, const UUID* guid)
+{
+    if (!guid || !str)
+        return;
+
+    TCHAR uuidString[40];
+    _stprintf_s(uuidString, ARRAYSIZE(uuidString), TEXT("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"), guid->Data1, guid->Data2, guid->Data3,
+        guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
+
+    LPCTSTR guidPattern = TEXT("########-####-####-####-############");
+    size_t patternLength = _tcslen(guidPattern);
+    size_t strLength = _tcslen(str);
+    LPTSTR guidSubStr = str;
+    while (strLength) {
+        guidSubStr = _tcsstr(guidSubStr, guidPattern);
+        if (!guidSubStr)
+            break;
+        _tcsncpy(guidSubStr, uuidString, patternLength);
+        guidSubStr += patternLength;
+        strLength -= (guidSubStr - str);
+    }
+}
+
+STDAPI DllUnregisterServer(void)
+{
+    HRESULT hr = S_OK;
+    HKEY userClasses;
+
+#if __BUILDBOT__
+    UnRegisterTypeLib(LIBID_WebKit, 3, 0, 0, SYS_WIN32);
+#else
+    UnRegisterTypeLib(LIBID_OpenSourceWebKit, 3, 0, 0, SYS_WIN32);
+#endif
+
+    if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\\CLASSES"), 0, KEY_WRITE, &userClasses) != ERROR_SUCCESS)
+        userClasses = 0;
+
+    int nEntries = ARRAYSIZE(gRegTable);
+    for (int i = nEntries - 1; i >= 0; i--) {
+        LPTSTR pszKeyName = _tcsdup(gRegTable[i][0]);
+        if (pszKeyName) {
+            substituteGUID(pszKeyName, &gRegCLSIDs[i/gSlotsPerEntry]);
+            RegDeleteKey(HKEY_CLASSES_ROOT, pszKeyName);
+            if (userClasses)
+                RegDeleteKey(userClasses, pszKeyName);
+            free(pszKeyName);
+        } else
+            hr = E_OUTOFMEMORY;
+    }
+
+    if (userClasses)
+        RegCloseKey(userClasses);
+    return hr;
+}
+
+STDAPI DllRegisterServer(void)
+{
+    HRESULT hr = S_OK;
+
+    // look up server's file name
+    TCHAR szFileName[MAX_PATH];
+    GetModuleFileName(gInstance, szFileName, MAX_PATH);
+
+    COMPtr<ITypeLib> typeLib;
+    LoadTypeLibEx(szFileName, REGKIND_REGISTER, &typeLib);
+
+    HKEY userClasses;
+    if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\\CLASSES"), 0, KEY_WRITE, &userClasses) != ERROR_SUCCESS)
+        userClasses = 0;
+
+    // register entries from table
+    int nEntries = ARRAYSIZE(gRegTable);
+    for (int i = 0; SUCCEEDED(hr) && i < nEntries; i++) {
+        LPTSTR pszKeyName   = _tcsdup(gRegTable[i][0]);
+        LPTSTR pszValueName = gRegTable[i][1] ? _tcsdup(gRegTable[i][1]) : 0;
+        LPTSTR allocatedValue   = (gRegTable[i][2] != (LPTSTR)-1) ? _tcsdup(gRegTable[i][2]) : (LPTSTR)-1;
+        LPTSTR pszValue     = allocatedValue;
+
+        if (pszKeyName && pszValue) {
+
+            int clsidIndex = i/gSlotsPerEntry;
+            substituteGUID(pszKeyName, &gRegCLSIDs[clsidIndex]);
+            substituteGUID(pszValueName, &gRegCLSIDs[clsidIndex]);
+
+            // map rogue value to module file name
+            if (pszValue == (LPTSTR)-1)
+                pszValue = szFileName;
+            else
+                substituteGUID(pszValue, &gRegCLSIDs[clsidIndex]);
+
+            // create the key
+            HKEY hkey;
+            LONG err = RegCreateKey(HKEY_CLASSES_ROOT, pszKeyName, &hkey);
+            if (err != ERROR_SUCCESS && userClasses)
+                err = RegCreateKey(userClasses, pszKeyName, &hkey);
+            if (err == ERROR_SUCCESS) {
+                // set the value
+                err = RegSetValueEx(hkey, pszValueName, 0, REG_SZ, (const BYTE*)pszValue, (DWORD) sizeof(pszValue[0])*(_tcslen(pszValue) + 1));
+                RegCloseKey(hkey);
+            }
+        }
+        if (pszKeyName)
+            free(pszKeyName);
+        if (pszValueName)
+            free(pszValueName);
+        if (allocatedValue && allocatedValue != (LPTSTR)-1)
+            free(allocatedValue);
+    }
+
+    if (userClasses)
+        RegCloseKey(userClasses);
+
+    return hr;
+}
+
+STDAPI RunAsLocalServer(void)
+{
+    DWORD reg;
+    COMPtr<IUnknown> classFactory;
+    DllGetClassObject(CLSID_WebDebugProgram, IID_IUnknown, (void**)&classFactory);
+    CoRegisterClassObject(CLSID_WebDebugProgram, classFactory.get(), CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &reg);
+    return 0;
+}
+
+//FIXME: We should consider moving this to a new file for cross-project functionality
+PassRefPtr<WebCore::SharedBuffer> loadResourceIntoBuffer(const char* name)
+{
+    int idr;
+    // temporary hack to get resource id
+    if (!strcmp(name, "textAreaResizeCorner"))
+        idr = IDR_RESIZE_CORNER;
+    else if (!strcmp(name, "missingImage"))
+        idr = IDR_MISSING_IMAGE;
+    else if (!strcmp(name, "urlIcon"))
+        idr = IDR_URL_ICON;
+    else if (!strcmp(name, "nullPlugin"))
+        idr = IDR_NULL_PLUGIN;
+    else if (!strcmp(name, "zoomInCursor"))
+        idr = IDR_ZOOM_IN_CURSOR;
+    else if (!strcmp(name, "zoomOutCursor"))
+        idr = IDR_ZOOM_OUT_CURSOR;
+    else if (!strcmp(name, "verticalTextCursor"))
+        idr = IDR_VERTICAL_TEXT_CURSOR;
+    else
+        return 0;
+
+    HRSRC resInfo = FindResource(gInstance, MAKEINTRESOURCE(idr), L"PNG");
+    if (!resInfo)
+        return 0;
+    HANDLE res = LoadResource(gInstance, resInfo);
+    if (!res)
+        return 0;
+    void* resource = LockResource(res);
+    if (!resource)
+        return 0;
+    int size = SizeofResource(gInstance, resInfo);
+
+    return new WebCore::SharedBuffer(reinterpret_cast<const char*>(resource), size);
+}