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  * 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(&section, 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(&params);
00601 
00602     RtlFreeUnicodeString(&title);
00603     RtlFreeUnicodeString(&inf);
00604     RtlFreeUnicodeString(&section);
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(&section, 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(&section);
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 doxygen 1.7.6.1

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