ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

install.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2006-2007 Jacek Caban for CodeWeavers
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00017  */
00018 
00019 #include "config.h"
00020 
00021 #include <stdarg.h>
00022 #include <fcntl.h>
00023 #ifdef HAVE_UNISTD_H
00024 # include <unistd.h>
00025 #endif
00026 
00027 #define COBJMACROS
00028 #define NONAMELESSUNION
00029 #define NONAMELESSSTRUCT
00030 
00031 #include "windef.h"
00032 #include "winbase.h"
00033 #include "winuser.h"
00034 #include "winreg.h"
00035 #include "ole2.h"
00036 #include "commctrl.h"
00037 #include "advpub.h"
00038 #include "wininet.h"
00039 #include "shellapi.h"
00040 
00041 #include "wine/debug.h"
00042 #include "wine/unicode.h"
00043 #include "wine/library.h"
00044 
00045 #include "mshtml_private.h"
00046 #include "resource.h"
00047 
00048 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
00049 
00050 #ifdef __i386__
00051 #define GECKO_ARCH "x86"
00052 #else
00053 #define GECKO_ARCH ""
00054 #endif
00055 
00056 #define GECKO_FILE_NAME "wine_gecko-" GECKO_VERSION "-" GECKO_ARCH ".cab"
00057 
00058 static const WCHAR mshtml_keyW[] =
00059     {'S','o','f','t','w','a','r','e',
00060      '\\','W','i','n','e',
00061      '\\','M','S','H','T','M','L',0};
00062 
00063 static HWND install_dialog = NULL;
00064 static LPWSTR tmp_file_name = NULL;
00065 static HANDLE tmp_file = INVALID_HANDLE_VALUE;
00066 static LPWSTR url = NULL;
00067 
00068 static void clean_up(void)
00069 {
00070     if(tmp_file != INVALID_HANDLE_VALUE)
00071         CloseHandle(tmp_file);
00072 
00073     if(tmp_file_name) {
00074         DeleteFileW(tmp_file_name);
00075         heap_free(tmp_file_name);
00076         tmp_file_name = NULL;
00077     }
00078 
00079     if(tmp_file != INVALID_HANDLE_VALUE) {
00080         CloseHandle(tmp_file);
00081         tmp_file = INVALID_HANDLE_VALUE;
00082     }
00083 
00084     if(install_dialog)
00085         EndDialog(install_dialog, 0);
00086 }
00087 
00088 static void set_status(DWORD id)
00089 {
00090     HWND status = GetDlgItem(install_dialog, ID_DWL_STATUS);
00091     WCHAR buf[64];
00092 
00093     LoadStringW(hInst, id, buf, sizeof(buf)/sizeof(WCHAR));
00094     SendMessageW(status, WM_SETTEXT, 0, (LPARAM)buf);
00095 }
00096 
00097 static void set_registry(LPCSTR install_dir)
00098 {
00099     WCHAR mshtml_key[100];
00100     LPWSTR gecko_path;
00101     HKEY hkey;
00102     DWORD res, len;
00103 
00104     static const WCHAR wszGeckoPath[] = {'G','e','c','k','o','P','a','t','h',0};
00105     static const WCHAR wszWineGecko[] = {'w','i','n','e','_','g','e','c','k','o',0};
00106 
00107     memcpy(mshtml_key, mshtml_keyW, sizeof(mshtml_keyW));
00108     mshtml_key[sizeof(mshtml_keyW)/sizeof(WCHAR)-1] = '\\';
00109     MultiByteToWideChar(CP_ACP, 0, GECKO_VERSION, sizeof(GECKO_VERSION),
00110             mshtml_key+sizeof(mshtml_keyW)/sizeof(WCHAR),
00111             (sizeof(mshtml_key)-sizeof(mshtml_keyW))/sizeof(WCHAR));
00112 
00113     /* @@ Wine registry key: HKCU\Software\Wine\MSHTML<version> */
00114     res = RegCreateKeyW(HKEY_CURRENT_USER, mshtml_key, &hkey);
00115     if(res != ERROR_SUCCESS) {
00116         ERR("Faild to create MSHTML key: %d\n", res);
00117         return;
00118     }
00119 
00120     len = MultiByteToWideChar(CP_ACP, 0, install_dir, -1, NULL, 0)-1;
00121     gecko_path = heap_alloc((len+1)*sizeof(WCHAR)+sizeof(wszWineGecko));
00122     MultiByteToWideChar(CP_ACP, 0, install_dir, -1, gecko_path, len+1);
00123 
00124     if (len && gecko_path[len-1] != '\\')
00125         gecko_path[len++] = '\\';
00126 
00127     memcpy(gecko_path+len, wszWineGecko, sizeof(wszWineGecko));
00128 
00129     res = RegSetValueExW(hkey, wszGeckoPath, 0, REG_SZ, (LPVOID)gecko_path,
00130                        len*sizeof(WCHAR)+sizeof(wszWineGecko));
00131     heap_free(gecko_path);
00132     RegCloseKey(hkey);
00133     if(res != ERROR_SUCCESS)
00134         ERR("Failed to set GeckoPath value: %08x\n", res);
00135 }
00136 
00137 static BOOL install_cab(LPCWSTR file_name)
00138 {
00139     HMODULE advpack;
00140     char install_dir[MAX_PATH];
00141     HRESULT (WINAPI *pExtractFilesA)(LPCSTR,LPCSTR,DWORD,LPCSTR,LPVOID,DWORD);
00142     LPSTR file_name_a;
00143     DWORD res;
00144     HRESULT hres;
00145 
00146     static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0};
00147 
00148     TRACE("(%s)\n", debugstr_w(file_name));
00149 
00150     GetSystemDirectoryA(install_dir, sizeof(install_dir));
00151     strcat(install_dir, "\\gecko\\");
00152     res = CreateDirectoryA(install_dir, NULL);
00153     if(!res && GetLastError() != ERROR_ALREADY_EXISTS) {
00154         ERR("Could not create directory: %08u\n", GetLastError());
00155         return FALSE;
00156     }
00157 
00158     strcat(install_dir, GECKO_VERSION);
00159     res = CreateDirectoryA(install_dir, NULL);
00160     if(!res && GetLastError() != ERROR_ALREADY_EXISTS) {
00161         ERR("Could not create directory: %08u\n", GetLastError());
00162         return FALSE;
00163     }
00164 
00165     advpack = LoadLibraryW(wszAdvpack);
00166     pExtractFilesA = (void *)GetProcAddress(advpack, "ExtractFiles");
00167 
00168     /* FIXME: Use unicode version (not yet implemented) */
00169     file_name_a = heap_strdupWtoA(file_name);
00170     hres = pExtractFilesA(file_name_a, install_dir, 0, NULL, NULL, 0);
00171     FreeLibrary(advpack);
00172     heap_free(file_name_a);
00173     if(FAILED(hres)) {
00174         ERR("Could not extract package: %08x\n", hres);
00175         clean_up();
00176         return FALSE;
00177     }
00178 
00179     set_registry(install_dir);
00180     clean_up();
00181 
00182     return TRUE;
00183 }
00184 
00185 static BOOL install_from_unix_file(const char *file_name)
00186 {
00187     LPWSTR dos_file_name;
00188     int fd;
00189     BOOL ret;
00190 
00191     static WCHAR * (CDECL *wine_get_dos_file_name)(const char*);
00192     static const WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0};
00193 
00194     fd = open(file_name, O_RDONLY);
00195     if(fd == -1) {
00196         TRACE("%s not found\n", debugstr_a(file_name));
00197         return FALSE;
00198     }
00199 
00200     close(fd);
00201 
00202     if(!wine_get_dos_file_name)
00203         wine_get_dos_file_name = (void*)GetProcAddress(GetModuleHandleW(kernel32W), "wine_get_dos_file_name");
00204 
00205     if(wine_get_dos_file_name) { /* Wine UNIX mode */
00206     dos_file_name = wine_get_dos_file_name(file_name);
00207     if(!dos_file_name) {
00208         ERR("Could not get dos file name of %s\n", debugstr_a(file_name));
00209         return FALSE;
00210     }
00211     } else { /* Windows mode */
00212     UINT res;
00213     WARN("Could not get wine_get_dos_file_name function, calling install_cab directly.\n");
00214     res = MultiByteToWideChar( CP_ACP, 0, file_name, -1, 0, 0);
00215     dos_file_name = heap_alloc (res*sizeof(WCHAR));
00216     MultiByteToWideChar( CP_ACP, 0, file_name, -1, dos_file_name, res);
00217     }
00218 
00219     ret = install_cab(dos_file_name);
00220 
00221     heap_free(dos_file_name);
00222     return ret;
00223 }
00224 
00225 static BOOL install_from_registered_dir(void)
00226 {
00227     char *file_name;
00228     HKEY hkey;
00229     DWORD res, type, size = MAX_PATH;
00230     BOOL ret;
00231 
00232     /* @@ Wine registry key: HKCU\Software\Wine\MSHTML */
00233     res = RegOpenKeyW(HKEY_CURRENT_USER, mshtml_keyW, &hkey);
00234     if(res != ERROR_SUCCESS)
00235         return FALSE;
00236 
00237     file_name = heap_alloc(size+sizeof(GECKO_FILE_NAME));
00238     res = RegGetValueA(hkey, NULL, "GeckoCabDir", RRF_RT_ANY, &type, (PBYTE)file_name, &size);
00239     if(res == ERROR_MORE_DATA) {
00240         file_name = heap_realloc(file_name, size+sizeof(GECKO_FILE_NAME));
00241         res = RegGetValueA(hkey, NULL, "GeckoCabDir", RRF_RT_ANY, &type, (PBYTE)file_name, &size);
00242     }
00243     RegCloseKey(hkey);
00244     if(res != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ)) {
00245         heap_free(file_name);
00246         return FALSE;
00247     }
00248 
00249     strcat(file_name, GECKO_FILE_NAME);
00250 
00251     TRACE("Trying %s\n", debugstr_a(file_name));
00252 
00253     ret = install_from_unix_file(file_name);
00254 
00255     heap_free(file_name);
00256     return ret;
00257 }
00258 
00259 static BOOL install_from_default_dir(void)
00260 {
00261     const char *data_dir, *subdir;
00262     char *file_name;
00263     int len, len2;
00264     BOOL ret;
00265 
00266     if((data_dir = wine_get_data_dir()))
00267         subdir = "/gecko/";
00268     else if((data_dir = wine_get_build_dir()))
00269         subdir = "/../gecko/";
00270     else
00271         return FALSE;
00272 
00273     len = strlen(data_dir);
00274     len2 = strlen(subdir);
00275 
00276     file_name = heap_alloc(len+len2+sizeof(GECKO_FILE_NAME));
00277     memcpy(file_name, data_dir, len);
00278     memcpy(file_name+len, subdir, len2);
00279     memcpy(file_name+len+len2, GECKO_FILE_NAME, sizeof(GECKO_FILE_NAME));
00280 
00281     ret = install_from_unix_file(file_name);
00282 
00283     heap_free(file_name);
00284     return ret;
00285 }
00286 
00287 static HRESULT WINAPI InstallCallback_QueryInterface(IBindStatusCallback *iface,
00288                                                      REFIID riid, void **ppv)
00289 {
00290     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IBindStatusCallback, riid)) {
00291         *ppv = iface;
00292         return S_OK;
00293     }
00294 
00295     return E_INVALIDARG;
00296 }
00297 
00298 static ULONG WINAPI InstallCallback_AddRef(IBindStatusCallback *iface)
00299 {
00300     return 2;
00301 }
00302 
00303 static ULONG WINAPI InstallCallback_Release(IBindStatusCallback *iface)
00304 {
00305     return 1;
00306 }
00307 
00308 static HRESULT WINAPI InstallCallback_OnStartBinding(IBindStatusCallback *iface,
00309         DWORD dwReserved, IBinding *pib)
00310 {
00311     WCHAR tmp_dir[MAX_PATH];
00312 
00313     set_status(IDS_DOWNLOADING);
00314 
00315     GetTempPathW(sizeof(tmp_dir)/sizeof(WCHAR), tmp_dir);
00316 
00317     tmp_file_name = heap_alloc(MAX_PATH*sizeof(WCHAR));
00318     GetTempFileNameW(tmp_dir, NULL, 0, tmp_file_name);
00319 
00320     TRACE("creating temp file %s\n", debugstr_w(tmp_file_name));
00321 
00322     tmp_file = CreateFileW(tmp_file_name, GENERIC_WRITE, 0, NULL, 
00323                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
00324 
00325     if(tmp_file == INVALID_HANDLE_VALUE) {
00326         ERR("Could not create file: %d\n", GetLastError());
00327         clean_up();
00328         return E_FAIL;
00329     }
00330 
00331     return S_OK;
00332 }
00333 
00334 static HRESULT WINAPI InstallCallback_GetPriority(IBindStatusCallback *iface,
00335         LONG *pnPriority)
00336 {
00337     return E_NOTIMPL;
00338 }
00339 
00340 static HRESULT WINAPI InstallCallback_OnLowResource(IBindStatusCallback *iface,
00341        DWORD dwReserved)
00342 {
00343     return E_NOTIMPL;
00344 }
00345 
00346 static HRESULT WINAPI InstallCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
00347         ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
00348 {
00349     HWND progress = GetDlgItem(install_dialog, ID_DWL_PROGRESS);
00350 
00351     if(ulProgressMax)
00352         SendMessageW(progress, PBM_SETRANGE32, 0, ulProgressMax);
00353     if(ulProgress)
00354         SendMessageW(progress, PBM_SETPOS, ulProgress, 0);
00355 
00356     return S_OK;
00357 }
00358 
00359 static HRESULT WINAPI InstallCallback_OnStopBinding(IBindStatusCallback *iface,
00360         HRESULT hresult, LPCWSTR szError)
00361 {
00362     if(FAILED(hresult)) {
00363         ERR("Binding failed %08x\n", hresult);
00364         clean_up();
00365         return S_OK;
00366     }
00367 
00368     CloseHandle(tmp_file);
00369     tmp_file = INVALID_HANDLE_VALUE;
00370 
00371     set_status(IDS_INSTALLING);
00372 
00373     install_cab(tmp_file_name);
00374 
00375     return S_OK;
00376 }
00377 
00378 static HRESULT WINAPI InstallCallback_GetBindInfo(IBindStatusCallback *iface,
00379         DWORD* grfBINDF, BINDINFO* pbindinfo)
00380 {
00381     /* FIXME */
00382     *grfBINDF = 0;
00383     return S_OK;
00384 }
00385 
00386 static HRESULT WINAPI InstallCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
00387         DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
00388 {
00389     IStream *str = pstgmed->u.pstm;
00390     BYTE buf[1024];
00391     DWORD size;
00392     HRESULT hres;
00393 
00394     do {
00395         DWORD written;
00396 
00397         size = 0;
00398         hres = IStream_Read(str, buf, sizeof(buf), &size);
00399         if(size)
00400             WriteFile(tmp_file, buf, size, &written, NULL);
00401     }while(hres == S_OK);
00402 
00403     return S_OK;
00404 }
00405 
00406 static HRESULT WINAPI InstallCallback_OnObjectAvailable(IBindStatusCallback *iface,
00407         REFIID riid, IUnknown* punk)
00408 {
00409     ERR("\n");
00410     return E_NOTIMPL;
00411 }
00412 
00413 static const IBindStatusCallbackVtbl InstallCallbackVtbl = {
00414     InstallCallback_QueryInterface,
00415     InstallCallback_AddRef,
00416     InstallCallback_Release,
00417     InstallCallback_OnStartBinding,
00418     InstallCallback_GetPriority,
00419     InstallCallback_OnLowResource,
00420     InstallCallback_OnProgress,
00421     InstallCallback_OnStopBinding,
00422     InstallCallback_GetBindInfo,
00423     InstallCallback_OnDataAvailable,
00424     InstallCallback_OnObjectAvailable
00425 };
00426 
00427 static IBindStatusCallback InstallCallback = { &InstallCallbackVtbl };
00428 
00429 static LPWSTR get_url(void)
00430 {
00431     HKEY hkey;
00432     DWORD res, type;
00433     DWORD size = INTERNET_MAX_URL_LENGTH*sizeof(WCHAR);
00434     DWORD returned_size;
00435     LPWSTR url;
00436 
00437     static const WCHAR wszGeckoUrl[] = {'G','e','c','k','o','U','r','l',0};
00438     static const WCHAR httpW[] = {'h','t','t','p'};
00439     static const WCHAR arch_formatW[] = {'?','a','r','c','h','='};
00440     static const WCHAR v_formatW[] = {'&','v','='};
00441 
00442     /* @@ Wine registry key: HKCU\Software\Wine\MSHTML */
00443     res = RegOpenKeyW(HKEY_CURRENT_USER, mshtml_keyW, &hkey);
00444     if(res != ERROR_SUCCESS)
00445         return NULL;
00446 
00447     url = heap_alloc(size);
00448     returned_size = size;
00449 
00450     res = RegQueryValueExW(hkey, wszGeckoUrl, NULL, &type, (LPBYTE)url, &returned_size);
00451     RegCloseKey(hkey);
00452     if(res != ERROR_SUCCESS || type != REG_SZ) {
00453         heap_free(url);
00454         return NULL;
00455     }
00456 
00457     if(returned_size > sizeof(httpW) && !memcmp(url, httpW, sizeof(httpW))) {
00458         DWORD len;
00459 
00460         len = strlenW(url);
00461         memcpy(url+len, arch_formatW, sizeof(arch_formatW));
00462         len += sizeof(arch_formatW)/sizeof(WCHAR);
00463         len += MultiByteToWideChar(CP_ACP, 0, GECKO_ARCH, sizeof(GECKO_ARCH), url+len, size/sizeof(WCHAR)-len)-1;
00464         memcpy(url+len, v_formatW, sizeof(v_formatW));
00465         len += sizeof(v_formatW)/sizeof(WCHAR);
00466         MultiByteToWideChar(CP_ACP, 0, GECKO_VERSION, -1, url+len, size/sizeof(WCHAR)-len);
00467     }
00468 
00469     TRACE("Got URL %s\n", debugstr_w(url));
00470     return url;
00471 }
00472 
00473 static DWORD WINAPI download_proc(PVOID arg)
00474 {
00475     IMoniker *mon;
00476     IBindCtx *bctx;
00477     IStream *str = NULL;
00478     HRESULT hres;
00479 
00480     CreateURLMoniker(NULL, url, &mon);
00481     heap_free(url);
00482     url = NULL;
00483 
00484     CreateAsyncBindCtx(0, &InstallCallback, 0, &bctx);
00485 
00486     hres = IMoniker_BindToStorage(mon, bctx, NULL, &IID_IStream, (void**)&str);
00487     IBindCtx_Release(bctx);
00488     if(FAILED(hres)) {
00489         ERR("BindToStorage failed: %08x\n", hres);
00490         return 0;
00491     }
00492 
00493     if(str)
00494         IStream_Release(str);
00495 
00496     return 0;
00497 }
00498 
00499 static INT_PTR CALLBACK installer_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
00500 {
00501     switch(msg) {
00502     case WM_INITDIALOG:
00503         ShowWindow(GetDlgItem(hwnd, ID_DWL_PROGRESS), SW_HIDE);
00504         install_dialog = hwnd;
00505         return TRUE;
00506 
00507     case WM_COMMAND:
00508         switch(wParam) {
00509         case IDCANCEL:
00510             EndDialog(hwnd, 0);
00511             return FALSE;
00512 
00513         case ID_DWL_INSTALL:
00514             ShowWindow(GetDlgItem(hwnd, ID_DWL_PROGRESS), SW_SHOW);
00515             EnableWindow(GetDlgItem(hwnd, ID_DWL_INSTALL), 0);
00516             EnableWindow(GetDlgItem(hwnd, IDCANCEL), 0); /* FIXME */
00517             CreateThread(NULL, 0, download_proc, NULL, 0, NULL);
00518             return FALSE;
00519         }
00520     }
00521 
00522     return FALSE;
00523 }
00524 
00525 BOOL install_wine_gecko(BOOL silent)
00526 {
00527     HANDLE hsem;
00528 
00529     if(!*GECKO_ARCH)
00530         return FALSE;
00531 
00532     SetLastError(ERROR_SUCCESS);
00533     hsem = CreateSemaphoreA( NULL, 0, 1, "mshtml_install_semaphore");
00534 
00535     if(GetLastError() == ERROR_ALREADY_EXISTS) {
00536         WaitForSingleObject(hsem, INFINITE);
00537     }else {
00538         /*
00539          * Try to find Gecko .cab file in following order:
00540          * - directory stored in GeckoCabDir value of HKCU/Software/MSHTML key
00541          * - $datadir/gecko
00542          * - download from URL stored in GeckoUrl value of HKCU/Software/MSHTML key
00543          */
00544         if(!install_from_registered_dir()
00545            && !install_from_default_dir()
00546            && !silent && (url = get_url()))
00547             DialogBoxW(hInst, MAKEINTRESOURCEW(ID_DWL_DIALOG), 0, installer_proc);
00548     }
00549 
00550     ReleaseSemaphore(hsem, 1, NULL);
00551     CloseHandle(hsem);
00552 
00553     return TRUE;
00554 }

Generated on Fri May 25 2012 04:17:24 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.