Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeninstall.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
1.7.6.1
|