diff --git a/reactos/dll/win32/msi/action.c b/reactos/dll/win32/msi/action.c index 5459051f226..cd1be045722 100644 --- a/reactos/dll/win32/msi/action.c +++ b/reactos/dll/win32/msi/action.c @@ -1756,6 +1756,45 @@ static BOOL process_overrides( MSIPACKAGE *package, int level ) return ret; } +static void disable_children( MSIFEATURE *feature, int level ) +{ + FeatureList *fl; + + LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry ) + { + if (!is_feature_selected( feature, level )) + { + TRACE("child %s (level %d request %d) follows disabled parent %s (level %d request %d)\n", + debugstr_w(fl->feature->Feature), fl->feature->Level, fl->feature->ActionRequest, + debugstr_w(feature->Feature), feature->Level, feature->ActionRequest); + + fl->feature->Level = feature->Level; + fl->feature->Action = INSTALLSTATE_UNKNOWN; + fl->feature->ActionRequest = INSTALLSTATE_UNKNOWN; + } + disable_children( fl->feature, level ); + } +} + +static void follow_parent( MSIFEATURE *feature ) +{ + FeatureList *fl; + + LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry ) + { + if (fl->feature->Attributes & msidbFeatureAttributesFollowParent) + { + TRACE("child %s (level %d request %d) follows parent %s (level %d request %d)\n", + debugstr_w(fl->feature->Feature), fl->feature->Level, fl->feature->ActionRequest, + debugstr_w(feature->Feature), feature->Level, feature->ActionRequest); + + fl->feature->Action = feature->Action; + fl->feature->ActionRequest = feature->ActionRequest; + } + follow_parent( fl->feature ); + } +} + UINT MSI_SetFeatureStates(MSIPACKAGE *package) { int level; @@ -1794,24 +1833,9 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package) /* disable child features of unselected parent or follow parent */ LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) { - FeatureList *fl; - - LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry ) - { - if (!is_feature_selected( feature, level )) - { - fl->feature->Action = INSTALLSTATE_UNKNOWN; - fl->feature->ActionRequest = INSTALLSTATE_UNKNOWN; - } - else if (fl->feature->Attributes & msidbFeatureAttributesFollowParent) - { - TRACE("feature %s (level %d request %d) follows parent %s (level %d request %d)\n", - debugstr_w(fl->feature->Feature), fl->feature->Level, fl->feature->ActionRequest, - debugstr_w(feature->Feature), feature->Level, feature->ActionRequest); - fl->feature->Action = feature->Action; - fl->feature->ActionRequest = feature->ActionRequest; - } - } + if (feature->Feature_Parent) continue; + disable_children( feature, level ); + follow_parent( feature ); } } else /* preselected */ @@ -1836,22 +1860,9 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package) } LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) { - FeatureList *fl; - - if (!is_feature_selected( feature, level )) continue; - - LIST_FOR_EACH_ENTRY( fl, &feature->Children, FeatureList, entry ) - { - if (fl->feature->Attributes & msidbFeatureAttributesFollowParent && - (!(feature->Attributes & msidbFeatureAttributesFavorAdvertise))) - { - TRACE("feature %s (level %d request %d) follows parent %s (level %d request %d)\n", - debugstr_w(fl->feature->Feature), fl->feature->Level, fl->feature->ActionRequest, - debugstr_w(feature->Feature), feature->Level, feature->ActionRequest); - fl->feature->Action = feature->Action; - fl->feature->ActionRequest = feature->ActionRequest; - } - } + if (feature->Feature_Parent) continue; + disable_children( feature, level ); + follow_parent( feature ); } } @@ -4404,7 +4415,16 @@ static UINT msi_publish_patches( MSIPACKAGE *package ) if (res != ERROR_SUCCESS) goto done; - res = RegSetValueExW( patch_key, szState, 0, REG_DWORD, (const BYTE *)&patch->state, sizeof(patch->state) ); + res = RegSetValueExW( patch_key, szState, 0, REG_DWORD, (const BYTE *)&patch->state, + sizeof(patch->state) ); + if (res != ERROR_SUCCESS) + { + RegCloseKey( patch_key ); + goto done; + } + + res = RegSetValueExW( patch_key, szUninstallable, 0, REG_DWORD, (const BYTE *)&patch->uninstallable, + sizeof(patch->uninstallable) ); RegCloseKey( patch_key ); if (res != ERROR_SUCCESS) goto done; diff --git a/reactos/dll/win32/msi/install.c b/reactos/dll/win32/msi/install.c index 5414715df8f..83d6badde82 100644 --- a/reactos/dll/win32/msi/install.c +++ b/reactos/dll/win32/msi/install.c @@ -1174,11 +1174,11 @@ UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature, static INT feature_cost( MSIFEATURE *feature ) { INT cost = 0; - MSICOMPONENT *comp; + ComponentList *cl; - LIST_FOR_EACH_ENTRY( comp, &feature->Components, MSICOMPONENT, entry ) + LIST_FOR_EACH_ENTRY( cl, &feature->Components, ComponentList, entry ) { - cost += comp->Cost; + cost += cl->component->Cost; } return cost; } diff --git a/reactos/dll/win32/msi/msi.c b/reactos/dll/win32/msi/msi.c index b97eb13907c..66bda28d081 100644 --- a/reactos/dll/win32/msi/msi.c +++ b/reactos/dll/win32/msi/msi.c @@ -1051,26 +1051,26 @@ done: return rc; } -static LPWSTR msi_reg_get_value(HKEY hkey, LPCWSTR name, DWORD *type) +static WCHAR *reg_get_value( HKEY hkey, const WCHAR *name, DWORD *type ) { - DWORD dval; LONG res; - WCHAR temp[20]; - static const WCHAR format[] = {'%','d',0}; + if ((res = RegQueryValueExW( hkey, name, NULL, type, NULL, NULL )) != ERROR_SUCCESS) return NULL; - res = RegQueryValueExW(hkey, name, NULL, type, NULL, NULL); - if (res != ERROR_SUCCESS) - return NULL; + if (*type == REG_SZ) return msi_reg_get_val_str( hkey, name ); + if (*type == REG_DWORD) + { + static const WCHAR fmt[] = {'%','u',0}; + WCHAR temp[11]; + DWORD val; - if (*type == REG_SZ) - return msi_reg_get_val_str(hkey, name); + if (!msi_reg_get_val_dword( hkey, name, &val )) return NULL; + sprintfW( temp, fmt, val ); + return strdupW( temp ); + } - if (!msi_reg_get_val_dword(hkey, name, &dval)) - return NULL; - - sprintfW(temp, format, dval); - return strdupW(temp); + ERR( "unhandled value type %u\n", *type ); + return NULL; } static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, @@ -1144,7 +1144,7 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, else if (!strcmpW( szAttribute, INSTALLPROPERTY_VERSIONSTRINGW )) szAttribute = display_version; - val = msi_reg_get_value(userdata, szAttribute, &type); + val = reg_get_value(userdata, szAttribute, &type); if (!val) val = empty; RegCloseKey(userdata); @@ -1178,7 +1178,7 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, goto done; } - val = msi_reg_get_value(source, szAttribute, &type); + val = reg_get_value(source, szAttribute, &type); if (!val) val = empty; @@ -1186,7 +1186,7 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, } else { - val = msi_reg_get_value(prodkey, szAttribute, &type); + val = reg_get_value(prodkey, szAttribute, &type); if (!val) val = empty; } @@ -1468,7 +1468,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid, !strcmpW( szProperty, INSTALLPROPERTY_REGOWNERW ) || !strcmpW( szProperty, INSTALLPROPERTY_INSTANCETYPEW )) { - val = msi_reg_get_value(props, package, &type); + val = reg_get_value(props, package, &type); if (!val) { if (prod || classes) @@ -1484,7 +1484,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid, else if (!strcmpW( szProperty, INSTALLPROPERTY_VERSIONSTRINGW )) szProperty = displayversion; - val = msi_reg_get_value(props, szProperty, &type); + val = reg_get_value(props, szProperty, &type); if (!val) val = strdupW(szEmpty); @@ -1509,7 +1509,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid, else if (dwContext == MSIINSTALLCONTEXT_MACHINE) hkey = classes; - val = msi_reg_get_value(hkey, szProperty, &type); + val = reg_get_value(hkey, szProperty, &type); if (!val) val = strdupW(szEmpty); @@ -1521,7 +1521,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid, { if (props) { - val = msi_reg_get_value(props, package, &type); + val = reg_get_value(props, package, &type); if (!val) goto done; @@ -1534,7 +1534,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid, r = msi_copy_outval(val, szValue, pcchValue); goto done; } - else if (props && (val = msi_reg_get_value(props, package, &type))) + else if (props && (val = reg_get_value(props, package, &type))) { msi_free(val); val = strdupW(five); @@ -1571,6 +1571,22 @@ done: return r; } +UINT WINAPI MsiGetPatchFileListA(LPCSTR szProductCode, LPCSTR szPatchList, + LPDWORD pcFiles, MSIHANDLE **pphFileRecords) +{ + FIXME("(%s, %s, %p, %p) stub!\n", debugstr_a(szProductCode), + debugstr_a(szPatchList), pcFiles, pphFileRecords); + return ERROR_FUNCTION_FAILED; +} + +UINT WINAPI MsiGetPatchFileListW(LPCWSTR szProductCode, LPCWSTR szPatchList, + LPDWORD pcFiles, MSIHANDLE **pphFileRecords) +{ + FIXME("(%s, %s, %p, %p) stub!\n", debugstr_w(szProductCode), + debugstr_w(szPatchList), pcFiles, pphFileRecords); + return ERROR_FUNCTION_FAILED; +} + UINT WINAPI MsiGetPatchInfoExA(LPCSTR szPatchCode, LPCSTR szProductCode, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, LPCSTR szProperty, LPSTR lpValue, DWORD *pcchValue) @@ -1650,7 +1666,7 @@ UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode, HKEY udpatch = 0, datakey = 0; HKEY prodpatches = 0; UINT r = ERROR_UNKNOWN_PRODUCT; - DWORD len; + DWORD len, type; LONG res; TRACE("(%s, %s, %s, %d, %s, %p, %p)\n", debugstr_w(szPatchCode), @@ -1742,7 +1758,7 @@ UINT WINAPI MsiGetPatchInfoExW(LPCWSTR szPatchCode, LPCWSTR szProductCode, } } - val = msi_reg_get_val_str(datakey, szProperty); + val = reg_get_value(datakey, szProperty, &type); if (!val) val = strdupW(szEmpty); @@ -2754,8 +2770,28 @@ UINT WINAPI MsiVerifyPackageW( LPCWSTR szPackage ) return r; } -static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent, - awstring* lpPathBuf, LPDWORD pcchBuf) +static BOOL open_userdata_comp_key( const WCHAR *comp, const WCHAR *usersid, MSIINSTALLCONTEXT ctx, + HKEY *hkey ) +{ + if (ctx & MSIINSTALLCONTEXT_MACHINE) + { + if (!MSIREG_OpenUserDataComponentKey( comp, szLocalSid, hkey, FALSE )) return TRUE; + } + if (ctx & (MSIINSTALLCONTEXT_USERMANAGED|MSIINSTALLCONTEXT_USERUNMANAGED)) + { + if (usersid && !strcmpiW( usersid, szAllSid )) + { + FIXME( "only looking at the current user\n" ); + usersid = NULL; + } + if (!MSIREG_OpenUserDataComponentKey( comp, usersid, hkey, FALSE )) return TRUE; + } + return FALSE; +} + +static INSTALLSTATE MSI_GetComponentPath( const WCHAR *szProduct, const WCHAR *szComponent, + const WCHAR *szUserSid, MSIINSTALLCONTEXT ctx, + awstring *lpPathBuf, DWORD *pcchBuf ) { static const WCHAR wininstaller[] = {'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0}; @@ -2773,20 +2809,20 @@ static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent, if (!squash_guid( szProduct, squashed_pc ) || !squash_guid( szComponent, squashed_comp )) return INSTALLSTATE_INVALIDARG; + if (szUserSid && ctx == MSIINSTALLCONTEXT_MACHINE) + return INSTALLSTATE_INVALIDARG; + state = INSTALLSTATE_UNKNOWN; - if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS || - MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS) + if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey )) { path = msi_reg_get_val_str( hkey, squashed_pc ); RegCloseKey(hkey); state = INSTALLSTATE_ABSENT; - if ((MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL, - &hkey, FALSE) == ERROR_SUCCESS || - MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, - NULL, &hkey, FALSE) == ERROR_SUCCESS) && + if ((!MSIREG_OpenInstallProps(szProduct, MSIINSTALLCONTEXT_MACHINE, NULL, &hkey, FALSE) || + !MSIREG_OpenUserDataProductKey(szProduct, MSIINSTALLCONTEXT_USERUNMANAGED, NULL, &hkey, FALSE)) && msi_reg_get_val_dword(hkey, wininstaller, &version) && GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES) { @@ -2796,16 +2832,12 @@ static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent, } if (state != INSTALLSTATE_LOCAL && - (MSIREG_OpenProductKey(szProduct, NULL, - MSIINSTALLCONTEXT_USERUNMANAGED, - &hkey, FALSE) == ERROR_SUCCESS || - MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, - &hkey, FALSE) == ERROR_SUCCESS)) + (!MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, &hkey, FALSE) || + !MSIREG_OpenProductKey(szProduct, NULL, MSIINSTALLCONTEXT_MACHINE, &hkey, FALSE))) { RegCloseKey(hkey); - if (MSIREG_OpenUserDataComponentKey(szComponent, szLocalSid, &hkey, FALSE) == ERROR_SUCCESS || - MSIREG_OpenUserDataComponentKey(szComponent, NULL, &hkey, FALSE) == ERROR_SUCCESS) + if (open_userdata_comp_key( szComponent, szUserSid, ctx, &hkey )) { msi_free(path); path = msi_reg_get_val_str( hkey, squashed_pc ); @@ -2832,51 +2864,63 @@ static INSTALLSTATE MSI_GetComponentPath(LPCWSTR szProduct, LPCWSTR szComponent, } /****************************************************************** - * MsiGetComponentPathW [MSI.@] + * MsiGetComponentPathExW [MSI.@] */ -INSTALLSTATE WINAPI MsiGetComponentPathW(LPCWSTR szProduct, LPCWSTR szComponent, - LPWSTR lpPathBuf, LPDWORD pcchBuf) +INSTALLSTATE WINAPI MsiGetComponentPathExW( LPCWSTR product, LPCWSTR comp, LPCWSTR usersid, + MSIINSTALLCONTEXT ctx, LPWSTR buf, LPDWORD buflen ) { awstring path; - TRACE("%s %s %p %p\n", debugstr_w(szProduct), debugstr_w(szComponent), lpPathBuf, pcchBuf); + TRACE( "%s %s %s 0x%x %p %p\n", debugstr_w(product), debugstr_w(comp), debugstr_w(usersid), + ctx, buf, buflen ); path.unicode = TRUE; - path.str.w = lpPathBuf; + path.str.w = buf; - return MSI_GetComponentPath( szProduct, szComponent, &path, pcchBuf ); + return MSI_GetComponentPath( product, comp, usersid, ctx, &path, buflen ); +} + +INSTALLSTATE WINAPI MsiGetComponentPathExA( LPCSTR product, LPCSTR comp, LPCSTR usersid, + MSIINSTALLCONTEXT ctx, LPSTR buf, LPDWORD buflen ) +{ + WCHAR *productW = NULL, *compW = NULL, *usersidW = NULL; + INSTALLSTATE r = INSTALLSTATE_UNKNOWN; + awstring path; + + TRACE( "%s %s %s 0x%x %p %p\n", debugstr_a(product), debugstr_a(comp), debugstr_a(usersid), + ctx, buf, buflen ); + + if (product && !(productW = strdupAtoW( product ))) return INSTALLSTATE_UNKNOWN; + if (comp && !(compW = strdupAtoW( comp ))) goto end; + if (usersid && !(usersidW = strdupAtoW( usersid ))) goto end; + + path.unicode = FALSE; + path.str.a = buf; + + r = MSI_GetComponentPath( productW, compW, usersidW, ctx, &path, buflen ); + +end: + msi_free( productW ); + msi_free( compW ); + msi_free( usersidW ); + + return r; +} + +/****************************************************************** + * MsiGetComponentPathW [MSI.@] + */ +INSTALLSTATE WINAPI MsiGetComponentPathW( LPCWSTR product, LPCWSTR comp, LPWSTR buf, LPDWORD buflen ) +{ + return MsiGetComponentPathExW( product, comp, szAllSid, MSIINSTALLCONTEXT_ALL, buf, buflen ); } /****************************************************************** * MsiGetComponentPathA [MSI.@] */ -INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR szProduct, LPCSTR szComponent, - LPSTR lpPathBuf, LPDWORD pcchBuf) +INSTALLSTATE WINAPI MsiGetComponentPathA( LPCSTR product, LPCSTR comp, LPSTR buf, LPDWORD buflen ) { - LPWSTR szwProduct, szwComponent = NULL; - INSTALLSTATE r = INSTALLSTATE_UNKNOWN; - awstring path; - - TRACE("%s %s %p %p\n", debugstr_a(szProduct), debugstr_a(szComponent), lpPathBuf, pcchBuf); - - szwProduct = strdupAtoW( szProduct ); - if( szProduct && !szwProduct) - goto end; - - szwComponent = strdupAtoW( szComponent ); - if( szComponent && !szwComponent ) - goto end; - - path.unicode = FALSE; - path.str.a = lpPathBuf; - - r = MSI_GetComponentPath( szwProduct, szwComponent, &path, pcchBuf ); - -end: - msi_free( szwProduct ); - msi_free( szwComponent ); - - return r; + return MsiGetComponentPathExA( product, comp, "s-1-1-0", MSIINSTALLCONTEXT_ALL, buf, buflen ); } static UINT query_feature_state( const WCHAR *product, const WCHAR *squashed, const WCHAR *usersid, @@ -3398,7 +3442,7 @@ static UINT MSI_ProvideQualifiedComponentEx(LPCWSTR szComponent, StringFromGUID2( &guid, comp, sizeof(comp)/sizeof(comp[0]) ); } - state = MSI_GetComponentPath( szProduct, comp, lpPathBuf, pcchPathBuf ); + state = MSI_GetComponentPath( szProduct, comp, szAllSid, MSIINSTALLCONTEXT_ALL, lpPathBuf, pcchPathBuf ); if (state == INSTALLSTATE_MOREDATA) return ERROR_MORE_DATA; if (state != INSTALLSTATE_LOCAL) return ERROR_FILE_NOT_FOUND; diff --git a/reactos/dll/win32/msi/msi.spec b/reactos/dll/win32/msi/msi.spec index 6f7266a71a7..4288c9d408f 100644 --- a/reactos/dll/win32/msi/msi.spec +++ b/reactos/dll/win32/msi/msi.spec @@ -20,8 +20,8 @@ 24 stdcall MsiDatabaseGenerateTransformW(long long wstr long long) 25 stdcall MsiDatabaseGetPrimaryKeysA(long str ptr) 26 stdcall MsiDatabaseGetPrimaryKeysW(long wstr ptr) -27 stdcall MsiDatabaseImportA(str str long) -28 stdcall MsiDatabaseImportW(wstr wstr long) +27 stdcall MsiDatabaseImportA(str str str) +28 stdcall MsiDatabaseImportW(wstr wstr wstr) 29 stdcall MsiDatabaseMergeA(long long str) 30 stdcall MsiDatabaseMergeW(long long wstr) 31 stdcall MsiDatabaseOpenViewA(long str ptr) @@ -189,10 +189,10 @@ 193 stdcall MsiUseFeatureExW(wstr wstr long long) 194 stdcall MsiGetFileVersionA(str ptr ptr ptr ptr) 195 stdcall MsiGetFileVersionW(wstr ptr ptr ptr ptr) -196 stdcall MsiLoadStringA(long long long long long) -197 stdcall MsiLoadStringW(long long long long long) -198 stdcall MsiMessageBoxA(long long long long long long) -199 stdcall MsiMessageBoxW(long long long long long long) +196 stdcall MsiLoadStringA(long long ptr long long) +197 stdcall MsiLoadStringW(long long ptr long long) +198 stdcall MsiMessageBoxA(long str str long long long) +199 stdcall MsiMessageBoxW(long wstr wstr long long long) 200 stdcall MsiDecomposeDescriptorA(str ptr ptr ptr ptr) 201 stdcall MsiDecomposeDescriptorW(wstr ptr ptr ptr ptr) 202 stdcall MsiProvideQualifiedComponentExA(str str long str long long ptr ptr) @@ -275,8 +275,8 @@ 279 stdcall MsiMessageBoxExA(long str str long long long long) 280 stdcall MsiMessageBoxExW(long wstr wstr long long long long) 281 stdcall MsiSetExternalUIRecord(ptr long ptr ptr) -282 stub MsiGetPatchFileListA -283 stub MsiGetPatchFileListW +282 stdcall MsiGetPatchFileListA(str str ptr ptr) +283 stdcall MsiGetPatchFileListW(wstr wstr ptr ptr) 284 stdcall MsiBeginTransactionA(str long ptr ptr) 285 stdcall MsiBeginTransactionW(wstr long ptr ptr) 286 stdcall MsiEndTransaction(long) @@ -286,8 +286,8 @@ 290 stdcall MsiEnumComponentsExW(wstr long long ptr ptr ptr ptr) 291 stdcall MsiEnumClientsExA(str str long long ptr ptr ptr ptr) 292 stdcall MsiEnumClientsExW(wstr wstr long long ptr ptr ptr ptr) -293 stub MsiGetComponentPathExA -294 stub MsiGetComponentPathExW +293 stdcall MsiGetComponentPathExA(str str str long ptr ptr) +294 stdcall MsiGetComponentPathExW(wstr wstr wstr long ptr ptr) 295 stub QueryInstanceCount @ stdcall -private DllCanUnloadNow() diff --git a/reactos/dll/win32/msi/msipriv.h b/reactos/dll/win32/msi/msipriv.h index bb6fbd2b717..2595e4dd2f7 100644 --- a/reactos/dll/win32/msi/msipriv.h +++ b/reactos/dll/win32/msi/msipriv.h @@ -206,6 +206,7 @@ typedef struct tagMSIPATCHINFO LPWSTR filename; LPWSTR localfile; MSIPATCHSTATE state; + DWORD uninstallable; BOOL delete_on_close; BOOL registered; UINT disk_id; @@ -1213,6 +1214,7 @@ static const WCHAR szData[] = {'D','a','t','a',0}; static const WCHAR szLangResource[] = {'\\','V','a','r','F','i','l','e','I','n','f','o','\\','T','r','a','n','s','l','a','t','i','o','n',0}; static const WCHAR szInstallLocation[] = {'I','n','s','t','a','l','l','L','o','c','a','t','i','o','n',0}; static const WCHAR szProperty[] = {'P','r','o','p','e','r','t','y',0}; +static const WCHAR szUninstallable[] = {'U','n','i','n','s','t','a','l','l','a','b','l','e',0}; /* memory allocation macro functions */ static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1); diff --git a/reactos/dll/win32/msi/patch.c b/reactos/dll/win32/msi/patch.c index 12f2efe30e6..c3d2299fd68 100644 --- a/reactos/dll/win32/msi/patch.c +++ b/reactos/dll/win32/msi/patch.c @@ -827,6 +827,38 @@ done: return r; } +static DWORD is_uninstallable( MSIDATABASE *db ) +{ + static const WCHAR query[] = { + 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ','F','R','O','M',' ', + '`','M','s','i','P','a','t','c','h','M','e','t','a','d','a','t','a','`',' ', + 'W','H','E','R','E',' ','`','C','o','m','p','a','n','y','`',' ','I','S',' ', + 'N','U','L','L',' ','A','N','D',' ','`','P','r','o','p','e','r','t','y','`','=', + '\'','A','l','l','o','w','R','e','m','o','v','a','l','\'',0}; + MSIQUERY *view; + MSIRECORD *rec; + DWORD ret = 0; + + if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS) return 0; + if (MSI_ViewExecute( view, 0 ) != ERROR_SUCCESS) + { + msiobj_release( &view->hdr ); + return 0; + } + + if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS) + { + const WCHAR *value = MSI_RecordGetString( rec, 1 ); + ret = atoiW( value ); + msiobj_release( &rec->hdr ); + } + + FIXME( "check other criteria\n" ); + + msiobj_release( &view->hdr ); + return ret; +} + static UINT msi_apply_patch_db( MSIPACKAGE *package, MSIDATABASE *patch_db, MSIPATCHINFO *patch ) { UINT i, r = ERROR_SUCCESS; @@ -852,7 +884,8 @@ static UINT msi_apply_patch_db( MSIPACKAGE *package, MSIDATABASE *patch_db, MSIP if (r != ERROR_SUCCESS) return r; - patch->state = MSIPATCHSTATE_APPLIED; + patch->uninstallable = is_uninstallable( patch_db ); + patch->state = MSIPATCHSTATE_APPLIED; list_add_tail( &package->patches, &patch->entry ); return ERROR_SUCCESS; } diff --git a/reactos/dll/win32/msi/table.c b/reactos/dll/win32/msi/table.c index af077dbc6d6..312e26c406e 100644 --- a/reactos/dll/win32/msi/table.c +++ b/reactos/dll/win32/msi/table.c @@ -405,13 +405,11 @@ static UINT read_table_from_storage( MSIDATABASE *db, MSITABLE *t, IStorage *stg goto err; } - t->row_count = rawsize / row_size; - t->data = msi_alloc_zero( t->row_count * sizeof (USHORT*) ); - if( !t->data ) - goto err; - t->data_persistent = msi_alloc_zero( t->row_count * sizeof(BOOL)); - if ( !t->data_persistent ) - goto err; + if ((t->row_count = rawsize / row_size)) + { + if (!(t->data = msi_alloc_zero( t->row_count * sizeof(USHORT *) ))) goto err; + if (!(t->data_persistent = msi_alloc_zero( t->row_count * sizeof(BOOL) ))) goto err; + } /* transpose all the data */ TRACE("Transposing data from %d rows\n", t->row_count ); diff --git a/reactos/dll/win32/msi/tokenize.c b/reactos/dll/win32/msi/tokenize.c index d21d599bf94..52dd3dffde1 100644 --- a/reactos/dll/win32/msi/tokenize.c +++ b/reactos/dll/win32/msi/tokenize.c @@ -180,6 +180,21 @@ static const char isIdChar[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Fx */ }; +/* +** WCHAR safe version of isdigit() +*/ +static inline int isDigit(WCHAR c) +{ + return c >= '0' && c <= '9'; +} + +/* +** WCHAR safe version of isspace(), except '\r' +*/ +static inline int isSpace(WCHAR c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\f'; +} /* ** Return the length of the token that begins at z[0]. Return @@ -192,7 +207,7 @@ int sqliteGetToken(const WCHAR *z, int *tokenType, int *skip){ *skip = 0; switch( *z ){ case ' ': case '\t': case '\n': case '\f': - for(i=1; isspace(z[i]) && z[i] != '\r'; i++){} + for(i=1; isSpace(z[i]); i++){} *tokenType = TK_SPACE; return i; case '-': @@ -258,7 +273,7 @@ int sqliteGetToken(const WCHAR *z, int *tokenType, int *skip){ return i; } case '.': - if( !isdigit(z[1]) ){ + if( !isDigit(z[1]) ){ *tokenType = TK_DOT; return 1; } @@ -266,7 +281,7 @@ int sqliteGetToken(const WCHAR *z, int *tokenType, int *skip){ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': *tokenType = TK_INTEGER; - for(i=1; isdigit(z[i]); i++){} + for(i=1; isDigit(z[i]); i++){} return i; case '[': for(i=1; z[i] && z[i-1]!=']'; i++){} diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 1dd6024e9eb..c4512fef64c 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -112,7 +112,7 @@ reactos/dll/win32/msg711.acm # Synced to WineStaging-2.2 reactos/dll/win32/msgsm32.acm # Synced to WineStaging-1.9.11 reactos/dll/win32/mshtml # Synced to WineStaging-1.7.55 reactos/dll/win32/mshtml.tlb # Synced to WineStaging-1.7.55 -reactos/dll/win32/msi # Synced to WineStaging-2.2 +reactos/dll/win32/msi # Synced to WineStaging-2.9 reactos/dll/win32/msimg32 # Synced to WineStaging-1.9.11 reactos/dll/win32/msimtf # Synced to WineStaging-1.9.23 reactos/dll/win32/msisip # Synced to WineStaging-1.9.11