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

msiexec.c
Go to the documentation of this file.
00001 /*
00002  * msiexec.exe implementation
00003  *
00004  * Copyright 2004 Vincent Béron
00005  * Copyright 2005 Mike McCormack
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #define WIN32_LEAN_AND_MEAN
00023 
00024 #include <windows.h>
00025 #include <msi.h>
00026 #include <objbase.h>
00027 #include <stdio.h>
00028 
00029 #include "wine/debug.h"
00030 #include "wine/unicode.h"
00031 
00032 WINE_DEFAULT_DEBUG_CHANNEL(msiexec);
00033 
00034 typedef HRESULT (WINAPI *DLLREGISTERSERVER)(void);
00035 typedef HRESULT (WINAPI *DLLUNREGISTERSERVER)(void);
00036 
00037 DWORD DoService(void);
00038 
00039 struct string_list
00040 {
00041     struct string_list *next;
00042     WCHAR str[1];
00043 };
00044 
00045 static const WCHAR ActionAdmin[] = {
00046    'A','C','T','I','O','N','=','A','D','M','I','N',0 };
00047 static const WCHAR RemoveAll[] = {
00048    'R','E','M','O','V','E','=','A','L','L',0 };
00049 
00050 static const WCHAR InstallRunOnce[] = {
00051    'S','o','f','t','w','a','r','e','\\',
00052    'M','i','c','r','o','s','o','f','t','\\',
00053    'W','i','n','d','o','w','s','\\',
00054    'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00055    'I','n','s','t','a','l','l','e','r','\\',
00056    'R','u','n','O','n','c','e','E','n','t','r','i','e','s',0};
00057 
00058 static void ShowUsage(int ExitCode)
00059 {
00060     WCHAR msiexec_version[40];
00061     WCHAR filename[MAX_PATH];
00062     LPWSTR msi_res;
00063     LPWSTR msiexec_help;
00064     HMODULE hmsi = GetModuleHandleA("msi.dll");
00065     DWORD len;
00066     DWORD res;
00067 
00068     /* MsiGetFileVersion need the full path */
00069     *filename = 0;
00070     res = GetModuleFileNameW(hmsi, filename, sizeof(filename) / sizeof(filename[0]));
00071     if (!res)
00072         WINE_ERR("GetModuleFileName failed: %d\n", GetLastError());
00073 
00074     len = sizeof(msiexec_version) / sizeof(msiexec_version[0]);
00075     *msiexec_version = 0;
00076     res = MsiGetFileVersionW(filename, msiexec_version, &len, NULL, NULL);
00077     if (res)
00078         WINE_ERR("MsiGetFileVersion failed with %d\n", res);
00079 
00080     /* Return the length of the resource.
00081        No typo: The LPWSTR parameter must be a LPWSTR * for this mode */
00082     len = LoadStringW(hmsi, 10, (LPWSTR) &msi_res, 0);
00083 
00084     msi_res = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
00085     msiexec_help = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) + sizeof(msiexec_version));
00086     if (msi_res && msiexec_help) {
00087         *msi_res = 0;
00088         LoadStringW(hmsi, 10, msi_res, len + 1);
00089 
00090         sprintfW(msiexec_help, msi_res, msiexec_version);
00091         MsiMessageBoxW(0, msiexec_help, NULL, 0, GetUserDefaultLangID(), 0);
00092     }
00093     HeapFree(GetProcessHeap(), 0, msi_res);
00094     HeapFree(GetProcessHeap(), 0, msiexec_help);
00095     ExitProcess(ExitCode);
00096 }
00097 
00098 static BOOL IsProductCode(LPWSTR str)
00099 {
00100     GUID ProductCode;
00101 
00102     if(lstrlenW(str) != 38)
00103         return FALSE;
00104     return ( (CLSIDFromString(str, &ProductCode) == NOERROR) );
00105 
00106 }
00107 
00108 static VOID StringListAppend(struct string_list **list, LPCWSTR str)
00109 {
00110     struct string_list *entry;
00111     DWORD size;
00112 
00113     size = sizeof *entry + lstrlenW(str) * sizeof (WCHAR);
00114     entry = HeapAlloc(GetProcessHeap(), 0, size);
00115     if(!entry)
00116     {
00117         WINE_ERR("Out of memory!\n");
00118         ExitProcess(1);
00119     }
00120     lstrcpyW(entry->str, str);
00121     entry->next = NULL;
00122 
00123     /*
00124      * Ignoring o(n^2) time complexity to add n strings for simplicity,
00125      *  add the string to the end of the list to preserve the order.
00126      */
00127     while( *list )
00128         list = &(*list)->next;
00129     *list = entry;
00130 }
00131 
00132 static LPWSTR build_properties(struct string_list *property_list)
00133 {
00134     struct string_list *list;
00135     LPWSTR ret, p, value;
00136     DWORD len;
00137     BOOL needs_quote;
00138 
00139     if(!property_list)
00140         return NULL;
00141 
00142     /* count the space we need */
00143     len = 1;
00144     for(list = property_list; list; list = list->next)
00145         len += lstrlenW(list->str) + 3;
00146 
00147     ret = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
00148 
00149     /* add a space before each string, and quote the value */
00150     p = ret;
00151     for(list = property_list; list; list = list->next)
00152     {
00153         value = strchrW(list->str,'=');
00154         if(!value)
00155             continue;
00156         len = value - list->str;
00157         *p++ = ' ';
00158         memcpy(p, list->str, len * sizeof(WCHAR));
00159         p += len;
00160         *p++ = '=';
00161 
00162         /* check if the value contains spaces and maybe quote it */
00163         value++;
00164         needs_quote = strchrW(value,' ') ? 1 : 0;
00165         if(needs_quote)
00166             *p++ = '"';
00167         len = lstrlenW(value);
00168         memcpy(p, value, len * sizeof(WCHAR));
00169         p += len;
00170         if(needs_quote)
00171             *p++ = '"';
00172     }
00173     *p = 0;
00174 
00175     WINE_TRACE("properties -> %s\n", wine_dbgstr_w(ret) );
00176 
00177     return ret;
00178 }
00179 
00180 static LPWSTR build_transforms(struct string_list *transform_list)
00181 {
00182     struct string_list *list;
00183     LPWSTR ret, p;
00184     DWORD len;
00185 
00186     /* count the space we need */
00187     len = 1;
00188     for(list = transform_list; list; list = list->next)
00189         len += lstrlenW(list->str) + 1;
00190 
00191     ret = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
00192 
00193     /* add all the transforms with a semicolon between each one */
00194     p = ret;
00195     for(list = transform_list; list; list = list->next)
00196     {
00197         len = lstrlenW(list->str);
00198         lstrcpynW(p, list->str, len );
00199         p += len;
00200         if(list->next)
00201             *p++ = ';';
00202     }
00203     *p = 0;
00204 
00205     return ret;
00206 }
00207 
00208 static DWORD msi_atou(LPCWSTR str)
00209 {
00210     DWORD ret = 0;
00211     while(*str >= '0' && *str <= '9')
00212     {
00213         ret *= 10;
00214         ret += (*str - '0');
00215         str++;
00216     }
00217     return ret;
00218 }
00219 
00220 static LPWSTR msi_strdup(LPCWSTR str)
00221 {
00222     DWORD len = lstrlenW(str)+1;
00223     LPWSTR ret = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
00224     lstrcpyW(ret, str);
00225     return ret;
00226 }
00227 
00228 /* str1 is the same as str2, ignoring case */
00229 static BOOL msi_strequal(LPCWSTR str1, LPCSTR str2)
00230 {
00231     DWORD len, ret;
00232     LPWSTR strW;
00233 
00234     len = MultiByteToWideChar( CP_ACP, 0, str2, -1, NULL, 0);
00235     if( !len )
00236         return FALSE;
00237     if( lstrlenW(str1) != (len-1) )
00238         return FALSE;
00239     strW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
00240     MultiByteToWideChar( CP_ACP, 0, str2, -1, strW, len);
00241     ret = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, str1, len, strW, len);
00242     HeapFree(GetProcessHeap(), 0, strW);
00243     return (ret == CSTR_EQUAL);
00244 }
00245 
00246 /* prefix is hyphen or dash, and str1 is the same as str2, ignoring case */
00247 static BOOL msi_option_equal(LPCWSTR str1, LPCSTR str2)
00248 {
00249     if (str1[0] != '/' && str1[0] != '-')
00250         return FALSE;
00251 
00252     /* skip over the hyphen or slash */
00253     return msi_strequal(str1 + 1, str2);
00254 }
00255 
00256 /* str2 is at the beginning of str1, ignoring case */
00257 static BOOL msi_strprefix(LPCWSTR str1, LPCSTR str2)
00258 {
00259     DWORD len, ret;
00260     LPWSTR strW;
00261 
00262     len = MultiByteToWideChar( CP_ACP, 0, str2, -1, NULL, 0);
00263     if( !len )
00264         return FALSE;
00265     if( lstrlenW(str1) < (len-1) )
00266         return FALSE;
00267     strW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
00268     MultiByteToWideChar( CP_ACP, 0, str2, -1, strW, len);
00269     ret = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, str1, len-1, strW, len-1);
00270     HeapFree(GetProcessHeap(), 0, strW);
00271     return (ret == CSTR_EQUAL);
00272 }
00273 
00274 /* prefix is hyphen or dash, and str2 is at the beginning of str1, ignoring case */
00275 static BOOL msi_option_prefix(LPCWSTR str1, LPCSTR str2)
00276 {
00277     if (str1[0] != '/' && str1[0] != '-')
00278         return FALSE;
00279 
00280     /* skip over the hyphen or slash */
00281     return msi_strprefix(str1 + 1, str2);
00282 }
00283 
00284 static VOID *LoadProc(LPCWSTR DllName, LPCSTR ProcName, HMODULE* DllHandle)
00285 {
00286     VOID* (*proc)(void);
00287 
00288     *DllHandle = LoadLibraryExW(DllName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
00289     if(!*DllHandle)
00290     {
00291         fprintf(stderr, "Unable to load dll %s\n", wine_dbgstr_w(DllName));
00292         ExitProcess(1);
00293     }
00294     proc = (VOID *) GetProcAddress(*DllHandle, ProcName);
00295     if(!proc)
00296     {
00297         fprintf(stderr, "Dll %s does not implement function %s\n",
00298             wine_dbgstr_w(DllName), ProcName);
00299         FreeLibrary(*DllHandle);
00300         ExitProcess(1);
00301     }
00302 
00303     return proc;
00304 }
00305 
00306 static DWORD DoDllRegisterServer(LPCWSTR DllName)
00307 {
00308     HRESULT hr;
00309     DLLREGISTERSERVER pfDllRegisterServer = NULL;
00310     HMODULE DllHandle = NULL;
00311 
00312     pfDllRegisterServer = LoadProc(DllName, "DllRegisterServer", &DllHandle);
00313 
00314     hr = pfDllRegisterServer();
00315     if(FAILED(hr))
00316     {
00317         fprintf(stderr, "Failed to register dll %s\n", wine_dbgstr_w(DllName));
00318         return 1;
00319     }
00320     printf("Successfully registered dll %s\n", wine_dbgstr_w(DllName));
00321     if(DllHandle)
00322         FreeLibrary(DllHandle);
00323     return 0;
00324 }
00325 
00326 static DWORD DoDllUnregisterServer(LPCWSTR DllName)
00327 {
00328     HRESULT hr;
00329     DLLUNREGISTERSERVER pfDllUnregisterServer = NULL;
00330     HMODULE DllHandle = NULL;
00331 
00332     pfDllUnregisterServer = LoadProc(DllName, "DllUnregisterServer", &DllHandle);
00333 
00334     hr = pfDllUnregisterServer();
00335     if(FAILED(hr))
00336     {
00337         fprintf(stderr, "Failed to unregister dll %s\n", wine_dbgstr_w(DllName));
00338         return 1;
00339     }
00340     printf("Successfully unregistered dll %s\n", wine_dbgstr_w(DllName));
00341     if(DllHandle)
00342         FreeLibrary(DllHandle);
00343     return 0;
00344 }
00345 
00346 static DWORD DoRegServer(void)
00347 {
00348     SC_HANDLE scm, service;
00349     CHAR path[MAX_PATH+12];
00350     DWORD ret = 0;
00351 
00352     scm = OpenSCManagerA(NULL, SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CREATE_SERVICE);
00353     if (!scm)
00354     {
00355         fprintf(stderr, "Failed to open the service control manager.\n");
00356         return 1;
00357     }
00358 
00359     GetSystemDirectoryA(path, MAX_PATH);
00360     lstrcatA(path, "\\msiexec.exe /V");
00361 
00362     service = CreateServiceA(scm, "MSIServer", "MSIServer", GENERIC_ALL,
00363                              SERVICE_WIN32_SHARE_PROCESS, SERVICE_DEMAND_START,
00364                              SERVICE_ERROR_NORMAL, path, NULL, NULL,
00365                              NULL, NULL, NULL);
00366 
00367     if (service) CloseServiceHandle(service);
00368     else if (GetLastError() != ERROR_SERVICE_EXISTS)
00369     {
00370         fprintf(stderr, "Failed to create MSI service\n");
00371         ret = 1;
00372     }
00373     CloseServiceHandle(scm);
00374     return ret;
00375 }
00376 
00377 static INT DoEmbedding( LPWSTR key )
00378 {
00379     printf("Remote custom actions are not supported yet\n");
00380     return 1;
00381 }
00382 
00383 /*
00384  * state machine to break up the command line properly
00385  */
00386 
00387 enum chomp_state
00388 {
00389     cs_whitespace,
00390     cs_token,
00391     cs_quote
00392 };
00393 
00394 static int chomp( WCHAR *str )
00395 {
00396     enum chomp_state state = cs_token;
00397     WCHAR *p, *out;
00398     int count = 1, ignore;
00399 
00400     for( p = str, out = str; *p; p++ )
00401     {
00402         ignore = 1;
00403         switch( state )
00404         {
00405         case cs_whitespace:
00406             switch( *p )
00407             {
00408             case ' ':
00409                 break;
00410             case '"':
00411                 state = cs_quote;
00412                 count++;
00413                 break;
00414             default:
00415                 count++;
00416                 ignore = 0;
00417                 state = cs_token;
00418             }
00419             break;
00420 
00421         case cs_token:
00422             switch( *p )
00423             {
00424             case '"':
00425                 state = cs_quote;
00426                 break;
00427             case ' ':
00428                 state = cs_whitespace;
00429                 *out++ = 0;
00430                 break;
00431             default:
00432                 ignore = 0;
00433             }
00434             break;
00435 
00436         case cs_quote:
00437             switch( *p )
00438             {
00439             case '"':
00440                 state = cs_token;
00441                 break;
00442             default:
00443                 ignore = 0;
00444             }
00445             break;
00446         }
00447         if( !ignore )
00448             *out++ = *p;
00449     }
00450 
00451     *out = 0;
00452 
00453     return count;
00454 }
00455 
00456 static void process_args( WCHAR *cmdline, int *pargc, WCHAR ***pargv )
00457 {
00458     WCHAR **argv, *p = msi_strdup(cmdline);
00459     int i, n;
00460 
00461     n = chomp( p );
00462     argv = HeapAlloc(GetProcessHeap(), 0, sizeof (WCHAR*)*(n+1));
00463     for( i=0; i<n; i++ )
00464     {
00465         argv[i] = p;
00466         p += lstrlenW(p) + 1;
00467     }
00468     argv[i] = NULL;
00469 
00470     *pargc = n;
00471     *pargv = argv;
00472 }
00473 
00474 static BOOL process_args_from_reg( LPWSTR ident, int *pargc, WCHAR ***pargv )
00475 {
00476     LONG r;
00477     HKEY hkey = 0, hkeyArgs = 0;
00478     DWORD sz = 0, type = 0;
00479     LPWSTR buf = NULL;
00480     BOOL ret = FALSE;
00481 
00482     r = RegOpenKeyW(HKEY_LOCAL_MACHINE, InstallRunOnce, &hkey);
00483     if(r != ERROR_SUCCESS)
00484         return FALSE;
00485     r = RegQueryValueExW(hkey, ident, 0, &type, 0, &sz);
00486     if(r == ERROR_SUCCESS && type == REG_SZ)
00487     {
00488         buf = HeapAlloc(GetProcessHeap(), 0, sz);
00489         r = RegQueryValueExW(hkey, ident, 0, &type, (LPBYTE)buf, &sz);
00490         if( r == ERROR_SUCCESS )
00491         {
00492             process_args(buf, pargc, pargv);
00493             ret = TRUE;
00494         }
00495         HeapFree(GetProcessHeap(), 0, buf);
00496     }
00497     RegCloseKey(hkeyArgs);
00498     return ret;
00499 }
00500 
00501 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
00502 {
00503     int i;
00504     BOOL FunctionInstall = FALSE;
00505     BOOL FunctionInstallAdmin = FALSE;
00506     BOOL FunctionRepair = FALSE;
00507     BOOL FunctionAdvertise = FALSE;
00508     BOOL FunctionPatch = FALSE;
00509     BOOL FunctionDllRegisterServer = FALSE;
00510     BOOL FunctionDllUnregisterServer = FALSE;
00511     BOOL FunctionRegServer = FALSE;
00512     BOOL FunctionUnregServer = FALSE;
00513     BOOL FunctionServer = FALSE;
00514     BOOL FunctionUnknown = FALSE;
00515 
00516     LPWSTR PackageName = NULL;
00517     LPWSTR Properties = NULL;
00518     struct string_list *property_list = NULL;
00519 
00520     DWORD RepairMode = 0;
00521 
00522     DWORD_PTR AdvertiseMode = 0;
00523     struct string_list *transform_list = NULL;
00524     LANGID Language = 0;
00525 
00526     DWORD LogMode = 0;
00527     LPWSTR LogFileName = NULL;
00528     DWORD LogAttributes = 0;
00529 
00530     LPWSTR PatchFileName = NULL;
00531     INSTALLTYPE InstallType = INSTALLTYPE_DEFAULT;
00532 
00533     INSTALLUILEVEL InstallUILevel = INSTALLUILEVEL_FULL;
00534 
00535     LPWSTR DllName = NULL;
00536     DWORD ReturnCode;
00537     int argc;
00538     LPWSTR *argvW = NULL;
00539 
00540     /* parse the command line */
00541     process_args( GetCommandLineW(), &argc, &argvW );
00542 
00543     /*
00544      * If the args begin with /@ IDENT then we need to load the real
00545      * command line out of the RunOnceEntries key in the registry.
00546      *  We do that before starting to process the real commandline,
00547      * then overwrite the commandline again.
00548      */
00549     if(argc>1 && msi_option_equal(argvW[1], "@"))
00550     {
00551         if(!process_args_from_reg( argvW[2], &argc, &argvW ))
00552             return 1;
00553     }
00554 
00555     if (argc == 3 && msi_option_equal(argvW[1], "Embedding"))
00556         return DoEmbedding( argvW[2] );
00557 
00558     for(i = 1; i < argc; i++)
00559     {
00560         WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
00561 
00562         if (msi_option_equal(argvW[i], "regserver"))
00563         {
00564             FunctionRegServer = TRUE;
00565         }
00566         else if (msi_option_equal(argvW[i], "unregserver") || msi_option_equal(argvW[i], "unregister"))
00567         {
00568             FunctionUnregServer = TRUE;
00569         }
00570         else if(msi_option_prefix(argvW[i], "i") || msi_option_prefix(argvW[i], "package"))
00571         {
00572             LPWSTR argvWi = argvW[i];
00573             int argLen = (msi_option_prefix(argvW[i], "i") ? 2 : 8);
00574             FunctionInstall = TRUE;
00575             if(lstrlenW(argvW[i]) > argLen)
00576                 argvWi += argLen;
00577             else
00578             {
00579                 i++;
00580                 if(i >= argc)
00581                     ShowUsage(1);
00582                 WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
00583                 argvWi = argvW[i];
00584             }
00585             PackageName = argvWi;
00586         }
00587         else if(msi_option_equal(argvW[i], "a"))
00588         {
00589             FunctionInstall = TRUE;
00590             FunctionInstallAdmin = TRUE;
00591             InstallType = INSTALLTYPE_NETWORK_IMAGE;
00592             i++;
00593             if(i >= argc)
00594                 ShowUsage(1);
00595             WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
00596             PackageName = argvW[i];
00597             StringListAppend(&property_list, ActionAdmin);
00598         }
00599         else if(msi_option_prefix(argvW[i], "f"))
00600         {
00601             int j;
00602             int len = lstrlenW(argvW[i]);
00603             FunctionRepair = TRUE;
00604             for(j = 2; j < len; j++)
00605             {
00606                 switch(argvW[i][j])
00607                 {
00608                     case 'P':
00609                     case 'p':
00610                         RepairMode |= REINSTALLMODE_FILEMISSING;
00611                         break;
00612                     case 'O':
00613                     case 'o':
00614                         RepairMode |= REINSTALLMODE_FILEOLDERVERSION;
00615                         break;
00616                     case 'E':
00617                     case 'e':
00618                         RepairMode |= REINSTALLMODE_FILEEQUALVERSION;
00619                         break;
00620                     case 'D':
00621                     case 'd':
00622                         RepairMode |= REINSTALLMODE_FILEEXACT;
00623                         break;
00624                     case 'C':
00625                     case 'c':
00626                         RepairMode |= REINSTALLMODE_FILEVERIFY;
00627                         break;
00628                     case 'A':
00629                     case 'a':
00630                         RepairMode |= REINSTALLMODE_FILEREPLACE;
00631                         break;
00632                     case 'U':
00633                     case 'u':
00634                         RepairMode |= REINSTALLMODE_USERDATA;
00635                         break;
00636                     case 'M':
00637                     case 'm':
00638                         RepairMode |= REINSTALLMODE_MACHINEDATA;
00639                         break;
00640                     case 'S':
00641                     case 's':
00642                         RepairMode |= REINSTALLMODE_SHORTCUT;
00643                         break;
00644                     case 'V':
00645                     case 'v':
00646                         RepairMode |= REINSTALLMODE_PACKAGE;
00647                         break;
00648                     default:
00649                         fprintf(stderr, "Unknown option \"%c\" in Repair mode\n", argvW[i][j]);
00650                         break;
00651                 }
00652             }
00653             if(len == 2)
00654             {
00655                 RepairMode = REINSTALLMODE_FILEMISSING |
00656                     REINSTALLMODE_FILEEQUALVERSION |
00657                     REINSTALLMODE_FILEVERIFY |
00658                     REINSTALLMODE_MACHINEDATA |
00659                     REINSTALLMODE_SHORTCUT;
00660             }
00661             i++;
00662             if(i >= argc)
00663                 ShowUsage(1);
00664             WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
00665             PackageName = argvW[i];
00666         }
00667         else if(msi_option_prefix(argvW[i], "x") || msi_option_equal(argvW[i], "uninstall"))
00668         {
00669             FunctionInstall = TRUE;
00670             if(msi_option_prefix(argvW[i], "x")) PackageName = argvW[i]+2;
00671             if(!PackageName || !PackageName[0])
00672             {
00673                 i++;
00674                 if (i >= argc)
00675                     ShowUsage(1);
00676                 PackageName = argvW[i];
00677             }
00678             WINE_TRACE("PackageName = %s\n", wine_dbgstr_w(PackageName));
00679             StringListAppend(&property_list, RemoveAll);
00680         }
00681         else if(msi_option_prefix(argvW[i], "j"))
00682         {
00683             int j;
00684             int len = lstrlenW(argvW[i]);
00685             FunctionAdvertise = TRUE;
00686             for(j = 2; j < len; j++)
00687             {
00688                 switch(argvW[i][j])
00689                 {
00690                     case 'U':
00691                     case 'u':
00692                         AdvertiseMode = ADVERTISEFLAGS_USERASSIGN;
00693                         break;
00694                     case 'M':
00695                     case 'm':
00696                         AdvertiseMode = ADVERTISEFLAGS_MACHINEASSIGN;
00697                         break;
00698                     default:
00699                         fprintf(stderr, "Unknown option \"%c\" in Advertise mode\n", argvW[i][j]);
00700                         break;
00701                 }
00702             }
00703             i++;
00704             if(i >= argc)
00705                 ShowUsage(1);
00706             WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
00707             PackageName = argvW[i];
00708         }
00709         else if(msi_strequal(argvW[i], "u"))
00710         {
00711             FunctionAdvertise = TRUE;
00712             AdvertiseMode = ADVERTISEFLAGS_USERASSIGN;
00713             i++;
00714             if(i >= argc)
00715                 ShowUsage(1);
00716             WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
00717             PackageName = argvW[i];
00718         }
00719         else if(msi_strequal(argvW[i], "m"))
00720         {
00721             FunctionAdvertise = TRUE;
00722             AdvertiseMode = ADVERTISEFLAGS_MACHINEASSIGN;
00723             i++;
00724             if(i >= argc)
00725                 ShowUsage(1);
00726             WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
00727             PackageName = argvW[i];
00728         }
00729         else if(msi_option_equal(argvW[i], "t"))
00730         {
00731             i++;
00732             if(i >= argc)
00733                 ShowUsage(1);
00734             WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
00735             StringListAppend(&transform_list, argvW[i]);
00736         }
00737         else if(msi_option_equal(argvW[i], "g"))
00738         {
00739             i++;
00740             if(i >= argc)
00741                 ShowUsage(1);
00742             WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
00743             Language = msi_atou(argvW[i]);
00744         }
00745         else if(msi_option_prefix(argvW[i], "l"))
00746         {
00747             int j;
00748             int len = lstrlenW(argvW[i]);
00749             for(j = 2; j < len; j++)
00750             {
00751                 switch(argvW[i][j])
00752                 {
00753                     case 'I':
00754                     case 'i':
00755                         LogMode |= INSTALLLOGMODE_INFO;
00756                         break;
00757                     case 'W':
00758                     case 'w':
00759                         LogMode |= INSTALLLOGMODE_WARNING;
00760                         break;
00761                     case 'E':
00762                     case 'e':
00763                         LogMode |= INSTALLLOGMODE_ERROR;
00764                         break;
00765                     case 'A':
00766                     case 'a':
00767                         LogMode |= INSTALLLOGMODE_ACTIONSTART;
00768                         break;
00769                     case 'R':
00770                     case 'r':
00771                         LogMode |= INSTALLLOGMODE_ACTIONDATA;
00772                         break;
00773                     case 'U':
00774                     case 'u':
00775                         LogMode |= INSTALLLOGMODE_USER;
00776                         break;
00777                     case 'C':
00778                     case 'c':
00779                         LogMode |= INSTALLLOGMODE_COMMONDATA;
00780                         break;
00781                     case 'M':
00782                     case 'm':
00783                         LogMode |= INSTALLLOGMODE_FATALEXIT;
00784                         break;
00785                     case 'O':
00786                     case 'o':
00787                         LogMode |= INSTALLLOGMODE_OUTOFDISKSPACE;
00788                         break;
00789                     case 'P':
00790                     case 'p':
00791                         LogMode |= INSTALLLOGMODE_PROPERTYDUMP;
00792                         break;
00793                     case 'V':
00794                     case 'v':
00795                         LogMode |= INSTALLLOGMODE_VERBOSE;
00796                         break;
00797                     case '*':
00798                         LogMode = INSTALLLOGMODE_FATALEXIT |
00799                             INSTALLLOGMODE_ERROR |
00800                             INSTALLLOGMODE_WARNING |
00801                             INSTALLLOGMODE_USER |
00802                             INSTALLLOGMODE_INFO |
00803                             INSTALLLOGMODE_RESOLVESOURCE |
00804                             INSTALLLOGMODE_OUTOFDISKSPACE |
00805                             INSTALLLOGMODE_ACTIONSTART |
00806                             INSTALLLOGMODE_ACTIONDATA |
00807                             INSTALLLOGMODE_COMMONDATA |
00808                             INSTALLLOGMODE_PROPERTYDUMP |
00809                             INSTALLLOGMODE_PROGRESS |
00810                             INSTALLLOGMODE_INITIALIZE |
00811                             INSTALLLOGMODE_TERMINATE |
00812                             INSTALLLOGMODE_SHOWDIALOG;
00813                         break;
00814                     case '+':
00815                         LogAttributes |= INSTALLLOGATTRIBUTES_APPEND;
00816                         break;
00817                     case '!':
00818                         LogAttributes |= INSTALLLOGATTRIBUTES_FLUSHEACHLINE;
00819                         break;
00820                     default:
00821                         break;
00822                 }
00823             }
00824             i++;
00825             if(i >= argc)
00826                 ShowUsage(1);
00827             WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
00828             LogFileName = argvW[i];
00829             if(MsiEnableLogW(LogMode, LogFileName, LogAttributes) != ERROR_SUCCESS)
00830             {
00831                 fprintf(stderr, "Logging in %s (0x%08x, %u) failed\n",
00832                      wine_dbgstr_w(LogFileName), LogMode, LogAttributes);
00833                 ExitProcess(1);
00834             }
00835         }
00836         else if(msi_option_equal(argvW[i], "p"))
00837         {
00838             FunctionPatch = TRUE;
00839             i++;
00840             if(i >= argc)
00841                 ShowUsage(1);
00842             WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
00843             PatchFileName = argvW[i];
00844         }
00845         else if(msi_option_prefix(argvW[i], "q"))
00846         {
00847             if(lstrlenW(argvW[i]) == 2 || msi_strequal(argvW[i]+2, "n") ||
00848                msi_strequal(argvW[i] + 2, "uiet"))
00849             {
00850                 InstallUILevel = INSTALLUILEVEL_NONE;
00851             }
00852             else if(msi_strequal(argvW[i]+2, "b"))
00853             {
00854                 InstallUILevel = INSTALLUILEVEL_BASIC;
00855             }
00856             else if(msi_strequal(argvW[i]+2, "r"))
00857             {
00858                 InstallUILevel = INSTALLUILEVEL_REDUCED;
00859             }
00860             else if(msi_strequal(argvW[i]+2, "f"))
00861             {
00862                 InstallUILevel = INSTALLUILEVEL_FULL|INSTALLUILEVEL_ENDDIALOG;
00863             }
00864             else if(msi_strequal(argvW[i]+2, "n+"))
00865             {
00866                 InstallUILevel = INSTALLUILEVEL_NONE|INSTALLUILEVEL_ENDDIALOG;
00867             }
00868             else if(msi_strequal(argvW[i]+2, "b+"))
00869             {
00870                 InstallUILevel = INSTALLUILEVEL_BASIC|INSTALLUILEVEL_ENDDIALOG;
00871             }
00872             else if(msi_strequal(argvW[i]+2, "b-"))
00873             {
00874                 InstallUILevel = INSTALLUILEVEL_BASIC|INSTALLUILEVEL_PROGRESSONLY;
00875             }
00876             else if(msi_strequal(argvW[i]+2, "b+!"))
00877             {
00878                 InstallUILevel = INSTALLUILEVEL_BASIC|INSTALLUILEVEL_ENDDIALOG;
00879                 WINE_FIXME("Unknown modifier: !\n");
00880             }
00881             else
00882             {
00883                 fprintf(stderr, "Unknown option \"%s\" for UI level\n",
00884                      wine_dbgstr_w(argvW[i]+2));
00885             }
00886         }
00887         else if(msi_option_equal(argvW[i], "y"))
00888         {
00889             FunctionDllRegisterServer = TRUE;
00890             i++;
00891             if(i >= argc)
00892                 ShowUsage(1);
00893             WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
00894             DllName = argvW[i];
00895         }
00896         else if(msi_option_equal(argvW[i], "z"))
00897         {
00898             FunctionDllUnregisterServer = TRUE;
00899             i++;
00900             if(i >= argc)
00901                 ShowUsage(1);
00902             WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
00903             DllName = argvW[i];
00904         }
00905         else if(msi_option_equal(argvW[i], "help") || msi_option_equal(argvW[i], "?"))
00906         {
00907             ShowUsage(0);
00908         }
00909         else if(msi_option_equal(argvW[i], "m"))
00910         {
00911             FunctionUnknown = TRUE;
00912             WINE_FIXME("Unknown parameter /m\n");
00913         }
00914         else if(msi_option_equal(argvW[i], "D"))
00915         {
00916             FunctionUnknown = TRUE;
00917             WINE_FIXME("Unknown parameter /D\n");
00918         }
00919         else if (msi_option_equal(argvW[i], "V"))
00920         {
00921             FunctionServer = TRUE;
00922         }
00923         else
00924             StringListAppend(&property_list, argvW[i]);
00925     }
00926 
00927     /* start the GUI */
00928     MsiSetInternalUI(InstallUILevel, NULL);
00929 
00930     Properties = build_properties( property_list );
00931 
00932     if(FunctionInstallAdmin && FunctionPatch)
00933         FunctionInstall = FALSE;
00934 
00935     ReturnCode = 1;
00936     if(FunctionInstall)
00937     {
00938         if(IsProductCode(PackageName))
00939             ReturnCode = MsiConfigureProductExW(PackageName, 0, INSTALLSTATE_DEFAULT, Properties);
00940         else
00941             ReturnCode = MsiInstallProductW(PackageName, Properties);
00942     }
00943     else if(FunctionRepair)
00944     {
00945         if(IsProductCode(PackageName))
00946             WINE_FIXME("Product code treatment not implemented yet\n");
00947         else
00948             ReturnCode = MsiReinstallProductW(PackageName, RepairMode);
00949     }
00950     else if(FunctionAdvertise)
00951     {
00952         LPWSTR Transforms = build_transforms( property_list );
00953         ReturnCode = MsiAdvertiseProductW(PackageName, (LPWSTR) AdvertiseMode, Transforms, Language);
00954     }
00955     else if(FunctionPatch)
00956     {
00957         ReturnCode = MsiApplyPatchW(PatchFileName, PackageName, InstallType, Properties);
00958     }
00959     else if(FunctionDllRegisterServer)
00960     {
00961         ReturnCode = DoDllRegisterServer(DllName);
00962     }
00963     else if(FunctionDllUnregisterServer)
00964     {
00965         ReturnCode = DoDllUnregisterServer(DllName);
00966     }
00967     else if (FunctionRegServer)
00968     {
00969         ReturnCode = DoRegServer();
00970     }
00971     else if (FunctionUnregServer)
00972     {
00973         WINE_FIXME( "/unregserver not implemented yet, ignoring\n" );
00974     }
00975     else if (FunctionServer)
00976     {
00977         ReturnCode = DoService();
00978     }
00979     else if (FunctionUnknown)
00980     {
00981         WINE_FIXME( "Unknown function, ignoring\n" );
00982     }
00983     else
00984         ShowUsage(1);
00985 
00986     return ReturnCode;
00987 }

Generated on Thu May 24 2012 04:18:59 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.