Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeninstall.c
Go to the documentation of this file.
00001 /* 00002 * Advpack install functions 00003 * 00004 * Copyright 2006 James Hawkins 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include <stdarg.h> 00022 #include <stdlib.h> 00023 00024 #include "windef.h" 00025 #include "winbase.h" 00026 #include "winuser.h" 00027 #include "winreg.h" 00028 #include "winternl.h" 00029 #include "winnls.h" 00030 #include "setupapi.h" 00031 #include "advpub.h" 00032 #include "ole2.h" 00033 #include "wine/debug.h" 00034 #include "wine/unicode.h" 00035 #include "advpack_private.h" 00036 00037 WINE_DEFAULT_DEBUG_CHANNEL(advpack); 00038 00039 #define SPAPI_ERROR 0xE0000000L 00040 #define SPAPI_PREFIX 0x800F0000L 00041 #define SPAPI_MASK 0xFFFFL 00042 #define HRESULT_FROM_SPAPI(x) ((HRESULT)((x & SPAPI_MASK) | SPAPI_PREFIX)) 00043 00044 #define ADV_HRESULT(x) ((x & SPAPI_ERROR) ? HRESULT_FROM_SPAPI(x) : HRESULT_FROM_WIN32(x)) 00045 00046 #define ADV_SUCCESS 0 00047 #define ADV_FAILURE 1 00048 00049 /* contains information about a specific install instance */ 00050 typedef struct _ADVInfo 00051 { 00052 HINF hinf; 00053 LPWSTR inf_path; 00054 LPWSTR inf_filename; 00055 LPWSTR install_sec; 00056 LPWSTR working_dir; 00057 DWORD flags; 00058 BOOL need_reboot; 00059 } ADVInfo; 00060 00061 typedef HRESULT (*iterate_fields_func)(HINF hinf, PCWSTR field, const void *arg); 00062 00063 /* Advanced INF commands */ 00064 static const WCHAR CheckAdminRights[] = { 00065 'C','h','e','c','k','A','d','m','i','n','R','i','g','h','t','s',0 00066 }; 00067 static const WCHAR DelDirs[] = {'D','e','l','D','i','r','s',0}; 00068 static const WCHAR PerUserInstall[] = {'P','e','r','U','s','e','r','I','n','s','t','a','l','l',0}; 00069 static const WCHAR RegisterOCXs[] = {'R','e','g','i','s','t','e','r','O','C','X','s',0}; 00070 static const WCHAR RunPreSetupCommands[] = { 00071 'R','u','n','P','r','e','S','e','t','u','p','C','o','m','m','a','n','d','s',0 00072 }; 00073 static const WCHAR RunPostSetupCommands[] = { 00074 'R','u','n','P','o','s','t','S','e','t','u','p','C','o','m','m','a','n','d','s',0 00075 }; 00076 00077 /* Advanced INF callbacks */ 00078 static HRESULT del_dirs_callback(HINF hinf, PCWSTR field, const void *arg) 00079 { 00080 INFCONTEXT context; 00081 HRESULT hr = S_OK; 00082 DWORD size; 00083 00084 BOOL ok = SetupFindFirstLineW(hinf, field, NULL, &context); 00085 00086 for (; ok; ok = SetupFindNextLine(&context, &context)) 00087 { 00088 WCHAR directory[MAX_INF_STRING_LENGTH]; 00089 00090 if (!SetupGetLineTextW(&context, NULL, NULL, NULL, directory, 00091 MAX_INF_STRING_LENGTH, &size)) 00092 continue; 00093 00094 if (DelNodeW(directory, ADN_DEL_IF_EMPTY) != S_OK) 00095 hr = E_FAIL; 00096 } 00097 00098 return hr; 00099 } 00100 00101 static HRESULT per_user_install_callback(HINF hinf, PCWSTR field, const void *arg) 00102 { 00103 PERUSERSECTIONW per_user; 00104 INFCONTEXT context; 00105 DWORD size; 00106 00107 static const WCHAR disp_name[] = {'D','i','s','p','l','a','y','N','a','m','e',0}; 00108 static const WCHAR version[] = {'V','e','r','s','i','o','n',0}; 00109 static const WCHAR is_installed[] = {'I','s','I','n','s','t','a','l','l','e','d',0}; 00110 static const WCHAR comp_id[] = {'C','o','m','p','o','n','e','n','t','I','D',0}; 00111 static const WCHAR guid[] = {'G','U','I','D',0}; 00112 static const WCHAR locale[] = {'L','o','c','a','l','e',0}; 00113 static const WCHAR stub_path[] = {'S','t','u','b','P','a','t','h',0}; 00114 00115 per_user.bRollback = FALSE; 00116 per_user.dwIsInstalled = 0; 00117 00118 SetupGetLineTextW(NULL, hinf, field, disp_name, per_user.szDispName, 00119 sizeof(per_user.szDispName) / sizeof(WCHAR), &size); 00120 00121 SetupGetLineTextW(NULL, hinf, field, version, per_user.szVersion, 00122 sizeof(per_user.szVersion) / sizeof(WCHAR), &size); 00123 00124 if (SetupFindFirstLineW(hinf, field, is_installed, &context)) 00125 { 00126 SetupGetIntField(&context, 1, (PINT)&per_user.dwIsInstalled); 00127 } 00128 00129 SetupGetLineTextW(NULL, hinf, field, comp_id, per_user.szCompID, 00130 sizeof(per_user.szCompID) / sizeof(WCHAR), &size); 00131 00132 SetupGetLineTextW(NULL, hinf, field, guid, per_user.szGUID, 00133 sizeof(per_user.szGUID) / sizeof(WCHAR), &size); 00134 00135 SetupGetLineTextW(NULL, hinf, field, locale, per_user.szLocale, 00136 sizeof(per_user.szLocale) / sizeof(WCHAR), &size); 00137 00138 SetupGetLineTextW(NULL, hinf, field, stub_path, per_user.szStub, 00139 sizeof(per_user.szStub) / sizeof(WCHAR), &size); 00140 00141 return SetPerUserSecValuesW(&per_user); 00142 } 00143 00144 static HRESULT register_ocxs_callback(HINF hinf, PCWSTR field, const void *arg) 00145 { 00146 HMODULE hm; 00147 INFCONTEXT context; 00148 HRESULT hr = S_OK; 00149 00150 BOOL ok = SetupFindFirstLineW(hinf, field, NULL, &context); 00151 00152 for (; ok; ok = SetupFindNextLine(&context, &context)) 00153 { 00154 WCHAR buffer[MAX_INF_STRING_LENGTH]; 00155 00156 /* get OCX filename */ 00157 if (!SetupGetStringFieldW(&context, 1, buffer, 00158 sizeof(buffer) / sizeof(WCHAR), NULL)) 00159 continue; 00160 00161 hm = LoadLibraryExW(buffer, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); 00162 if (hm) 00163 { 00164 if (do_ocx_reg(hm, TRUE, NULL, NULL) != S_OK) 00165 hr = E_FAIL; 00166 00167 FreeLibrary(hm); 00168 } 00169 else 00170 hr = E_FAIL; 00171 00172 if (FAILED(hr)) 00173 { 00174 /* FIXME: display a message box */ 00175 break; 00176 } 00177 } 00178 00179 return hr; 00180 } 00181 00182 static HRESULT run_setup_commands_callback(HINF hinf, PCWSTR field, const void *arg) 00183 { 00184 const ADVInfo *info = (const ADVInfo *)arg; 00185 INFCONTEXT context; 00186 HRESULT hr = S_OK; 00187 DWORD size; 00188 00189 BOOL ok = SetupFindFirstLineW(hinf, field, NULL, &context); 00190 00191 for (; ok; ok = SetupFindNextLine(&context, &context)) 00192 { 00193 WCHAR buffer[MAX_INF_STRING_LENGTH]; 00194 00195 if (!SetupGetLineTextW(&context, NULL, NULL, NULL, buffer, 00196 MAX_INF_STRING_LENGTH, &size)) 00197 continue; 00198 00199 if (launch_exe(buffer, info->working_dir, NULL) != S_OK) 00200 hr = E_FAIL; 00201 } 00202 00203 return hr; 00204 } 00205 00206 /* sequentially returns pointers to parameters in a parameter list 00207 * returns NULL if the parameter is empty, e.g. one,,three */ 00208 LPWSTR get_parameter(LPWSTR *params, WCHAR separator) 00209 { 00210 LPWSTR token = *params; 00211 00212 if (!*params) 00213 return NULL; 00214 00215 *params = strchrW(*params, separator); 00216 if (*params) 00217 *(*params)++ = '\0'; 00218 00219 if (!*token) 00220 return NULL; 00221 00222 return token; 00223 } 00224 00225 static BOOL is_full_path(LPCWSTR path) 00226 { 00227 const int MIN_PATH_LEN = 3; 00228 00229 if (!path || lstrlenW(path) < MIN_PATH_LEN) 00230 return FALSE; 00231 00232 if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\')) 00233 return TRUE; 00234 00235 return FALSE; 00236 } 00237 00238 /* retrieves the contents of a field, dynamically growing the buffer if necessary */ 00239 static WCHAR *get_field_string(INFCONTEXT *context, DWORD index, WCHAR *buffer, 00240 const WCHAR *static_buffer, DWORD *size) 00241 { 00242 DWORD required; 00243 00244 if (SetupGetStringFieldW(context, index, buffer, *size, &required)) return buffer; 00245 00246 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 00247 { 00248 /* now grow the buffer */ 00249 if (buffer != static_buffer) HeapFree(GetProcessHeap(), 0, buffer); 00250 if (!(buffer = HeapAlloc(GetProcessHeap(), 0, required*sizeof(WCHAR)))) return NULL; 00251 *size = required; 00252 if (SetupGetStringFieldW(context, index, buffer, *size, &required)) return buffer; 00253 } 00254 00255 if (buffer != static_buffer) HeapFree(GetProcessHeap(), 0, buffer); 00256 return NULL; 00257 } 00258 00259 /* iterates over all fields of a certain key of a certain section */ 00260 static HRESULT iterate_section_fields(HINF hinf, PCWSTR section, PCWSTR key, 00261 iterate_fields_func callback, void *arg) 00262 { 00263 WCHAR static_buffer[200]; 00264 WCHAR *buffer = static_buffer; 00265 DWORD size = sizeof(static_buffer) / sizeof(WCHAR); 00266 INFCONTEXT context; 00267 HRESULT hr = E_FAIL; 00268 00269 BOOL ok = SetupFindFirstLineW(hinf, section, key, &context); 00270 while (ok) 00271 { 00272 UINT i, count = SetupGetFieldCount(&context); 00273 00274 for (i = 1; i <= count; i++) 00275 { 00276 if (!(buffer = get_field_string(&context, i, buffer, static_buffer, &size))) 00277 goto done; 00278 00279 if ((hr = callback(hinf, buffer, arg)) != S_OK) 00280 goto done; 00281 } 00282 00283 ok = SetupFindNextMatchLineW(&context, key, &context); 00284 } 00285 00286 hr = S_OK; 00287 00288 done: 00289 if (buffer != static_buffer) HeapFree(GetProcessHeap(), 0, buffer); 00290 return hr; 00291 } 00292 00293 static HRESULT check_admin_rights(const ADVInfo *info) 00294 { 00295 INT check; 00296 INFCONTEXT context; 00297 HRESULT hr = S_OK; 00298 00299 if (!SetupFindFirstLineW(info->hinf, info->install_sec, 00300 CheckAdminRights, &context)) 00301 return S_OK; 00302 00303 if (!SetupGetIntField(&context, 1, &check)) 00304 return S_OK; 00305 00306 if (check == 1) 00307 hr = IsNTAdmin(0, NULL) ? S_OK : E_FAIL; 00308 00309 return hr; 00310 } 00311 00312 /* performs a setupapi-level install of the INF file */ 00313 static HRESULT spapi_install(const ADVInfo *info) 00314 { 00315 BOOL ret; 00316 HRESULT res; 00317 PVOID context; 00318 00319 context = SetupInitDefaultQueueCallbackEx(NULL, INVALID_HANDLE_VALUE, 0, 0, NULL); 00320 if (!context) 00321 return ADV_HRESULT(GetLastError()); 00322 00323 ret = SetupInstallFromInfSectionW(NULL, info->hinf, info->install_sec, 00324 SPINST_FILES, NULL, info->working_dir, 00325 SP_COPY_NEWER, SetupDefaultQueueCallbackW, 00326 context, NULL, NULL); 00327 if (!ret) 00328 { 00329 res = ADV_HRESULT(GetLastError()); 00330 SetupTermDefaultQueueCallback(context); 00331 00332 return res; 00333 } 00334 00335 SetupTermDefaultQueueCallback(context); 00336 00337 ret = SetupInstallFromInfSectionW(NULL, info->hinf, info->install_sec, 00338 SPINST_INIFILES | SPINST_REGISTRY | SPINST_REGSVR, 00339 HKEY_LOCAL_MACHINE, NULL, 0, 00340 NULL, NULL, NULL, NULL); 00341 if (!ret) 00342 return ADV_HRESULT(GetLastError()); 00343 00344 return S_OK; 00345 } 00346 00347 /* processes the Advanced INF commands */ 00348 static HRESULT adv_install(ADVInfo *info) 00349 { 00350 HRESULT hr; 00351 00352 hr = check_admin_rights(info); 00353 if (hr != S_OK) 00354 return hr; 00355 00356 hr = iterate_section_fields(info->hinf, info->install_sec, RunPreSetupCommands, 00357 run_setup_commands_callback, info); 00358 if (hr != S_OK) 00359 return hr; 00360 00361 OleInitialize(NULL); 00362 hr = iterate_section_fields(info->hinf, info->install_sec, 00363 RegisterOCXs, register_ocxs_callback, NULL); 00364 OleUninitialize(); 00365 if (hr != S_OK) 00366 return hr; 00367 00368 hr = iterate_section_fields(info->hinf, info->install_sec, 00369 PerUserInstall, per_user_install_callback, info); 00370 if (hr != S_OK) 00371 return hr; 00372 00373 hr = iterate_section_fields(info->hinf, info->install_sec, RunPostSetupCommands, 00374 run_setup_commands_callback, info); 00375 if (hr != S_OK) 00376 return hr; 00377 00378 hr = iterate_section_fields(info->hinf, info->install_sec, 00379 DelDirs, del_dirs_callback, info); 00380 if (hr != S_OK) 00381 return hr; 00382 00383 return hr; 00384 } 00385 00386 /* determines the proper working directory for the INF file */ 00387 static HRESULT get_working_dir(ADVInfo *info, LPCWSTR inf_filename, LPCWSTR working_dir) 00388 { 00389 WCHAR path[MAX_PATH]; 00390 LPCWSTR ptr; 00391 DWORD len; 00392 00393 static const WCHAR backslash[] = {'\\',0}; 00394 static const WCHAR inf_dir[] = {'\\','I','N','F',0}; 00395 00396 if ((ptr = strrchrW(inf_filename, '\\'))) 00397 { 00398 len = ptr - inf_filename + 1; 00399 ptr = inf_filename; 00400 } 00401 else if (working_dir && *working_dir) 00402 { 00403 len = lstrlenW(working_dir) + 1; 00404 ptr = working_dir; 00405 } 00406 else 00407 { 00408 GetCurrentDirectoryW(MAX_PATH, path); 00409 lstrcatW(path, backslash); 00410 lstrcatW(path, inf_filename); 00411 00412 /* check if the INF file is in the current directory */ 00413 if (GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES) 00414 { 00415 GetCurrentDirectoryW(MAX_PATH, path); 00416 } 00417 else 00418 { 00419 /* default to the windows\inf directory if all else fails */ 00420 GetWindowsDirectoryW(path, MAX_PATH); 00421 lstrcatW(path, inf_dir); 00422 } 00423 00424 len = lstrlenW(path) + 1; 00425 ptr = path; 00426 } 00427 00428 info->working_dir = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 00429 if (!info->working_dir) 00430 return E_OUTOFMEMORY; 00431 00432 lstrcpynW(info->working_dir, ptr, len); 00433 00434 return S_OK; 00435 } 00436 00437 /* loads the INF file and performs checks on it */ 00438 static HRESULT install_init(LPCWSTR inf_filename, LPCWSTR install_sec, 00439 LPCWSTR working_dir, DWORD flags, ADVInfo *info) 00440 { 00441 DWORD len; 00442 HRESULT hr; 00443 LPCWSTR ptr, path; 00444 00445 static const WCHAR backslash[] = {'\\',0}; 00446 static const WCHAR default_install[] = { 00447 'D','e','f','a','u','l','t','I','n','s','t','a','l','l',0 00448 }; 00449 00450 if (!(ptr = strrchrW(inf_filename, '\\'))) 00451 ptr = inf_filename; 00452 00453 len = lstrlenW(ptr); 00454 00455 info->inf_filename = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); 00456 if (!info->inf_filename) 00457 return E_OUTOFMEMORY; 00458 00459 lstrcpyW(info->inf_filename, ptr); 00460 00461 /* FIXME: determine the proper platform to install (NTx86, etc) */ 00462 if (!install_sec || !*install_sec) 00463 { 00464 len = sizeof(default_install) - 1; 00465 ptr = default_install; 00466 } 00467 else 00468 { 00469 len = lstrlenW(install_sec); 00470 ptr = install_sec; 00471 } 00472 00473 info->install_sec = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); 00474 if (!info->install_sec) 00475 return E_OUTOFMEMORY; 00476 00477 lstrcpyW(info->install_sec, ptr); 00478 00479 hr = get_working_dir(info, inf_filename, working_dir); 00480 if (FAILED(hr)) 00481 return hr; 00482 00483 len = lstrlenW(info->working_dir) + lstrlenW(info->inf_filename) + 2; 00484 info->inf_path = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 00485 if (!info->inf_path) 00486 return E_OUTOFMEMORY; 00487 00488 lstrcpyW(info->inf_path, info->working_dir); 00489 lstrcatW(info->inf_path, backslash); 00490 lstrcatW(info->inf_path, info->inf_filename); 00491 00492 /* RunSetupCommand opens unmodifed filename parameter */ 00493 if (flags & RSC_FLAG_INF) 00494 path = inf_filename; 00495 else 00496 path = info->inf_path; 00497 00498 info->hinf = SetupOpenInfFileW(path, NULL, INF_STYLE_WIN4, NULL); 00499 if (info->hinf == INVALID_HANDLE_VALUE) 00500 return ADV_HRESULT(GetLastError()); 00501 00502 set_ldids(info->hinf, info->install_sec, info->working_dir); 00503 00504 /* FIXME: check that the INF is advanced */ 00505 00506 info->flags = flags; 00507 info->need_reboot = FALSE; 00508 00509 return S_OK; 00510 } 00511 00512 /* release the install instance information */ 00513 static void install_release(const ADVInfo *info) 00514 { 00515 SetupCloseInfFile(info->hinf); 00516 00517 HeapFree(GetProcessHeap(), 0, info->inf_path); 00518 HeapFree(GetProcessHeap(), 0, info->inf_filename); 00519 HeapFree(GetProcessHeap(), 0, info->install_sec); 00520 HeapFree(GetProcessHeap(), 0, info->working_dir); 00521 } 00522 00523 /* this structure very closely resembles parameters of RunSetupCommand() */ 00524 typedef struct 00525 { 00526 HWND hwnd; 00527 LPCSTR title; 00528 LPCSTR inf_name; 00529 LPCSTR dir; 00530 LPCSTR section_name; 00531 } SETUPCOMMAND_PARAMS; 00532 00533 typedef struct 00534 { 00535 HWND hwnd; 00536 LPCWSTR title; 00537 LPCWSTR inf_name; 00538 LPCWSTR dir; 00539 LPCWSTR section_name; 00540 } SETUPCOMMAND_PARAMSW; 00541 00542 /* internal: see DoInfInstall */ 00543 static HRESULT DoInfInstallW(const SETUPCOMMAND_PARAMSW *setup) 00544 { 00545 ADVInfo info; 00546 HRESULT hr; 00547 00548 TRACE("(%p)\n", setup); 00549 00550 ZeroMemory(&info, sizeof(ADVInfo)); 00551 00552 hr = install_init(setup->inf_name, setup->section_name, setup->dir, 0, &info); 00553 if (hr != S_OK) 00554 goto done; 00555 00556 hr = spapi_install(&info); 00557 if (hr != S_OK) 00558 goto done; 00559 00560 hr = adv_install(&info); 00561 00562 done: 00563 install_release(&info); 00564 00565 return S_OK; 00566 } 00567 00568 /*********************************************************************** 00569 * DoInfInstall (ADVPACK.@) 00570 * 00571 * Install an INF section. 00572 * 00573 * PARAMS 00574 * setup [I] Structure containing install information. 00575 * 00576 * RETURNS 00577 * S_OK Everything OK 00578 * HRESULT_FROM_WIN32(GetLastError()) Some other error 00579 */ 00580 HRESULT WINAPI DoInfInstall(const SETUPCOMMAND_PARAMS *setup) 00581 { 00582 UNICODE_STRING title, inf, section, dir; 00583 SETUPCOMMAND_PARAMSW params; 00584 HRESULT hr; 00585 00586 if (!setup) 00587 return E_INVALIDARG; 00588 00589 RtlCreateUnicodeStringFromAsciiz(&title, setup->title); 00590 RtlCreateUnicodeStringFromAsciiz(&inf, setup->inf_name); 00591 RtlCreateUnicodeStringFromAsciiz(§ion, setup->section_name); 00592 RtlCreateUnicodeStringFromAsciiz(&dir, setup->dir); 00593 00594 params.title = title.Buffer; 00595 params.inf_name = inf.Buffer; 00596 params.section_name = section.Buffer; 00597 params.dir = dir.Buffer; 00598 params.hwnd = setup->hwnd; 00599 00600 hr = DoInfInstallW(¶ms); 00601 00602 RtlFreeUnicodeString(&title); 00603 RtlFreeUnicodeString(&inf); 00604 RtlFreeUnicodeString(§ion); 00605 RtlFreeUnicodeString(&dir); 00606 00607 return hr; 00608 } 00609 00610 /*********************************************************************** 00611 * ExecuteCabA (ADVPACK.@) 00612 * 00613 * See ExecuteCabW. 00614 */ 00615 HRESULT WINAPI ExecuteCabA(HWND hwnd, CABINFOA* pCab, LPVOID pReserved) 00616 { 00617 UNICODE_STRING cab, inf, section; 00618 CABINFOW cabinfo; 00619 HRESULT hr; 00620 00621 TRACE("(%p, %p, %p)\n", hwnd, pCab, pReserved); 00622 00623 if (!pCab) 00624 return E_INVALIDARG; 00625 00626 if (pCab->pszCab) 00627 { 00628 RtlCreateUnicodeStringFromAsciiz(&cab, pCab->pszCab); 00629 cabinfo.pszCab = cab.Buffer; 00630 } 00631 else 00632 cabinfo.pszCab = NULL; 00633 00634 RtlCreateUnicodeStringFromAsciiz(&inf, pCab->pszInf); 00635 RtlCreateUnicodeStringFromAsciiz(§ion, pCab->pszSection); 00636 00637 MultiByteToWideChar(CP_ACP, 0, pCab->szSrcPath, -1, cabinfo.szSrcPath, 00638 sizeof(cabinfo.szSrcPath) / sizeof(WCHAR)); 00639 00640 cabinfo.pszInf = inf.Buffer; 00641 cabinfo.pszSection = section.Buffer; 00642 cabinfo.dwFlags = pCab->dwFlags; 00643 00644 hr = ExecuteCabW(hwnd, &cabinfo, pReserved); 00645 00646 if (pCab->pszCab) 00647 RtlFreeUnicodeString(&cab); 00648 00649 RtlFreeUnicodeString(&inf); 00650 RtlFreeUnicodeString(§ion); 00651 00652 return hr; 00653 } 00654 00655 /*********************************************************************** 00656 * ExecuteCabW (ADVPACK.@) 00657 * 00658 * Installs the INF file extracted from a specified cabinet file. 00659 * 00660 * PARAMS 00661 * hwnd [I] Handle to the window used for the display. 00662 * pCab [I] Information about the cabinet file. 00663 * pReserved [I] Reserved. Must be NULL. 00664 * 00665 * RETURNS 00666 * Success: S_OK. 00667 * Failure: E_FAIL. 00668 */ 00669 HRESULT WINAPI ExecuteCabW(HWND hwnd, CABINFOW* pCab, LPVOID pReserved) 00670 { 00671 ADVInfo info; 00672 HRESULT hr; 00673 00674 TRACE("(%p, %p, %p)\n", hwnd, pCab, pReserved); 00675 00676 ZeroMemory(&info, sizeof(ADVInfo)); 00677 00678 if (pCab->pszCab && *pCab->pszCab) 00679 FIXME("Cab archive not extracted!\n"); 00680 00681 hr = install_init(pCab->pszInf, pCab->pszSection, pCab->szSrcPath, pCab->dwFlags, &info); 00682 if (hr != S_OK) 00683 goto done; 00684 00685 hr = spapi_install(&info); 00686 if (hr != S_OK) 00687 goto done; 00688 00689 hr = adv_install(&info); 00690 00691 done: 00692 install_release(&info); 00693 00694 return hr; 00695 } 00696 00697 /*********************************************************************** 00698 * LaunchINFSectionA (ADVPACK.@) 00699 * 00700 * See LaunchINFSectionW. 00701 */ 00702 INT WINAPI LaunchINFSectionA(HWND hWnd, HINSTANCE hInst, LPSTR cmdline, INT show) 00703 { 00704 UNICODE_STRING cmd; 00705 HRESULT hr; 00706 00707 TRACE("(%p, %p, %s, %i)\n", hWnd, hInst, debugstr_a(cmdline), show); 00708 00709 if (!cmdline) 00710 return ADV_FAILURE; 00711 00712 RtlCreateUnicodeStringFromAsciiz(&cmd, cmdline); 00713 00714 hr = LaunchINFSectionW(hWnd, hInst, cmd.Buffer, show); 00715 00716 RtlFreeUnicodeString(&cmd); 00717 00718 return hr; 00719 } 00720 00721 /*********************************************************************** 00722 * LaunchINFSectionW (ADVPACK.@) 00723 * 00724 * Installs an INF section without BACKUP/ROLLBACK capabilities. 00725 * 00726 * PARAMS 00727 * hWnd [I] Handle to parent window, NULL for desktop. 00728 * hInst [I] Instance of the process. 00729 * cmdline [I] Contains parameters in the order INF,section,flags,reboot. 00730 * show [I] How the window should be shown. 00731 * 00732 * RETURNS 00733 * Success: ADV_SUCCESS. 00734 * Failure: ADV_FAILURE. 00735 * 00736 * NOTES 00737 * INF - Filename of the INF to launch. 00738 * section - INF section to install. 00739 * flags - see advpub.h. 00740 * reboot - smart reboot behavior 00741 * 'A' Always reboot. 00742 * 'I' Reboot if needed (default). 00743 * 'N' No reboot. 00744 */ 00745 INT WINAPI LaunchINFSectionW(HWND hWnd, HINSTANCE hInst, LPWSTR cmdline, INT show) 00746 { 00747 ADVInfo info; 00748 LPWSTR cmdline_copy, cmdline_ptr; 00749 LPWSTR inf_filename, install_sec; 00750 LPWSTR str_flags; 00751 DWORD flags = 0; 00752 HRESULT hr = S_OK; 00753 00754 TRACE("(%p, %p, %s, %d)\n", hWnd, hInst, debugstr_w(cmdline), show); 00755 00756 if (!cmdline) 00757 return ADV_FAILURE; 00758 00759 cmdline_copy = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(cmdline) + 1) * sizeof(WCHAR)); 00760 cmdline_ptr = cmdline_copy; 00761 lstrcpyW(cmdline_copy, cmdline); 00762 00763 inf_filename = get_parameter(&cmdline_ptr, ','); 00764 install_sec = get_parameter(&cmdline_ptr, ','); 00765 00766 str_flags = get_parameter(&cmdline_ptr, ','); 00767 if (str_flags) 00768 flags = atolW(str_flags); 00769 00770 ZeroMemory(&info, sizeof(ADVInfo)); 00771 00772 hr = install_init(inf_filename, install_sec, NULL, flags, &info); 00773 if (hr != S_OK) 00774 goto done; 00775 00776 hr = spapi_install(&info); 00777 if (hr != S_OK) 00778 goto done; 00779 00780 hr = adv_install(&info); 00781 00782 done: 00783 install_release(&info); 00784 HeapFree(GetProcessHeap(), 0, cmdline_copy); 00785 00786 return SUCCEEDED(hr) ? ADV_SUCCESS : ADV_FAILURE; 00787 } 00788 00789 /*********************************************************************** 00790 * LaunchINFSectionExA (ADVPACK.@) 00791 * 00792 * See LaunchINFSectionExW. 00793 */ 00794 HRESULT WINAPI LaunchINFSectionExA(HWND hWnd, HINSTANCE hInst, LPSTR cmdline, INT show) 00795 { 00796 UNICODE_STRING cmd; 00797 HRESULT hr; 00798 00799 TRACE("(%p, %p, %s, %i)\n", hWnd, hInst, debugstr_a(cmdline), show); 00800 00801 if (!cmdline) 00802 return ADV_FAILURE; 00803 00804 RtlCreateUnicodeStringFromAsciiz(&cmd, cmdline); 00805 00806 hr = LaunchINFSectionExW(hWnd, hInst, cmd.Buffer, show); 00807 00808 RtlFreeUnicodeString(&cmd); 00809 00810 return hr; 00811 } 00812 00813 /*********************************************************************** 00814 * LaunchINFSectionExW (ADVPACK.@) 00815 * 00816 * Installs an INF section with BACKUP/ROLLBACK capabilities. 00817 * 00818 * PARAMS 00819 * hWnd [I] Handle to parent window, NULL for desktop. 00820 * hInst [I] Instance of the process. 00821 * cmdline [I] Contains parameters in the order INF,section,CAB,flags,reboot. 00822 * show [I] How the window should be shown. 00823 * 00824 * RETURNS 00825 * Success: ADV_SUCCESS. 00826 * Failure: ADV_FAILURE. 00827 * 00828 * NOTES 00829 * INF - Filename of the INF to launch. 00830 * section - INF section to install. 00831 * flags - see advpub.h. 00832 * reboot - smart reboot behavior 00833 * 'A' Always reboot. 00834 * 'I' Reboot if needed (default). 00835 * 'N' No reboot. 00836 * 00837 * BUGS 00838 * Doesn't handle the reboot flag. 00839 */ 00840 HRESULT WINAPI LaunchINFSectionExW(HWND hWnd, HINSTANCE hInst, LPWSTR cmdline, INT show) 00841 { 00842 LPWSTR cmdline_copy, cmdline_ptr; 00843 LPWSTR flags, ptr; 00844 CABINFOW cabinfo; 00845 HRESULT hr; 00846 00847 TRACE("(%p, %p, %s, %d)\n", hWnd, hInst, debugstr_w(cmdline), show); 00848 00849 if (!cmdline) 00850 return ADV_FAILURE; 00851 00852 cmdline_copy = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(cmdline) + 1) * sizeof(WCHAR)); 00853 cmdline_ptr = cmdline_copy; 00854 lstrcpyW(cmdline_copy, cmdline); 00855 00856 cabinfo.pszInf = get_parameter(&cmdline_ptr, ','); 00857 cabinfo.pszSection = get_parameter(&cmdline_ptr, ','); 00858 cabinfo.pszCab = get_parameter(&cmdline_ptr, ','); 00859 *cabinfo.szSrcPath = '\0'; 00860 00861 flags = get_parameter(&cmdline_ptr, ','); 00862 if (flags) 00863 cabinfo.dwFlags = atolW(flags); 00864 00865 if (!is_full_path(cabinfo.pszCab) && !is_full_path(cabinfo.pszInf)) 00866 { 00867 HeapFree(GetProcessHeap(), 0, cmdline_copy); 00868 return E_INVALIDARG; 00869 } 00870 00871 /* get the source path from the cab filename */ 00872 if (cabinfo.pszCab && *cabinfo.pszCab) 00873 { 00874 if (!is_full_path(cabinfo.pszCab)) 00875 lstrcpyW(cabinfo.szSrcPath, cabinfo.pszInf); 00876 else 00877 lstrcpyW(cabinfo.szSrcPath, cabinfo.pszCab); 00878 00879 ptr = strrchrW(cabinfo.szSrcPath, '\\'); 00880 *(++ptr) = '\0'; 00881 } 00882 00883 hr = ExecuteCabW(hWnd, &cabinfo, NULL); 00884 HeapFree(GetProcessHeap(), 0, cmdline_copy); 00885 return SUCCEEDED(hr) ? ADV_SUCCESS : ADV_FAILURE; 00886 } 00887 00888 HRESULT launch_exe(LPCWSTR cmd, LPCWSTR dir, HANDLE *phEXE) 00889 { 00890 STARTUPINFOW si; 00891 PROCESS_INFORMATION pi; 00892 00893 if (phEXE) *phEXE = NULL; 00894 00895 ZeroMemory(&pi, sizeof(pi)); 00896 ZeroMemory(&si, sizeof(si)); 00897 si.cb = sizeof(si); 00898 00899 if (!CreateProcessW(NULL, (LPWSTR)cmd, NULL, NULL, FALSE, 00900 CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_PROCESS_GROUP, 00901 NULL, dir, &si, &pi)) 00902 { 00903 return HRESULT_FROM_WIN32(GetLastError()); 00904 } 00905 00906 CloseHandle(pi.hThread); 00907 00908 if (phEXE) 00909 { 00910 *phEXE = pi.hProcess; 00911 return S_ASYNCHRONOUS; 00912 } 00913 00914 /* wait for the child process to finish */ 00915 WaitForSingleObject(pi.hProcess, INFINITE); 00916 CloseHandle(pi.hProcess); 00917 00918 return S_OK; 00919 } 00920 00921 /*********************************************************************** 00922 * RunSetupCommandA (ADVPACK.@) 00923 * 00924 * See RunSetupCommandW. 00925 */ 00926 HRESULT WINAPI RunSetupCommandA(HWND hWnd, LPCSTR szCmdName, 00927 LPCSTR szInfSection, LPCSTR szDir, 00928 LPCSTR lpszTitle, HANDLE *phEXE, 00929 DWORD dwFlags, LPVOID pvReserved) 00930 { 00931 UNICODE_STRING cmdname, infsec; 00932 UNICODE_STRING dir, title; 00933 HRESULT hr; 00934 00935 TRACE("(%p, %s, %s, %s, %s, %p, %d, %p)\n", 00936 hWnd, debugstr_a(szCmdName), debugstr_a(szInfSection), 00937 debugstr_a(szDir), debugstr_a(lpszTitle), 00938 phEXE, dwFlags, pvReserved); 00939 00940 if (!szCmdName || !szDir) 00941 return E_INVALIDARG; 00942 00943 RtlCreateUnicodeStringFromAsciiz(&cmdname, szCmdName); 00944 RtlCreateUnicodeStringFromAsciiz(&infsec, szInfSection); 00945 RtlCreateUnicodeStringFromAsciiz(&dir, szDir); 00946 RtlCreateUnicodeStringFromAsciiz(&title, lpszTitle); 00947 00948 hr = RunSetupCommandW(hWnd, cmdname.Buffer, infsec.Buffer, dir.Buffer, 00949 title.Buffer, phEXE, dwFlags, pvReserved); 00950 00951 RtlFreeUnicodeString(&cmdname); 00952 RtlFreeUnicodeString(&infsec); 00953 RtlFreeUnicodeString(&dir); 00954 RtlFreeUnicodeString(&title); 00955 00956 return hr; 00957 } 00958 00959 /*********************************************************************** 00960 * RunSetupCommandW (ADVPACK.@) 00961 * 00962 * Executes an install section in an INF file or a program. 00963 * 00964 * PARAMS 00965 * hWnd [I] Handle to parent window, NULL for quiet mode 00966 * szCmdName [I] Inf or EXE filename to execute 00967 * szInfSection [I] Inf section to install, NULL for DefaultInstall 00968 * szDir [I] Path to extracted files 00969 * szTitle [I] Title of all dialogs 00970 * phEXE [O] Handle of EXE to wait for 00971 * dwFlags [I] Flags; see include/advpub.h 00972 * pvReserved [I] Reserved 00973 * 00974 * RETURNS 00975 * S_OK Everything OK 00976 * S_ASYNCHRONOUS OK, required to wait on phEXE 00977 * ERROR_SUCCESS_REBOOT_REQUIRED Reboot required 00978 * E_INVALIDARG Invalid argument given 00979 * HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION) 00980 * Not supported on this Windows version 00981 * E_UNEXPECTED Unexpected error 00982 * HRESULT_FROM_WIN32(GetLastError()) Some other error 00983 */ 00984 HRESULT WINAPI RunSetupCommandW(HWND hWnd, LPCWSTR szCmdName, 00985 LPCWSTR szInfSection, LPCWSTR szDir, 00986 LPCWSTR lpszTitle, HANDLE *phEXE, 00987 DWORD dwFlags, LPVOID pvReserved) 00988 { 00989 ADVInfo info; 00990 HRESULT hr; 00991 00992 TRACE("(%p, %s, %s, %s, %s, %p, %d, %p)\n", 00993 hWnd, debugstr_w(szCmdName), debugstr_w(szInfSection), 00994 debugstr_w(szDir), debugstr_w(lpszTitle), 00995 phEXE, dwFlags, pvReserved); 00996 00997 if (dwFlags & RSC_FLAG_UPDHLPDLLS) 00998 FIXME("Unhandled flag: RSC_FLAG_UPDHLPDLLS\n"); 00999 01000 if (!szCmdName || !szDir) 01001 return E_INVALIDARG; 01002 01003 if (!(dwFlags & RSC_FLAG_INF)) 01004 return launch_exe(szCmdName, szDir, phEXE); 01005 01006 ZeroMemory(&info, sizeof(ADVInfo)); 01007 01008 hr = install_init(szCmdName, szInfSection, szDir, dwFlags, &info); 01009 if (hr != S_OK) 01010 goto done; 01011 01012 hr = spapi_install(&info); 01013 if (hr != S_OK) 01014 goto done; 01015 01016 hr = adv_install(&info); 01017 01018 done: 01019 install_release(&info); 01020 01021 return hr; 01022 } Generated on Sun May 27 2012 04:19:19 for ReactOS by
1.7.6.1
|