From: Christoph von Wittich Date: Tue, 22 Dec 2009 09:28:03 +0000 (+0000) Subject: sync msi with wine 1.1.35 X-Git-Tag: backups/aicom-network-stable@46924~219 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=67cca04bc061c7530691db197b2f8ee58a16edc4 sync msi with wine 1.1.35 svn path=/trunk/; revision=44693 --- diff --git a/reactos/dll/win32/msi/action.c b/reactos/dll/win32/msi/action.c index 0755f428675..79047704173 100644 --- a/reactos/dll/win32/msi/action.c +++ b/reactos/dll/win32/msi/action.c @@ -5008,12 +5008,30 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) FIXME("Not removing environment variable on uninstall!\n"); size = 0; + type = REG_SZ; res = RegQueryValueExW(env, name, NULL, &type, NULL, &size); if ((res != ERROR_SUCCESS && res != ERROR_FILE_NOT_FOUND) || (res == ERROR_SUCCESS && type != REG_SZ && type != REG_EXPAND_SZ)) goto done; - if (res != ERROR_FILE_NOT_FOUND) + if ((res == ERROR_FILE_NOT_FOUND || !(flags & ENV_MOD_MASK))) + { + /* Nothing to do. */ + if (!value) + { + res = ERROR_SUCCESS; + goto done; + } + + size = (lstrlenW(value) + 1) * sizeof(WCHAR); + newval = strdupW(value); + if (!newval) + { + res = ERROR_OUTOFMEMORY; + goto done; + } + } + else { if (flags & ENV_ACT_SETABSENT) { @@ -5038,8 +5056,18 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) goto done; } - size += (lstrlenW(value) + 1) * sizeof(WCHAR); - newval = msi_alloc(size); + size = (lstrlenW(data) + 1) * sizeof(WCHAR); + if (flags & ENV_MOD_MASK) + { + DWORD mod_size; + int multiplier = 0; + if (flags & ENV_MOD_APPEND) multiplier++; + if (flags & ENV_MOD_PREFIX) multiplier++; + mod_size = (lstrlenW(value) + 1) * multiplier; + size += mod_size * sizeof(WCHAR); + } + + newval = msi_alloc(size); ptr = newval; if (!newval) { @@ -5047,37 +5075,20 @@ static UINT ITERATE_WriteEnvironmentString( MSIRECORD *rec, LPVOID param ) goto done; } - if (!(flags & ENV_MOD_MASK)) - lstrcpyW(newval, value); - else + if (flags & ENV_MOD_PREFIX) { - if (flags & ENV_MOD_PREFIX) - { - lstrcpyW(newval, value); - lstrcatW(newval, szSemiColon); - ptr = newval + lstrlenW(value) + 1; - } + lstrcpyW(newval, value); + lstrcatW(newval, szSemiColon); + ptr = newval + lstrlenW(value) + 1; + } - lstrcpyW(ptr, data); + lstrcpyW(ptr, data); - if (flags & ENV_MOD_APPEND) - { - lstrcatW(newval, szSemiColon); - lstrcatW(newval, value); - } - } - } - else if (value) - { - size = (lstrlenW(value) + 1) * sizeof(WCHAR); - newval = msi_alloc(size); - if (!newval) + if (flags & ENV_MOD_APPEND) { - res = ERROR_OUTOFMEMORY; - goto done; + lstrcatW(newval, szSemiColon); + lstrcatW(newval, value); } - - lstrcpyW(newval, value); } if (newval) @@ -5288,6 +5299,11 @@ static BOOL move_files_wildcard(LPWSTR source, LPWSTR dest, int options) goto done; } + /* file->dest may be shorter after the reallocation, so add a NULL + * terminator. This is needed for the call to strrchrW, as there will no + * longer be a NULL terminator within the bounds of the allocation in this case. + */ + file->dest[size - 1] = '\0'; lstrcpyW(strrchrW(file->dest, '\\') + 1, file->destname); while (!list_empty(&files.entry)) diff --git a/reactos/dll/win32/msi/alter.c b/reactos/dll/win32/msi/alter.c index a62b13e9352..93d322bed7f 100644 --- a/reactos/dll/win32/msi/alter.c +++ b/reactos/dll/win32/msi/alter.c @@ -125,7 +125,10 @@ static UINT alter_add_column(MSIALTERVIEW *av) return r; if (check_column_exists(av->db, av->colinfo->table, av->colinfo->column)) + { + columns->ops->delete(columns); return ERROR_BAD_QUERY_SYNTAX; + } r = MSI_OpenQuery(av->db, &view, query, av->colinfo->table, av->colinfo->column); if (r == ERROR_SUCCESS) diff --git a/reactos/dll/win32/msi/appsearch.c b/reactos/dll/win32/msi/appsearch.c index 95daabb40bb..b99b4f52085 100644 --- a/reactos/dll/win32/msi/appsearch.c +++ b/reactos/dll/win32/msi/appsearch.c @@ -739,6 +739,7 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue, size_t dirLen = lstrlenW(dir), fileLen = lstrlenW(sig->File); WCHAR subpath[MAX_PATH]; WCHAR *buf; + DWORD len; static const WCHAR starDotStarW[] = { '*','.','*',0 }; @@ -753,7 +754,8 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue, * here. Add two because we might need to add a backslash if the dir name * isn't backslash-terminated. */ - buf = msi_alloc( (dirLen + max(fileLen, strlenW(starDotStarW)) + 2) * sizeof(WCHAR)); + len = dirLen + max(fileLen, strlenW(starDotStarW)) + 2; + buf = msi_alloc(len * sizeof(WCHAR)); if (!buf) return ERROR_OUTOFMEMORY; @@ -815,7 +817,7 @@ static UINT ACTION_RecurseSearchDirectory(MSIPACKAGE *package, LPWSTR *appValue, } } - if (!*appValue) + if (*appValue != buf) msi_free(buf); return rc; diff --git a/reactos/dll/win32/msi/automation.c b/reactos/dll/win32/msi/automation.c index 3b6dd2debe2..5305f9c9d47 100644 --- a/reactos/dll/win32/msi/automation.c +++ b/reactos/dll/win32/msi/automation.c @@ -1534,6 +1534,760 @@ static void variant_from_registry_value(VARIANT *pVarResult, DWORD dwType, LPBYT } } +static HRESULT InstallerImpl_CreateRecord(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + HRESULT hr; + VARIANTARG varg0; + MSIHANDLE hrec; + IDispatch* dispatch; + + if (!(wFlags & DISPATCH_METHOD)) + return DISP_E_MEMBERNOTFOUND; + + VariantInit(&varg0); + hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); + if (FAILED(hr)) + return hr; + + V_VT(pVarResult) = VT_DISPATCH; + + hrec = MsiCreateRecord(V_I4(&varg0)); + if (!hrec) + return DISP_E_EXCEPTION; + + hr = create_automation_object(hrec, NULL, (LPVOID*)&dispatch, + &DIID_Record, RecordImpl_Invoke, NULL, 0); + if (SUCCEEDED(hr)) + V_DISPATCH(pVarResult) = dispatch; + + return hr; +} + +static HRESULT InstallerImpl_OpenPackage(AutomationObject* This, + WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + UINT ret; + HRESULT hr; + MSIHANDLE hpkg; + IDispatch* dispatch; + VARIANTARG varg0, varg1; + + if (!(wFlags & DISPATCH_METHOD)) + return DISP_E_MEMBERNOTFOUND; + + if (pDispParams->cArgs == 0) + return DISP_E_TYPEMISMATCH; + + if (V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1]) != VT_BSTR) + return DISP_E_TYPEMISMATCH; + + VariantInit(&varg0); + hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); + if (FAILED(hr)) + return hr; + + VariantInit(&varg1); + if (pDispParams->cArgs == 2) + { + hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr); + if (FAILED(hr)) + goto done; + } + else + { + V_VT(&varg1) = VT_I4; + V_I4(&varg1) = 0; + } + + V_VT(pVarResult) = VT_DISPATCH; + + ret = MsiOpenPackageExW(V_BSTR(&varg0), V_I4(&varg1), &hpkg); + if (ret != ERROR_SUCCESS) + { + hr = DISP_E_EXCEPTION; + goto done; + } + + hr = create_session(hpkg, (IDispatch *)This, &dispatch); + if (SUCCEEDED(hr)) + V_DISPATCH(pVarResult) = dispatch; + +done: + VariantClear(&varg0); + VariantClear(&varg1); + return hr; +} + +static HRESULT InstallerImpl_OpenProduct(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + HRESULT hr; + VARIANTARG varg0; + + if (!(wFlags & DISPATCH_METHOD)) + return DISP_E_MEMBERNOTFOUND; + + VariantInit(&varg0); + hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); + if (FAILED(hr)) + return hr; + + FIXME("%s\n", debugstr_w(V_BSTR(&varg0))); + + VariantInit(pVarResult); + + VariantClear(&varg0); + return S_OK; +} + +static HRESULT InstallerImpl_OpenDatabase(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + UINT ret; + HRESULT hr; + MSIHANDLE hdb; + IDispatch* dispatch; + VARIANTARG varg0, varg1; + + if (!(wFlags & DISPATCH_METHOD)) + return DISP_E_MEMBERNOTFOUND; + + VariantInit(&varg0); + hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); + if (FAILED(hr)) + return hr; + + VariantInit(&varg1); + hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr); + if (FAILED(hr)) + goto done; + + V_VT(pVarResult) = VT_DISPATCH; + + ret = MsiOpenDatabaseW(V_BSTR(&varg0), V_BSTR(&varg1), &hdb); + if (ret != ERROR_SUCCESS) + { + hr = DISP_E_EXCEPTION; + goto done; + } + + hr = create_automation_object(hdb, NULL, (LPVOID *)&dispatch, + &DIID_Database, DatabaseImpl_Invoke, NULL, 0); + if (SUCCEEDED(hr)) + V_DISPATCH(pVarResult) = dispatch; + +done: + VariantClear(&varg0); + VariantClear(&varg1); + return hr; +} + +static HRESULT InstallerImpl_SummaryInformation(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + if (!(wFlags & DISPATCH_METHOD)) + return DISP_E_MEMBERNOTFOUND; + + FIXME("\n"); + + VariantInit(pVarResult); + return S_OK; +} + +static HRESULT InstallerImpl_UILevel(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + HRESULT hr; + VARIANTARG varg0; + INSTALLUILEVEL ui; + + if (!(wFlags & DISPATCH_PROPERTYPUT) && !(wFlags & DISPATCH_PROPERTYGET)) + return DISP_E_MEMBERNOTFOUND; + + if (wFlags & DISPATCH_PROPERTYPUT) + { + VariantInit(&varg0); + hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); + if (FAILED(hr)) + return hr; + + ui = MsiSetInternalUI(V_I4(&varg0), NULL); + if (ui == INSTALLUILEVEL_NOCHANGE) + return DISP_E_EXCEPTION; + } + else if (wFlags & DISPATCH_PROPERTYGET) + { + ui = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL); + if (ui == INSTALLUILEVEL_NOCHANGE) + return DISP_E_EXCEPTION; + + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = ui; + } + + return S_OK; +} + +static HRESULT InstallerImpl_EnableLog(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + if (!(wFlags & DISPATCH_METHOD)) + return DISP_E_MEMBERNOTFOUND; + + FIXME("\n"); + + VariantInit(pVarResult); + return S_OK; +} + +static HRESULT InstallerImpl_InstallProduct(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + UINT ret; + HRESULT hr; + VARIANTARG varg0, varg1; + + if (!(wFlags & DISPATCH_METHOD)) + return DISP_E_MEMBERNOTFOUND; + + VariantInit(&varg0); + hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); + if (FAILED(hr)) + return hr; + + VariantInit(&varg1); + hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr); + if (FAILED(hr)) + goto done; + + ret = MsiInstallProductW(V_BSTR(&varg0), V_BSTR(&varg1)); + if (ret != ERROR_SUCCESS) + { + hr = DISP_E_EXCEPTION; + goto done; + } + +done: + VariantClear(&varg0); + VariantClear(&varg1); + return hr; +} + +static HRESULT InstallerImpl_Version(WORD wFlags, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + HRESULT hr; + DLLVERSIONINFO verinfo; + WCHAR version[MAX_PATH]; + + static const WCHAR format[] = { + '%','d','.','%','d','.','%','d','.','%','d',0}; + + if (!(wFlags & DISPATCH_PROPERTYGET)) + return DISP_E_MEMBERNOTFOUND; + + verinfo.cbSize = sizeof(DLLVERSIONINFO); + hr = DllGetVersion(&verinfo); + if (FAILED(hr)) + return hr; + + sprintfW(version, format, verinfo.dwMajorVersion, verinfo.dwMinorVersion, + verinfo.dwBuildNumber, verinfo.dwPlatformID); + + V_VT(pVarResult) = VT_BSTR; + V_BSTR(pVarResult) = SysAllocString(version); + return S_OK; +} + +static HRESULT InstallerImpl_LastErrorRecord(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + if (!(wFlags & DISPATCH_METHOD)) + return DISP_E_MEMBERNOTFOUND; + + FIXME("\n"); + + VariantInit(pVarResult); + return S_OK; +} + +static HRESULT InstallerImpl_RegistryValue(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + UINT ret; + HKEY hkey = NULL; + HRESULT hr; + UINT posValue; + DWORD type, size; + LPWSTR szString = NULL; + VARIANTARG varg0, varg1, varg2; + + if (!(wFlags & DISPATCH_METHOD)) + return DISP_E_MEMBERNOTFOUND; + + VariantInit(&varg0); + hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); + if (FAILED(hr)) + return hr; + + VariantInit(&varg1); + hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr); + if (FAILED(hr)) + goto done; + + /* Save valuePos so we can save puArgErr if we are unable to do our type + * conversions. + */ + posValue = 2; + VariantInit(&varg2); + hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg2); + if (FAILED(hr)) + goto done; + + if (V_I4(&varg0) >= REG_INDEX_CLASSES_ROOT && + V_I4(&varg0) <= REG_INDEX_DYN_DATA) + { + V_I4(&varg0) |= (UINT_PTR)HKEY_CLASSES_ROOT; + } + + ret = RegOpenKeyW((HKEY)(UINT_PTR)V_I4(&varg0), V_BSTR(&varg1), &hkey); + + /* Only VT_EMPTY case can do anything if the key doesn't exist. */ + if (ret != ERROR_SUCCESS && V_VT(&varg2) != VT_EMPTY) + { + hr = DISP_E_BADINDEX; + goto done; + } + + /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */ + switch (V_VT(&varg2)) + { + /* Return VT_BOOL clarifying whether registry key exists or not. */ + case VT_EMPTY: + V_VT(pVarResult) = VT_BOOL; + V_BOOL(pVarResult) = (ret == ERROR_SUCCESS); + break; + + /* Return the value of specified key if it exists. */ + case VT_BSTR: + ret = RegQueryValueExW(hkey, V_BSTR(&varg2), + NULL, NULL, NULL, &size); + if (ret != ERROR_SUCCESS) + { + hr = DISP_E_BADINDEX; + goto done; + } + + szString = msi_alloc(size); + if (!szString) + { + hr = E_OUTOFMEMORY; + goto done; + } + + ret = RegQueryValueExW(hkey, V_BSTR(&varg2), NULL, + &type, (LPBYTE)szString, &size); + if (ret != ERROR_SUCCESS) + { + msi_free(szString); + hr = DISP_E_BADINDEX; + goto done; + } + + variant_from_registry_value(pVarResult, type, + (LPBYTE)szString, size); + msi_free(szString); + break; + + /* Try to make it into VT_I4, can use VariantChangeType for this. */ + default: + hr = VariantChangeType(&varg2, &varg2, 0, VT_I4); + if (FAILED(hr)) + { + if (hr == DISP_E_TYPEMISMATCH) + *puArgErr = posValue; + + goto done; + } + + /* Retrieve class name or maximum value name or subkey name size. */ + if (!V_I4(&varg2)) + ret = RegQueryInfoKeyW(hkey, NULL, &size, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL); + else if (V_I4(&varg2) > 0) + ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, &size, NULL, NULL, NULL); + else /* V_I4(&varg2) < 0 */ + ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, &size, + NULL, NULL, NULL, NULL, NULL, NULL); + + if (ret != ERROR_SUCCESS) + goto done; + + szString = msi_alloc(++size * sizeof(WCHAR)); + if (!szString) + { + hr = E_OUTOFMEMORY; + goto done; + } + + if (!V_I4(&varg2)) + ret = RegQueryInfoKeyW(hkey, szString, &size,NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL); + else if (V_I4(&varg2) > 0) + ret = RegEnumValueW(hkey, V_I4(&varg2)-1, szString, + &size, 0, 0, NULL, NULL); + else /* V_I4(&varg2) < 0 */ + ret = RegEnumKeyW(hkey, -1 - V_I4(&varg2), szString, size); + + if (ret == ERROR_SUCCESS) + { + V_VT(pVarResult) = VT_BSTR; + V_BSTR(pVarResult) = SysAllocString(szString); + } + + msi_free(szString); + } + +done: + VariantClear(&varg0); + VariantClear(&varg1); + VariantClear(&varg2); + RegCloseKey(hkey); + return hr; +} + +static HRESULT InstallerImpl_Environment(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + if (!(wFlags & DISPATCH_METHOD)) + return DISP_E_MEMBERNOTFOUND; + + FIXME("\n"); + + VariantInit(pVarResult); + return S_OK; +} + +static HRESULT InstallerImpl_FileAttributes(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + if (!(wFlags & DISPATCH_METHOD)) + return DISP_E_MEMBERNOTFOUND; + + FIXME("\n"); + + VariantInit(pVarResult); + return S_OK; +} + +static HRESULT InstallerImpl_FileSize(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + if (!(wFlags & DISPATCH_METHOD)) + return DISP_E_MEMBERNOTFOUND; + + FIXME("\n"); + + VariantInit(pVarResult); + return S_OK; +} + +static HRESULT InstallerImpl_FileVersion(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + if (!(wFlags & DISPATCH_METHOD)) + return DISP_E_MEMBERNOTFOUND; + + FIXME("\n"); + + VariantInit(pVarResult); + return S_OK; +} + +static HRESULT InstallerImpl_ProductState(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + HRESULT hr; + VARIANTARG varg0; + + if (!(wFlags & DISPATCH_PROPERTYGET)) + return DISP_E_MEMBERNOTFOUND; + + VariantInit(&varg0); + hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); + if (FAILED(hr)) + return hr; + + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = MsiQueryProductStateW(V_BSTR(&varg0)); + + VariantClear(&varg0); + return S_OK; +} + +static HRESULT InstallerImpl_ProductInfo(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + UINT ret; + HRESULT hr; + DWORD size; + LPWSTR str = NULL; + VARIANTARG varg0, varg1; + + if (!(wFlags & DISPATCH_PROPERTYGET)) + return DISP_E_MEMBERNOTFOUND; + + VariantInit(&varg0); + hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); + if (FAILED(hr)) + return hr; + + VariantInit(&varg1); + hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr); + if (FAILED(hr)) + goto done; + + V_VT(pVarResult) = VT_BSTR; + V_BSTR(pVarResult) = NULL; + + ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), NULL, &size); + if (ret != ERROR_SUCCESS) + { + hr = DISP_E_EXCEPTION; + goto done; + } + + str = msi_alloc(++size * sizeof(WCHAR)); + if (!str) + { + hr = E_OUTOFMEMORY; + goto done; + } + + ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), str, &size); + if (ret != ERROR_SUCCESS) + { + hr = DISP_E_EXCEPTION; + goto done; + } + + V_BSTR(pVarResult) = SysAllocString(str); + hr = S_OK; + +done: + msi_free(str); + VariantClear(&varg0); + VariantClear(&varg1); + return hr; +} + +static void cleanup_products(IDispatch* dispatch, ULONG count) +{ + UINT i; + ListData* ldata = private_data((AutomationObject *)dispatch); + + for (i = 0; i < count - 1; i++) + VariantClear(&ldata->pVars[i]); + + ldata->ulCount = 0; + msi_free(ldata->pVars); + + IDispatch_Release(dispatch); +} + +static HRESULT InstallerImpl_Products(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + UINT ret; + HRESULT hr; + ULONG idx = 0; + ListData *ldata; + IDispatch *dispatch; + WCHAR product[GUID_SIZE]; + + if (!(wFlags & DISPATCH_PROPERTYGET)) + return DISP_E_MEMBERNOTFOUND; + + /* Find number of products. */ + while ((ret = MsiEnumProductsW(idx, product)) == ERROR_SUCCESS) + idx++; + + if (ret != ERROR_NO_MORE_ITEMS) + return DISP_E_EXCEPTION; + + V_VT(pVarResult) = VT_DISPATCH; + hr = create_automation_object(0, NULL, (LPVOID*)&dispatch, + &DIID_StringList, ListImpl_Invoke, + ListImpl_Free, sizeof(ListData)); + if (FAILED(hr)) + return hr; + + V_DISPATCH(pVarResult) = dispatch; + + /* Save product strings. */ + ldata = private_data((AutomationObject *)dispatch); + ldata->ulCount = 0; + ldata->pVars = msi_alloc_zero(sizeof(VARIANT) * idx); + if (!ldata->pVars) + { + IDispatch_Release(dispatch); + return E_OUTOFMEMORY; + } + + ldata->ulCount = idx; + for (idx = 0; idx < ldata->ulCount; idx++) + { + ret = MsiEnumProductsW(idx, product); + if (ret != ERROR_SUCCESS) + { + cleanup_products(dispatch, idx - 1); + return DISP_E_EXCEPTION; + } + + VariantInit(&ldata->pVars[idx]); + V_VT(&ldata->pVars[idx]) = VT_BSTR; + V_BSTR(&ldata->pVars[idx]) = SysAllocString(product); + } + + return S_OK; +} + +static HRESULT InstallerImpl_RelatedProducts(WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + UINT ret; + ULONG idx; + HRESULT hr; + ListData *ldata; + VARIANTARG varg0; + IDispatch* dispatch; + WCHAR product[GUID_SIZE]; + + if (!(wFlags & DISPATCH_PROPERTYGET)) + return DISP_E_MEMBERNOTFOUND; + + VariantInit(&varg0); + hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); + if (FAILED(hr)) + return hr; + + /* Find number of related products. */ + idx = 0; + do + { + ret = MsiEnumRelatedProductsW(V_BSTR(&varg0), 0, idx, product); + if (ret == ERROR_SUCCESS) + idx++; + } while (ret == ERROR_SUCCESS); + + if (ret != ERROR_NO_MORE_ITEMS) + { + hr = DISP_E_EXCEPTION; + goto done; + } + + V_VT(pVarResult) = VT_DISPATCH; + + hr = create_automation_object(0, NULL, (LPVOID*)&dispatch, + &DIID_StringList, ListImpl_Invoke, + ListImpl_Free, sizeof(ListData)); + if (FAILED(hr)) + goto done; + + V_DISPATCH(pVarResult) = dispatch; + + /* Save product strings. */ + ldata = private_data((AutomationObject *)dispatch); + ldata->pVars = msi_alloc(sizeof(VARIANT) * idx); + if (!ldata->pVars) + { + IDispatch_Release(dispatch); + hr = E_OUTOFMEMORY; + goto done; + } + + ldata->ulCount = idx; + for (idx = 0; idx < ldata->ulCount; idx++) + { + ret = MsiEnumRelatedProductsW(V_BSTR(&varg0), 0, idx, product); + if (ret != ERROR_SUCCESS) + { + cleanup_products(dispatch, idx - 1); + hr = DISP_E_EXCEPTION; + goto done; + } + + VariantInit(&ldata->pVars[idx]); + V_VT(&ldata->pVars[idx]) = VT_BSTR; + V_BSTR(&ldata->pVars[idx]) = SysAllocString(product); + } + + hr = S_OK; + +done: + VariantClear(&varg0); + return hr; +} + static HRESULT WINAPI InstallerImpl_Invoke( AutomationObject* This, DISPID dispIdMember, @@ -1545,405 +2299,93 @@ static HRESULT WINAPI InstallerImpl_Invoke( EXCEPINFO* pExcepInfo, UINT* puArgErr) { - MSIHANDLE msiHandle; - IDispatch *pDispatch = NULL; - UINT ret; - VARIANTARG varg0, varg1, varg2; - HRESULT hr; - LPWSTR szString = NULL; - DWORD dwSize = 0; - INSTALLUILEVEL ui; - - VariantInit(&varg0); - VariantInit(&varg1); - VariantInit(&varg2); - switch (dispIdMember) { case DISPID_INSTALLER_CREATERECORD: - if (wFlags & DISPATCH_METHOD) - { - hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); - if (FAILED(hr)) return hr; - V_VT(pVarResult) = VT_DISPATCH; - if ((msiHandle = MsiCreateRecord(V_I4(&varg0)))) - { - if (SUCCEEDED(hr = create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_Record, RecordImpl_Invoke, NULL, 0))) - V_DISPATCH(pVarResult) = pDispatch; - else - ERR("Failed to create Record object, hresult 0x%08x\n", hr); - } - else - { - ERR("MsiCreateRecord failed\n"); - return DISP_E_EXCEPTION; - } - } - else return DISP_E_MEMBERNOTFOUND; - break; + return InstallerImpl_CreateRecord(wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); case DISPID_INSTALLER_OPENPACKAGE: - if (wFlags & DISPATCH_METHOD) - { - hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); - if (FAILED(hr)) return hr; - hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr); - if (FAILED(hr)) - { - VariantClear(&varg0); - return hr; - } - V_VT(pVarResult) = VT_DISPATCH; - if ((ret = MsiOpenPackageExW(V_BSTR(&varg0), V_I4(&varg1), &msiHandle)) == ERROR_SUCCESS) - { - if (SUCCEEDED(hr = create_session(msiHandle, (IDispatch *)This, &pDispatch))) - V_DISPATCH(pVarResult) = pDispatch; - else - ERR("Failed to create Session object, hresult 0x%08x\n", hr); - } - else - { - VariantClear(&varg0); - ERR("MsiOpenPackageEx returned %d\n", ret); - return DISP_E_EXCEPTION; - } - } - else return DISP_E_MEMBERNOTFOUND; - break; + return InstallerImpl_OpenPackage(This, wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); - case DISPID_INSTALLER_OPENDATABASE: - if (wFlags & DISPATCH_METHOD) - { - hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); - if (FAILED(hr)) return hr; + case DISPID_INSTALLER_OPENPRODUCT: + return InstallerImpl_OpenProduct(wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); - hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr); - if (FAILED(hr)) - { - VariantClear(&varg0); - return hr; - } + case DISPID_INSTALLER_OPENDATABASE: + return InstallerImpl_OpenDatabase(wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); - V_VT(pVarResult) = VT_DISPATCH; - if ((ret = MsiOpenDatabaseW(V_BSTR(&varg0), V_BSTR(&varg1), &msiHandle)) == ERROR_SUCCESS) - { - hr = create_automation_object(msiHandle, NULL, (LPVOID *)&pDispatch, - &DIID_Database, DatabaseImpl_Invoke, NULL, 0); - if (SUCCEEDED(hr)) - V_DISPATCH(pVarResult) = pDispatch; - else - ERR("Failed to create Database object: 0x%08x\n", hr); - } - else - { - VariantClear(&varg0); - VariantClear(&varg1); - ERR("MsiOpenDatabase returned %d\n", ret); - return DISP_E_EXCEPTION; - } - } - else return DISP_E_MEMBERNOTFOUND; - break; + case DISPID_INSTALLER_SUMMARYINFORMATION: + return InstallerImpl_SummaryInformation(wFlags, pDispParams, + pVarResult, pExcepInfo, + puArgErr); case DISPID_INSTALLER_UILEVEL: - if (wFlags & DISPATCH_PROPERTYPUT) - { - hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); - if (FAILED(hr)) return hr; - if ((ui = MsiSetInternalUI(V_I4(&varg0), NULL) == INSTALLUILEVEL_NOCHANGE)) - { - ERR("MsiSetInternalUI failed\n"); - return DISP_E_EXCEPTION; - } - } - else if (wFlags & DISPATCH_PROPERTYGET) - { - if ((ui = MsiSetInternalUI(INSTALLUILEVEL_NOCHANGE, NULL) == INSTALLUILEVEL_NOCHANGE)) - { - ERR("MsiSetInternalUI failed\n"); - return DISP_E_EXCEPTION; - } + return InstallerImpl_UILevel(wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); - V_VT(pVarResult) = VT_I4; - V_I4(pVarResult) = ui; - } - else return DISP_E_MEMBERNOTFOUND; - break; + case DISPID_INSTALLER_ENABLELOG: + return InstallerImpl_EnableLog(wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); case DISPID_INSTALLER_INSTALLPRODUCT: - if (wFlags & DISPATCH_METHOD) - { - hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); - if (FAILED(hr)) return hr; - hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr); - if (FAILED(hr)) - { - VariantClear(&varg0); - return hr; - } - if ((ret = MsiInstallProductW(V_BSTR(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS) - { - VariantClear(&varg1); - VariantClear(&varg0); - ERR("MsiInstallProduct returned %d\n", ret); - return DISP_E_EXCEPTION; - } - } - else return DISP_E_MEMBERNOTFOUND; - break; + return InstallerImpl_InstallProduct(wFlags, pDispParams, + pVarResult, pExcepInfo, + puArgErr); case DISPID_INSTALLER_VERSION: - if (wFlags & DISPATCH_PROPERTYGET) { - DLLVERSIONINFO verinfo; - WCHAR version[MAX_PATH]; + return InstallerImpl_Version(wFlags, pVarResult, + pExcepInfo, puArgErr); - static const WCHAR format[] = {'%','d','.','%','d','.','%','d','.','%','d',0}; - - verinfo.cbSize = sizeof(DLLVERSIONINFO); - hr = DllGetVersion(&verinfo); - if (FAILED(hr)) return hr; - - sprintfW(version, format, verinfo.dwMajorVersion, verinfo.dwMinorVersion, - verinfo.dwBuildNumber, verinfo.dwPlatformID); - - V_VT(pVarResult) = VT_BSTR; - V_BSTR(pVarResult) = SysAllocString(version); - } - else return DISP_E_MEMBERNOTFOUND; - break; + case DISPID_INSTALLER_LASTERRORRECORD: + return InstallerImpl_LastErrorRecord(wFlags, pDispParams, + pVarResult, pExcepInfo, + puArgErr); case DISPID_INSTALLER_REGISTRYVALUE: - if (wFlags & DISPATCH_METHOD) { - HKEY hkey; - DWORD dwType; - UINT posValue = 2; /* Save valuePos so we can save puArgErr if we are unable to do our type conversions */ - - hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); - if (FAILED(hr)) return hr; - hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr); - if (FAILED(hr)) return hr; - hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg2); - if (FAILED(hr)) - { - VariantClear(&varg1); - return hr; - } - - if (V_I4(&varg0) >= REG_INDEX_CLASSES_ROOT && - V_I4(&varg0) <= REG_INDEX_DYN_DATA) - V_I4(&varg0) |= (UINT_PTR)HKEY_CLASSES_ROOT; - - ret = RegOpenKeyW((HKEY)(UINT_PTR)V_I4(&varg0), V_BSTR(&varg1), &hkey); - - /* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */ - switch (V_VT(&varg2)) - { - case VT_EMPTY: /* Return VT_BOOL as to whether or not registry key exists */ - V_VT(pVarResult) = VT_BOOL; - V_BOOL(pVarResult) = (ret == ERROR_SUCCESS); - break; - - case VT_BSTR: /* Return value of specified key if it exists */ - if (ret == ERROR_SUCCESS && - (ret = RegQueryValueExW(hkey, V_BSTR(&varg2), NULL, NULL, NULL, &dwSize)) == ERROR_SUCCESS) - { - if (!(szString = msi_alloc(dwSize))) - ERR("Out of memory\n"); - else if ((ret = RegQueryValueExW(hkey, V_BSTR(&varg2), NULL, &dwType, (LPBYTE)szString, &dwSize)) == ERROR_SUCCESS) - variant_from_registry_value(pVarResult, dwType, (LPBYTE)szString, dwSize); - } - - if (ret != ERROR_SUCCESS) - { - msi_free(szString); - VariantClear(&varg2); - VariantClear(&varg1); - return DISP_E_BADINDEX; - } - break; + return InstallerImpl_RegistryValue(wFlags, pDispParams, + pVarResult, pExcepInfo, + puArgErr); - default: /* Try to make it into VT_I4, can use VariantChangeType for this */ - hr = VariantChangeType(&varg2, &varg2, 0, VT_I4); - if (SUCCEEDED(hr) && ret != ERROR_SUCCESS) hr = DISP_E_BADINDEX; /* Conversion fine, but couldn't find key */ - if (FAILED(hr)) - { - if (hr == DISP_E_TYPEMISMATCH) *puArgErr = posValue; - VariantClear(&varg2); /* Unknown type, so let's clear it */ - VariantClear(&varg1); - return hr; - } + case DISPID_INSTALLER_ENVIRONMENT: + return InstallerImpl_Environment(wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); - /* Retrieve class name or maximum value name or subkey name size */ - if (!V_I4(&varg2)) - ret = RegQueryInfoKeyW(hkey, NULL, &dwSize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - else if (V_I4(&varg2) > 0) - ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwSize, NULL, NULL, NULL); - else /* V_I4(&varg2) < 0 */ - ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, &dwSize, NULL, NULL, NULL, NULL, NULL, NULL); + case DISPID_INSTALLER_FILEATTRIBUTES: + return InstallerImpl_FileAttributes(wFlags, pDispParams, + pVarResult, pExcepInfo, + puArgErr); - if (ret == ERROR_SUCCESS) - { - if (!(szString = msi_alloc(++dwSize * sizeof(WCHAR)))) - ERR("Out of memory\n"); - else if (!V_I4(&varg2)) - ret = RegQueryInfoKeyW(hkey, szString, &dwSize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - else if (V_I4(&varg2) > 0) - ret = RegEnumValueW(hkey, V_I4(&varg2)-1, szString, &dwSize, 0, 0, NULL, NULL); - else /* V_I4(&varg2) < 0 */ - ret = RegEnumKeyW(hkey, -1 - V_I4(&varg2), szString, dwSize); - - if (szString && ret == ERROR_SUCCESS) - { - V_VT(pVarResult) = VT_BSTR; - V_BSTR(pVarResult) = SysAllocString(szString); - } - } - } + case DISPID_INSTALLER_FILESIZE: + return InstallerImpl_FileSize(wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); - msi_free(szString); - RegCloseKey(hkey); - } - else return DISP_E_MEMBERNOTFOUND; - break; + case DISPID_INSTALLER_FILEVERSION: + return InstallerImpl_FileVersion(wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); case DISPID_INSTALLER_PRODUCTSTATE: - if (wFlags & DISPATCH_PROPERTYGET) { - hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); - if (FAILED(hr)) return hr; - V_VT(pVarResult) = VT_I4; - V_I4(pVarResult) = MsiQueryProductStateW(V_BSTR(&varg0)); - } - else return DISP_E_MEMBERNOTFOUND; - break; + return InstallerImpl_ProductState(wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); case DISPID_INSTALLER_PRODUCTINFO: - if (wFlags & DISPATCH_PROPERTYGET) { - hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); - if (FAILED(hr)) return hr; - hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr); - if (FAILED(hr)) - { - VariantClear(&varg0); - return hr; - } - V_VT(pVarResult) = VT_BSTR; - V_BSTR(pVarResult) = NULL; - if ((ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), NULL, &dwSize)) == ERROR_SUCCESS) - { - if (!(szString = msi_alloc((++dwSize)*sizeof(WCHAR)))) - ERR("Out of memory\n"); - else if ((ret = MsiGetProductInfoW(V_BSTR(&varg0), V_BSTR(&varg1), szString, &dwSize)) == ERROR_SUCCESS) - V_BSTR(pVarResult) = SysAllocString(szString); - msi_free(szString); - } - if (ret != ERROR_SUCCESS) - { - ERR("MsiGetProductInfo returned %d\n", ret); - VariantClear(&varg1); - VariantClear(&varg0); - return DISP_E_EXCEPTION; - } - } - else return DISP_E_MEMBERNOTFOUND; - break; + return InstallerImpl_ProductInfo(wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); case DISPID_INSTALLER_PRODUCTS: - if (wFlags & DISPATCH_PROPERTYGET) - { - ListData *ldata = NULL; - ULONG idx = 0; - WCHAR szProductBuf[GUID_SIZE]; - - /* Find number of products */ - while ((ret = MsiEnumProductsW(idx, szProductBuf)) == ERROR_SUCCESS) idx++; - if (ret != ERROR_NO_MORE_ITEMS) - { - ERR("MsiEnumProducts returned %d\n", ret); - return DISP_E_EXCEPTION; - } - - V_VT(pVarResult) = VT_DISPATCH; - if (SUCCEEDED(hr = create_automation_object(0, NULL, (LPVOID*)&pDispatch, &DIID_StringList, ListImpl_Invoke, ListImpl_Free, sizeof(ListData)))) - { - V_DISPATCH(pVarResult) = pDispatch; - - /* Save product strings */ - ldata = private_data((AutomationObject *)pDispatch); - if (!(ldata->pVars = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VARIANT)*idx))) - ERR("Out of memory\n"); - else - { - ldata->ulCount = idx; - for (idx = 0; idx < ldata->ulCount; idx++) - { - ret = MsiEnumProductsW(idx, szProductBuf); - VariantInit(&ldata->pVars[idx]); - V_VT(&ldata->pVars[idx]) = VT_BSTR; - V_BSTR(&ldata->pVars[idx]) = SysAllocString(szProductBuf); - } - } - } - else - ERR("Failed to create StringList object, hresult 0x%08x\n", hr); - } - else return DISP_E_MEMBERNOTFOUND; - break; + return InstallerImpl_Products(wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); case DISPID_INSTALLER_RELATEDPRODUCTS: - if (wFlags & DISPATCH_PROPERTYGET) - { - ListData *ldata = NULL; - ULONG idx = 0; - WCHAR szProductBuf[GUID_SIZE]; - - hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); - if (FAILED(hr)) return hr; - - /* Find number of related products */ - while ((ret = MsiEnumRelatedProductsW(V_BSTR(&varg0), 0, idx, szProductBuf)) == ERROR_SUCCESS) idx++; - if (ret != ERROR_NO_MORE_ITEMS) - { - VariantClear(&varg0); - ERR("MsiEnumRelatedProducts returned %d\n", ret); - return DISP_E_EXCEPTION; - } - - V_VT(pVarResult) = VT_DISPATCH; - if (SUCCEEDED(hr = create_automation_object(0, NULL, (LPVOID*)&pDispatch, &DIID_StringList, ListImpl_Invoke, ListImpl_Free, sizeof(ListData)))) - { - V_DISPATCH(pVarResult) = pDispatch; - - /* Save product strings */ - ldata = private_data((AutomationObject *)pDispatch); - if (!(ldata->pVars = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VARIANT)*idx))) - ERR("Out of memory\n"); - else - { - ldata->ulCount = idx; - for (idx = 0; idx < ldata->ulCount; idx++) - { - ret = MsiEnumRelatedProductsW(V_BSTR(&varg0), 0, idx, szProductBuf); - VariantInit(&ldata->pVars[idx]); - V_VT(&ldata->pVars[idx]) = VT_BSTR; - V_BSTR(&ldata->pVars[idx]) = SysAllocString(szProductBuf); - } - } - } - else - ERR("Failed to create StringList object, hresult 0x%08x\n", hr); - } - else return DISP_E_MEMBERNOTFOUND; - break; + return InstallerImpl_RelatedProducts(wFlags, pDispParams, + pVarResult, pExcepInfo, + puArgErr); - default: + default: return DISP_E_MEMBERNOTFOUND; } - - VariantClear(&varg2); - VariantClear(&varg1); - VariantClear(&varg0); - - return S_OK; } /* Wrapper around create_automation_object to create an installer object. */ diff --git a/reactos/dll/win32/msi/database.c b/reactos/dll/win32/msi/database.c index adbdb9d46fc..b0966a25cf3 100644 --- a/reactos/dll/win32/msi/database.c +++ b/reactos/dll/win32/msi/database.c @@ -51,13 +51,220 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi); * Any binary data in a table is a reference to a stream. */ +typedef struct tagMSITRANSFORM { + struct list entry; + IStorage *stg; +} MSITRANSFORM; + +typedef struct tagMSISTREAM { + struct list entry; + IStream *stm; +} MSISTREAM; + +static UINT find_open_stream( MSIDATABASE *db, LPCWSTR name, IStream **stm ) +{ + MSISTREAM *stream; + + LIST_FOR_EACH_ENTRY( stream, &db->streams, MSISTREAM, entry ) + { + HRESULT r; + STATSTG stat; + + r = IStream_Stat( stream->stm, &stat, 0 ); + if( FAILED( r ) ) + { + WARN("failed to stat stream r = %08x!\n", r); + continue; + } + + if( !lstrcmpW( name, stat.pwcsName ) ) + { + TRACE("found %s\n", debugstr_w(name)); + *stm = stream->stm; + CoTaskMemFree( stat.pwcsName ); + return ERROR_SUCCESS; + } + + CoTaskMemFree( stat.pwcsName ); + } + + return ERROR_FUNCTION_FAILED; +} + +static UINT clone_open_stream( MSIDATABASE *db, LPCWSTR name, IStream **stm ) +{ + IStream *stream; + + if (find_open_stream( db, name, &stream ) == ERROR_SUCCESS) + { + HRESULT r; + LARGE_INTEGER pos; + + r = IStream_Clone( stream, stm ); + if( FAILED( r ) ) + { + WARN("failed to clone stream r = %08x!\n", r); + return ERROR_FUNCTION_FAILED; + } + + pos.QuadPart = 0; + r = IStream_Seek( *stm, pos, STREAM_SEEK_SET, NULL ); + if( FAILED( r ) ) + { + IStream_Release( *stm ); + return ERROR_FUNCTION_FAILED; + } + + return ERROR_SUCCESS; + } + + return ERROR_FUNCTION_FAILED; +} + +UINT db_get_raw_stream( MSIDATABASE *db, LPCWSTR stname, IStream **stm ) +{ + LPWSTR encname; + HRESULT r; + + encname = encode_streamname(FALSE, stname); + + TRACE("%s -> %s\n",debugstr_w(stname),debugstr_w(encname)); + + if (clone_open_stream( db, encname, stm ) == ERROR_SUCCESS) + { + msi_free( encname ); + return ERROR_SUCCESS; + } + + r = IStorage_OpenStream( db->storage, encname, NULL, + STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm ); + if( FAILED( r ) ) + { + MSITRANSFORM *transform; + + LIST_FOR_EACH_ENTRY( transform, &db->transforms, MSITRANSFORM, entry ) + { + TRACE("looking for %s in transform storage\n", debugstr_w(stname) ); + r = IStorage_OpenStream( transform->stg, encname, NULL, + STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm ); + if (SUCCEEDED(r)) + break; + } + } + + msi_free( encname ); + + if( SUCCEEDED(r) ) + { + MSISTREAM *stream; + + stream = msi_alloc( sizeof(MSISTREAM) ); + if( !stream ) + return ERROR_NOT_ENOUGH_MEMORY; + + stream->stm = *stm; + IStream_AddRef( *stm ); + list_add_tail( &db->streams, &stream->entry ); + } + + return SUCCEEDED(r) ? ERROR_SUCCESS : ERROR_FUNCTION_FAILED; +} + +UINT read_raw_stream_data( MSIDATABASE *db, LPCWSTR stname, + USHORT **pdata, UINT *psz ) +{ + HRESULT r; + UINT ret = ERROR_FUNCTION_FAILED; + VOID *data; + ULONG sz, count; + IStream *stm = NULL; + STATSTG stat; + + r = db_get_raw_stream( db, stname, &stm ); + if( r != ERROR_SUCCESS) + return ret; + r = IStream_Stat(stm, &stat, STATFLAG_NONAME ); + if( FAILED( r ) ) + { + WARN("open stream failed r = %08x!\n", r); + goto end; + } + + if( stat.cbSize.QuadPart >> 32 ) + { + WARN("Too big!\n"); + goto end; + } + + sz = stat.cbSize.QuadPart; + data = msi_alloc( sz ); + if( !data ) + { + WARN("couldn't allocate memory r=%08x!\n", r); + ret = ERROR_NOT_ENOUGH_MEMORY; + goto end; + } + + r = IStream_Read(stm, data, sz, &count ); + if( FAILED( r ) || ( count != sz ) ) + { + msi_free( data ); + WARN("read stream failed r = %08x!\n", r); + goto end; + } + + *pdata = data; + *psz = sz; + ret = ERROR_SUCCESS; + +end: + IStream_Release( stm ); + + return ret; +} + +void append_storage_to_db( MSIDATABASE *db, IStorage *stg ) +{ + MSITRANSFORM *t; + + t = msi_alloc( sizeof *t ); + t->stg = stg; + IStorage_AddRef( stg ); + list_add_tail( &db->transforms, &t->entry ); +} + +static void free_transforms( MSIDATABASE *db ) +{ + while( !list_empty( &db->transforms ) ) + { + MSITRANSFORM *t = LIST_ENTRY( list_head( &db->transforms ), + MSITRANSFORM, entry ); + list_remove( &t->entry ); + IStorage_Release( t->stg ); + msi_free( t ); + } +} + +static void free_streams( MSIDATABASE *db ) +{ + while( !list_empty( &db->streams ) ) + { + MSISTREAM *s = LIST_ENTRY( list_head( &db->streams ), + MSISTREAM, entry ); + list_remove( &s->entry ); + IStream_Release( s->stm ); + msi_free( s ); + } +} + static VOID MSI_CloseDatabase( MSIOBJECTHDR *arg ) { MSIDATABASE *db = (MSIDATABASE *) arg; msi_free(db->path); free_cached_tables( db ); - msi_free_transforms( db ); + free_streams( db ); + free_transforms( db ); msi_destroy_stringtable( db->strings ); IStorage_Release( db->storage ); if (db->deletefile) @@ -198,6 +405,7 @@ UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb) db->deletefile = strdupW( szDBPath ); list_init( &db->tables ); list_init( &db->transforms ); + list_init( &db->streams ); db->strings = msi_load_string_table( stg, &db->bytes_per_strref ); if( !db->strings ) @@ -493,10 +701,10 @@ done: static UINT msi_add_table_to_db(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types, LPWSTR *labels, DWORD num_labels, DWORD num_columns) { - UINT r; + UINT r = ERROR_OUTOFMEMORY; DWORD size; MSIQUERY *view; - LPWSTR create_sql; + LPWSTR create_sql = NULL; LPWSTR prelude, columns_sql, postlude; prelude = msi_build_createsql_prelude(labels[0]); @@ -504,31 +712,30 @@ static UINT msi_add_table_to_db(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types, postlude = msi_build_createsql_postlude(labels + 1, num_labels - 1); /* skip over table name */ if (!prelude || !columns_sql || !postlude) - return ERROR_OUTOFMEMORY; + goto done; size = lstrlenW(prelude) + lstrlenW(columns_sql) + lstrlenW(postlude) + 1; create_sql = msi_alloc(size * sizeof(WCHAR)); if (!create_sql) - return ERROR_OUTOFMEMORY; + goto done; lstrcpyW(create_sql, prelude); lstrcatW(create_sql, columns_sql); lstrcatW(create_sql, postlude); - msi_free(prelude); - msi_free(columns_sql); - msi_free(postlude); - r = MSI_DatabaseOpenViewW( db, create_sql, &view ); - msi_free(create_sql); - if (r != ERROR_SUCCESS) - return r; + goto done; r = MSI_ViewExecute(view, NULL); MSI_ViewClose(view); msiobj_release(&view->hdr); +done: + msi_free(prelude); + msi_free(columns_sql); + msi_free(postlude); + msi_free(create_sql); return r; } @@ -622,6 +829,7 @@ static UINT msi_add_records_to_table(MSIDATABASE *db, LPWSTR *columns, LPWSTR *t while (MSI_ViewFetch(view, &rec) != ERROR_NO_MORE_ITEMS) { r = MSI_ViewModify(view, MSIMODIFY_DELETE, rec); + msiobj_release(&rec->hdr); if (r != ERROR_SUCCESS) goto done; } @@ -1451,6 +1659,7 @@ static UINT msi_get_query_types(MSIQUERY *query, LPWSTR **types, DWORD *numtypes goto end; } + *numtypes = count; for (i=1; i<=count; i++ ) { (*types)[i-1] = strdupW(MSI_RecordGetString(prec, i)); @@ -1477,32 +1686,36 @@ static void merge_free_rows(MERGETABLE *table) static void free_merge_table(MERGETABLE *table) { - UINT i; + UINT i; - if (table->labels != NULL) - { - for (i = 0; i < table->numlabels; i++) - msi_free(table->labels[i]); - msi_free(table->labels); - } + if (table->labels != NULL) + { + for (i = 0; i < table->numlabels; i++) + msi_free(table->labels[i]); - if (table->columns != NULL) - { - for (i = 0; i < table->numcolumns; i++) - msi_free(table->columns[i]); - msi_free(table->columns); - } + msi_free(table->labels); + } - if (table->types != NULL) - { - for (i = 0; i < table->numtypes; i++) - msi_free(table->types[i]); - msi_free(table->types); - } - msi_free(table->name); - merge_free_rows(table); + if (table->columns != NULL) + { + for (i = 0; i < table->numcolumns; i++) + msi_free(table->columns[i]); - msi_free(table); + msi_free(table->columns); + } + + if (table->types != NULL) + { + for (i = 0; i < table->numtypes; i++) + msi_free(table->types[i]); + + msi_free(table->types); + } + + msi_free(table->name); + merge_free_rows(table); + + msi_free(table); } static UINT msi_get_merge_table (MSIDATABASE *db, LPCWSTR name, MERGETABLE **ptable) @@ -1753,7 +1966,6 @@ UINT WINAPI MsiDatabaseMergeW(MSIHANDLE hDatabase, MSIHANDLE hDatabaseMerge, LIST_FOR_EACH_SAFE(item, cursor, &tabledata) { MERGETABLE *table = LIST_ENTRY(item, MERGETABLE, entry); - list_remove(&table->entry); free_merge_table(table); } diff --git a/reactos/dll/win32/msi/drop.c b/reactos/dll/win32/msi/drop.c index a385633d442..f0b58039fd3 100644 --- a/reactos/dll/win32/msi/drop.c +++ b/reactos/dll/win32/msi/drop.c @@ -78,6 +78,20 @@ static UINT DROP_get_dimensions(struct tagMSIVIEW *view, UINT *rows, UINT *cols) return ERROR_FUNCTION_FAILED; } +static UINT DROP_delete( struct tagMSIVIEW *view ) +{ + MSIDROPVIEW *dv = (MSIDROPVIEW*)view; + + TRACE("%p\n", dv ); + + if( dv->table ) + dv->table->ops->delete( dv->table ); + + msi_free( dv ); + + return ERROR_SUCCESS; +} + static const MSIVIEWOPS drop_ops = { NULL, @@ -91,7 +105,7 @@ static const MSIVIEWOPS drop_ops = DROP_get_dimensions, NULL, NULL, - NULL, + DROP_delete, NULL, NULL, NULL, diff --git a/reactos/dll/win32/msi/files.c b/reactos/dll/win32/msi/files.c index 381ceca37b5..7e74dca9696 100644 --- a/reactos/dll/win32/msi/files.c +++ b/reactos/dll/win32/msi/files.c @@ -155,7 +155,7 @@ static UINT copy_install_file(MSIPACKAGE *package, MSIFILE *file, LPWSTR source) gle = copy_file(file, source); TRACE("Overwriting existing file: %d\n", gle); } - if ((gle == ERROR_SHARING_VIOLATION) || (gle == ERROR_USER_MAPPED_FILE)) + if (gle == ERROR_SHARING_VIOLATION || gle == ERROR_USER_MAPPED_FILE) { WCHAR tmpfileW[MAX_PATH], *pathW, *p; DWORD len; diff --git a/reactos/dll/win32/msi/join.c b/reactos/dll/win32/msi/join.c index 1aeb17cdc03..134c5698cd2 100644 --- a/reactos/dll/win32/msi/join.c +++ b/reactos/dll/win32/msi/join.c @@ -229,14 +229,18 @@ static UINT JOIN_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, static UINT JOIN_delete( struct tagMSIVIEW *view ) { MSIJOINVIEW *jv = (MSIJOINVIEW*)view; - JOINTABLE *table; + struct list *item, *cursor; TRACE("%p\n", jv ); - LIST_FOR_EACH_ENTRY(table, &jv->tables, JOINTABLE, entry) + LIST_FOR_EACH_SAFE(item, cursor, &jv->tables) { + JOINTABLE* table = LIST_ENTRY(item, JOINTABLE, entry); + + list_remove(&table->entry); table->view->ops->delete(table->view); table->view = NULL; + msi_free(table); } msi_free(jv); @@ -349,11 +353,13 @@ UINT JOIN_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR tables ) if( r != ERROR_SUCCESS ) { WARN("can't create table: %s\n", debugstr_w(tables)); + msi_free(table); r = ERROR_BAD_QUERY_SYNTAX; goto end; } - r = table->view->ops->get_dimensions( table->view, NULL, &table->columns ); + r = table->view->ops->get_dimensions( table->view, NULL, + &table->columns ); if( r != ERROR_SUCCESS ) { ERR("can't get table dimensions\n"); diff --git a/reactos/dll/win32/msi/media.c b/reactos/dll/win32/msi/media.c index 67cb7dc22eb..0a6c4314fbc 100644 --- a/reactos/dll/win32/msi/media.c +++ b/reactos/dll/win32/msi/media.c @@ -334,7 +334,12 @@ static INT_PTR cabinet_copy_file(FDINOTIFICATIONTYPE fdint, data->curfile = strdupAtoW(pfdin->psz1); if (!data->cb(data->package, data->curfile, MSICABEXTRACT_BEGINEXTRACT, &path, &attrs, data->user)) + { + /* We're not extracting this file, so free the filename. */ + msi_free(data->curfile); + data->curfile = NULL; goto done; + } TRACE("extracting %s\n", debugstr_w(path)); @@ -362,7 +367,7 @@ static INT_PTR cabinet_copy_file(FDINOTIFICATIONTYPE fdint, if (handle != INVALID_HANDLE_VALUE) goto done; err = GetLastError(); } - if ((err == ERROR_SHARING_VIOLATION) || (err == ERROR_USER_MAPPED_FILE)) + if (err == ERROR_SHARING_VIOLATION || err == ERROR_USER_MAPPED_FILE) { WCHAR tmpfileW[MAX_PATH], *tmppathW, *p; DWORD len; diff --git a/reactos/dll/win32/msi/msi.c b/reactos/dll/win32/msi/msi.c index 2515714ce73..4d9da4cd68f 100644 --- a/reactos/dll/win32/msi/msi.c +++ b/reactos/dll/win32/msi/msi.c @@ -901,7 +901,7 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, WCHAR packagecode[GUID_SIZE]; BOOL badconfig = FALSE; LONG res; - DWORD save, type = REG_NONE; + DWORD type = REG_NONE; static WCHAR empty[] = {0}; static const WCHAR sourcelist[] = { @@ -1036,22 +1036,26 @@ static UINT MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, if (pcchValueBuf) { - save = *pcchValueBuf; - - if (strlenW(val) < *pcchValueBuf) - r = msi_strcpy_to_awstring(val, szValue, pcchValueBuf); - else if (szValue->str.a || szValue->str.w) - r = ERROR_MORE_DATA; + /* If szBuffer (szValue->str) is NULL, there's no need to copy the value + * out. Also, *pcchValueBuf may be uninitialized in this case, so we + * can't rely on its value. + */ + if (szValue->str.a || szValue->str.w) + { + DWORD size = *pcchValueBuf; + if (strlenW(val) < size) + r = msi_strcpy_to_awstring(val, szValue, &size); + else + { + r = ERROR_MORE_DATA; + } + } if (!badconfig) *pcchValueBuf = lstrlenW(val); - else if (r == ERROR_SUCCESS) - { - *pcchValueBuf = save; - r = ERROR_BAD_CONFIGURATION; - } } - else if (badconfig) + + if (badconfig) r = ERROR_BAD_CONFIGURATION; if (val != empty) diff --git a/reactos/dll/win32/msi/msipriv.h b/reactos/dll/win32/msi/msipriv.h index 5b23f55b189..ac247ac4548 100644 --- a/reactos/dll/win32/msi/msipriv.h +++ b/reactos/dll/win32/msi/msipriv.h @@ -80,6 +80,7 @@ typedef struct tagMSIDATABASE LPCWSTR mode; struct list tables; struct list transforms; + struct list streams; } MSIDATABASE; typedef struct tagMSIVIEW MSIVIEW; @@ -649,7 +650,6 @@ extern void msiobj_unlock(MSIOBJECTHDR *); extern void msi_free_handle_table(void); extern void free_cached_tables( MSIDATABASE *db ); -extern void msi_free_transforms( MSIDATABASE *db ); extern UINT MSI_CommitTables( MSIDATABASE *db ); @@ -698,6 +698,7 @@ extern UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine, BOOL preserve_case ); /* record internals */ +extern void MSI_CloseRecord( MSIOBJECTHDR * ); extern UINT MSI_RecordSetIStream( MSIRECORD *, UINT, IStream *); extern UINT MSI_RecordGetIStream( MSIRECORD *, UINT, IStream **); extern const WCHAR *MSI_RecordGetString( const MSIRECORD *, UINT ); @@ -718,11 +719,12 @@ extern MSIRECORD *MSI_CloneRecord( MSIRECORD * ); extern BOOL MSI_RecordsAreEqual( MSIRECORD *, MSIRECORD * ); /* stream internals */ -extern UINT get_raw_stream( MSIHANDLE hdb, LPCWSTR stname, IStream **stm ); extern void enum_stream_names( IStorage *stg ); +extern LPWSTR encode_streamname(BOOL bTable, LPCWSTR in); extern BOOL decode_streamname(LPCWSTR in, LPWSTR out); /* database internals */ +extern UINT db_get_raw_stream( MSIDATABASE *, LPCWSTR, IStream ** ); extern UINT MSI_OpenDatabaseW( LPCWSTR, LPCWSTR, MSIDATABASE ** ); extern UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY ** ); extern UINT MSI_OpenQuery( MSIDATABASE *, MSIQUERY **, LPCWSTR, ... ); @@ -755,7 +757,7 @@ extern MSICONDITION MSI_EvaluateConditionW( MSIPACKAGE *, LPCWSTR ); extern UINT MSI_GetComponentStateW( MSIPACKAGE *, LPCWSTR, INSTALLSTATE *, INSTALLSTATE * ); extern UINT MSI_GetFeatureStateW( MSIPACKAGE *, LPCWSTR, INSTALLSTATE *, INSTALLSTATE * ); extern UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE*, LPCWSTR, INSTALLSTATE ); -extern LPCWSTR msi_download_file( LPCWSTR szUrl, LPWSTR filename ); +extern UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename ); extern UINT msi_package_add_info(MSIPACKAGE *, DWORD, DWORD, LPCWSTR, LPWSTR); extern UINT msi_package_add_media_disk(MSIPACKAGE *, DWORD, DWORD, DWORD, LPWSTR, LPWSTR); extern UINT msi_clone_properties(MSIPACKAGE *); diff --git a/reactos/dll/win32/msi/msiserver.idl b/reactos/dll/win32/msi/msiserver.idl index 9972a023652..a8146957b06 100644 --- a/reactos/dll/win32/msi/msiserver.idl +++ b/reactos/dll/win32/msi/msiserver.idl @@ -153,21 +153,48 @@ library WindowsInstaller Session* OpenPackage( [in] VARIANT PackagePath, [in, optional, defaultvalue(0)] long Options); + [id(DISPID_INSTALLER_OPENPRODUCT)] + Session* OpenProduct( + [in] BSTR ProductCode); + [id(DISPID_INSTALLER_SUMMARYINFORMATION)] + SummaryInfo* SummaryInformation( + [in] BSTR PackagePath, + [in, optional, defaultvalue(0)] long UpdateCount); [id(DISPID_INSTALLER_OPENDATABASE)] Database *OpenDatabase( [in] BSTR DatabasePath, [in] VARIANT OpenMode); + [id(DISPID_INSTALLER_ENABLELOG)] + void EnableLog( + [in] BSTR LogMode, + [in] BSTR LogFile); [id(DISPID_INSTALLER_INSTALLPRODUCT)] void InstallProduct( [in] BSTR PackagePath, [in, optional, defaultvalue("0")] BSTR PropertyValues); [id(DISPID_INSTALLER_VERSION)] BSTR Version(); + [id(DISPID_INSTALLER_LASTERRORRECORD)] + Record* LastErrorRecord(); [id(DISPID_INSTALLER_REGISTRYVALUE), propget] BSTR RegistryValue( [in] VARIANT Root, [in] BSTR Key, [in, optional] VARIANT Value); + [id(DISPID_INSTALLER_ENVIRONMENT), propget] + BSTR Environment([in] BSTR Variable); + [id(DISPID_INSTALLER_ENVIRONMENT), propput] + void Environment( + [in] BSTR Variable, + [in] BSTR rhs); + [id(DISPID_INSTALLER_FILEATTRIBUTES)] + long FileAttributes([in] BSTR FilePath); + [id(DISPID_INSTALLER_FILESIZE)] + long FileSize([in] BSTR FilePath); + [id(DISPID_INSTALLER_FILEVERSION)] + BSTR FileVersion( + [in] BSTR FilePath, + [in, optional] VARIANT Language); [id(DISPID_INSTALLER_PRODUCTSTATE), propget] MsiInstallState ProductState( [in] BSTR Product); diff --git a/reactos/dll/win32/msi/msiserver_dispids.h b/reactos/dll/win32/msi/msiserver_dispids.h index e6078fd6d67..d98d784940a 100644 --- a/reactos/dll/win32/msi/msiserver_dispids.h +++ b/reactos/dll/win32/msi/msiserver_dispids.h @@ -18,11 +18,19 @@ #define DISPID_INSTALLER_CREATERECORD 1 #define DISPID_INSTALLER_OPENPACKAGE 2 +#define DISPID_INSTALLER_OPENPRODUCT 3 #define DISPID_INSTALLER_OPENDATABASE 4 +#define DISPID_INSTALLER_SUMMARYINFORMATION 5 #define DISPID_INSTALLER_UILEVEL 6 +#define DISPID_INSTALLER_ENABLELOG 7 #define DISPID_INSTALLER_INSTALLPRODUCT 8 #define DISPID_INSTALLER_VERSION 9 +#define DISPID_INSTALLER_LASTERRORRECORD 10 #define DISPID_INSTALLER_REGISTRYVALUE 11 +#define DISPID_INSTALLER_ENVIRONMENT 12 +#define DISPID_INSTALLER_FILEATTRIBUTES 13 +#define DISPID_INSTALLER_FILESIZE 15 +#define DISPID_INSTALLER_FILEVERSION 16 #define DISPID_INSTALLER_PRODUCTSTATE 17 #define DISPID_INSTALLER_PRODUCTINFO 18 #define DISPID_INSTALLER_PRODUCTS 35 diff --git a/reactos/dll/win32/msi/package.c b/reactos/dll/win32/msi/package.c index 574289fb3f1..120972fdd07 100644 --- a/reactos/dll/win32/msi/package.c +++ b/reactos/dll/win32/msi/package.c @@ -779,6 +779,16 @@ static UINT msi_load_admin_properties(MSIPACKAGE *package) return r; } +static void adjust_allusers_property( MSIPACKAGE *package ) +{ + /* FIXME: this should depend on the user's privileges */ + if (msi_get_property_int( package, szAllUsers, 0 ) == 2) + { + TRACE("resetting ALLUSERS property from 2 to 1\n"); + MSI_SetPropertyW( package, szAllUsers, szOne ); + } +} + MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url ) { static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 }; @@ -818,6 +828,8 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url ) if (package->WordCount & msidbSumInfoSourceTypeAdminImage) msi_load_admin_properties( package ); + + adjust_allusers_property( package ); } return package; @@ -833,7 +845,7 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url ) * we should read all the tables to memory, then open the * database to read binary streams on demand. */ -static LPCWSTR copy_package_to_temp( LPCWSTR szPackage, LPWSTR filename ) +static UINT copy_package_to_temp( LPCWSTR szPackage, LPWSTR filename ) { WCHAR path[MAX_PATH]; @@ -842,16 +854,16 @@ static LPCWSTR copy_package_to_temp( LPCWSTR szPackage, LPWSTR filename ) if( !CopyFileW( szPackage, filename, FALSE ) ) { + UINT error = GetLastError(); + ERR("failed to copy package %s to %s (%u)\n", debugstr_w(szPackage), debugstr_w(filename), error); DeleteFileW( filename ); - ERR("failed to copy package %s\n", debugstr_w(szPackage) ); - return szPackage; + return error; } - TRACE("Opening relocated package %s\n", debugstr_w( filename )); - return filename; + return ERROR_SUCCESS; } -LPCWSTR msi_download_file( LPCWSTR szUrl, LPWSTR filename ) +UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename ) { LPINTERNET_CACHE_ENTRY_INFOW cache_entry; DWORD size = 0; @@ -867,20 +879,24 @@ LPCWSTR msi_download_file( LPCWSTR szUrl, LPWSTR filename ) cache_entry = HeapAlloc( GetProcessHeap(), 0, size ); if ( !GetUrlCacheEntryInfoW( szUrl, cache_entry, &size ) ) { + UINT error = GetLastError(); HeapFree( GetProcessHeap(), 0, cache_entry ); - return szUrl; + return error; } lstrcpyW( filename, cache_entry->lpszLocalFileName ); HeapFree( GetProcessHeap(), 0, cache_entry ); - return filename; + return ERROR_SUCCESS; } hr = URLDownloadToCacheFileW( NULL, szUrl, filename, MAX_PATH, 0, NULL ); if ( FAILED(hr) ) - return szUrl; + { + WARN("failed to download %s to cache file\n", debugstr_w(szUrl)); + return ERROR_FUNCTION_FAILED; + } - return filename; + return ERROR_SUCCESS; } static UINT msi_get_local_package_name( LPWSTR path ) @@ -925,7 +941,7 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) MSIHANDLE handle; LPWSTR ptr, base_url = NULL; UINT r; - WCHAR temppath[MAX_PATH], localfile[MAX_PATH]; + WCHAR temppath[MAX_PATH], localfile[MAX_PATH], cachefile[MAX_PATH]; LPCWSTR file = szPackage; TRACE("%s %p\n", debugstr_w(szPackage), pPackage); @@ -952,9 +968,15 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) { if ( UrlIsW( szPackage, URLIS_URL ) ) { - file = msi_download_file( szPackage, temppath ); - if ( file != szPackage ) - file = copy_package_to_temp( file, temppath ); + r = msi_download_file( szPackage, cachefile ); + if ( r != ERROR_SUCCESS ) + return r; + + r = copy_package_to_temp( cachefile, temppath ); + if ( r != ERROR_SUCCESS ) + return r; + + file = temppath; base_url = strdupW( szPackage ); if ( !base_url ) @@ -964,7 +986,13 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) if (ptr) *(ptr + 1) = '\0'; } else - file = copy_package_to_temp( szPackage, temppath ); + { + r = copy_package_to_temp( szPackage, temppath ); + if ( r != ERROR_SUCCESS ) + return r; + + file = temppath; + } r = msi_get_local_package_name( localfile ); if (r != ERROR_SUCCESS) @@ -979,6 +1007,8 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) return GetLastError(); } + TRACE("Opening relocated package %s\n", debugstr_w( file )); + /* transforms that add binary streams require that we open the database * read/write, which is safe because we always create a copy that is thrown * away when we're done. diff --git a/reactos/dll/win32/msi/record.c b/reactos/dll/win32/msi/record.c index 68eab694370..45adbac8471 100644 --- a/reactos/dll/win32/msi/record.c +++ b/reactos/dll/win32/msi/record.c @@ -64,7 +64,7 @@ static void MSI_FreeField( MSIFIELD *field ) } } -static void MSI_CloseRecord( MSIOBJECTHDR *arg ) +void MSI_CloseRecord( MSIOBJECTHDR *arg ) { MSIRECORD *rec = (MSIRECORD *) arg; UINT i; diff --git a/reactos/dll/win32/msi/sql.tab.c b/reactos/dll/win32/msi/sql.tab.c index 84597a4f6b7..72e230ca837 100644 --- a/reactos/dll/win32/msi/sql.tab.c +++ b/reactos/dll/win32/msi/sql.tab.c @@ -126,7 +126,10 @@ typedef struct tag_SQL_input LPCWSTR command; DWORD n, len; UINT r; - MSIVIEW **view; /* view structure for the resulting query */ + MSIVIEW **view; /* View structure for the resulting query. This value + * tracks the view currently being created so we can free + * this view on syntax error. + */ struct list *mem; } SQL_input; @@ -147,10 +150,14 @@ static struct expr * EXPR_ival( void *info, int val ); static struct expr * EXPR_sval( void *info, const struct sql_str *str ); static struct expr * EXPR_wildcard( void *info ); +#define PARSER_BUBBLE_UP_VIEW( sql, result, current_view ) \ + *sql->view = current_view; \ + result = current_view + /* Line 189 of yacc.c */ -#line 154 "sql.tab.c" +#line 161 "sql.tab.c" /* Enabling traces. */ #ifndef YYDEBUG @@ -248,7 +255,7 @@ typedef union YYSTYPE { /* Line 214 of yacc.c */ -#line 76 "sql.y" +#line 83 "sql.y" struct sql_str str; LPWSTR string; @@ -261,7 +268,7 @@ typedef union YYSTYPE /* Line 214 of yacc.c */ -#line 265 "sql.tab.c" +#line 272 "sql.tab.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -273,7 +280,7 @@ typedef union YYSTYPE /* Line 264 of yacc.c */ -#line 277 "sql.tab.c" +#line 284 "sql.tab.c" #ifdef short # undef short @@ -595,15 +602,15 @@ static const yytype_int8 yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 126, 126, 134, 135, 136, 137, 138, 139, 140, - 144, 154, 167, 183, 198, 208, 221, 234, 244, 254, - 267, 271, 278, 291, 301, 311, 318, 327, 331, 335, - 342, 346, 353, 357, 361, 365, 369, 373, 377, 384, - 393, 406, 410, 414, 430, 451, 452, 456, 463, 464, - 480, 490, 502, 507, 516, 522, 528, 534, 540, 546, - 552, 558, 564, 570, 576, 585, 586, 590, 597, 608, - 609, 617, 625, 631, 637, 643, 652, 661, 667, 676, - 683, 691 + 0, 133, 133, 141, 142, 143, 144, 145, 146, 147, + 151, 162, 176, 193, 209, 220, 234, 248, 259, 270, + 284, 288, 295, 310, 320, 330, 337, 346, 350, 354, + 361, 365, 372, 376, 380, 384, 388, 392, 396, 403, + 412, 425, 429, 433, 448, 468, 469, 473, 480, 481, + 496, 508, 523, 528, 537, 543, 549, 555, 561, 567, + 573, 579, 585, 591, 597, 606, 607, 611, 618, 629, + 630, 638, 646, 652, 658, 664, 673, 682, 688, 697, + 704, 712 }; #endif @@ -1612,7 +1619,7 @@ yyreduce: case 2: /* Line 1455 of yacc.c */ -#line 127 "sql.y" +#line 134 "sql.y" { SQL_input* sql = (SQL_input*) info; *sql->view = (yyvsp[(1) - (1)].query); @@ -1622,7 +1629,7 @@ yyreduce: case 10: /* Line 1455 of yacc.c */ -#line 145 "sql.y" +#line 152 "sql.y" { SQL_input *sql = (SQL_input*) info; MSIVIEW *insert = NULL; @@ -1630,14 +1637,15 @@ yyreduce: INSERT_CreateView( sql->db, &insert, (yyvsp[(3) - (10)].string), (yyvsp[(5) - (10)].column_list), (yyvsp[(9) - (10)].column_list), FALSE ); if( !insert ) YYABORT; - (yyval.query) = insert; + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), insert ); ;} break; case 11: /* Line 1455 of yacc.c */ -#line 155 "sql.y" +#line 163 "sql.y" { SQL_input *sql = (SQL_input*) info; MSIVIEW *insert = NULL; @@ -1645,14 +1653,15 @@ yyreduce: INSERT_CreateView( sql->db, &insert, (yyvsp[(3) - (11)].string), (yyvsp[(5) - (11)].column_list), (yyvsp[(9) - (11)].column_list), TRUE ); if( !insert ) YYABORT; - (yyval.query) = insert; + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), insert ); ;} break; case 12: /* Line 1455 of yacc.c */ -#line 168 "sql.y" +#line 177 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW *create = NULL; @@ -1666,14 +1675,15 @@ yyreduce: sql->r = r; YYABORT; } - (yyval.query) = create; + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), create ); ;} break; case 13: /* Line 1455 of yacc.c */ -#line 184 "sql.y" +#line 194 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW *create = NULL; @@ -1683,14 +1693,15 @@ yyreduce: CREATE_CreateView( sql->db, &create, (yyvsp[(3) - (7)].string), (yyvsp[(5) - (7)].column_list), TRUE ); if( !create ) YYABORT; - (yyval.query) = create; + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), create ); ;} break; case 14: /* Line 1455 of yacc.c */ -#line 199 "sql.y" +#line 210 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW *update = NULL; @@ -1698,14 +1709,15 @@ yyreduce: UPDATE_CreateView( sql->db, &update, (yyvsp[(2) - (6)].string), (yyvsp[(4) - (6)].column_list), (yyvsp[(6) - (6)].expr) ); if( !update ) YYABORT; - (yyval.query) = update; + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), update ); ;} break; case 15: /* Line 1455 of yacc.c */ -#line 209 "sql.y" +#line 221 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW *update = NULL; @@ -1713,14 +1725,15 @@ yyreduce: UPDATE_CreateView( sql->db, &update, (yyvsp[(2) - (4)].string), (yyvsp[(4) - (4)].column_list), NULL ); if( !update ) YYABORT; - (yyval.query) = update; + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), update ); ;} break; case 16: /* Line 1455 of yacc.c */ -#line 222 "sql.y" +#line 235 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW *delete = NULL; @@ -1728,14 +1741,15 @@ yyreduce: DELETE_CreateView( sql->db, &delete, (yyvsp[(2) - (2)].query) ); if( !delete ) YYABORT; - (yyval.query) = delete; + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), delete ); ;} break; case 17: /* Line 1455 of yacc.c */ -#line 235 "sql.y" +#line 249 "sql.y" { SQL_input* sql = (SQL_input*) info; MSIVIEW *alter = NULL; @@ -1743,14 +1757,15 @@ yyreduce: ALTER_CreateView( sql->db, &alter, (yyvsp[(3) - (4)].string), NULL, (yyvsp[(4) - (4)].integer) ); if( !alter ) YYABORT; - (yyval.query) = alter; + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), alter ); ;} break; case 18: /* Line 1455 of yacc.c */ -#line 245 "sql.y" +#line 260 "sql.y" { SQL_input *sql = (SQL_input *)info; MSIVIEW *alter = NULL; @@ -1758,14 +1773,15 @@ yyreduce: ALTER_CreateView( sql->db, &alter, (yyvsp[(3) - (5)].string), (yyvsp[(5) - (5)].column_list), 0 ); if (!alter) YYABORT; - (yyval.query) = alter; + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), alter ); ;} break; case 19: /* Line 1455 of yacc.c */ -#line 255 "sql.y" +#line 271 "sql.y" { SQL_input *sql = (SQL_input *)info; MSIVIEW *alter = NULL; @@ -1773,14 +1789,15 @@ yyreduce: ALTER_CreateView( sql->db, &alter, (yyvsp[(3) - (6)].string), (yyvsp[(5) - (6)].column_list), 1 ); if (!alter) YYABORT; - (yyval.query) = alter; + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), alter ); ;} break; case 20: /* Line 1455 of yacc.c */ -#line 268 "sql.y" +#line 285 "sql.y" { (yyval.integer) = 1; ;} @@ -1789,7 +1806,7 @@ yyreduce: case 21: /* Line 1455 of yacc.c */ -#line 272 "sql.y" +#line 289 "sql.y" { (yyval.integer) = -1; ;} @@ -1798,22 +1815,24 @@ yyreduce: case 22: /* Line 1455 of yacc.c */ -#line 279 "sql.y" +#line 296 "sql.y" { SQL_input* sql = (SQL_input*) info; + MSIVIEW* drop = NULL; UINT r; - (yyval.query) = NULL; - r = DROP_CreateView( sql->db, &(yyval.query), (yyvsp[(3) - (3)].string) ); + r = DROP_CreateView( sql->db, &drop, (yyvsp[(3) - (3)].string) ); if( r != ERROR_SUCCESS || !(yyval.query) ) YYABORT; + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), drop ); ;} break; case 23: /* Line 1455 of yacc.c */ -#line 292 "sql.y" +#line 311 "sql.y" { if( SQL_MarkPrimaryKeys( &(yyvsp[(1) - (4)].column_list), (yyvsp[(4) - (4)].column_list) ) ) (yyval.column_list) = (yyvsp[(1) - (4)].column_list); @@ -1825,7 +1844,7 @@ yyreduce: case 24: /* Line 1455 of yacc.c */ -#line 302 "sql.y" +#line 321 "sql.y" { column_info *ci; @@ -1840,7 +1859,7 @@ yyreduce: case 25: /* Line 1455 of yacc.c */ -#line 312 "sql.y" +#line 331 "sql.y" { (yyval.column_list) = (yyvsp[(1) - (1)].column_list); ;} @@ -1849,7 +1868,7 @@ yyreduce: case 26: /* Line 1455 of yacc.c */ -#line 319 "sql.y" +#line 338 "sql.y" { (yyval.column_list) = (yyvsp[(1) - (2)].column_list); (yyval.column_list)->type = ((yyvsp[(2) - (2)].column_type) | MSITYPE_VALID); @@ -1860,7 +1879,7 @@ yyreduce: case 27: /* Line 1455 of yacc.c */ -#line 328 "sql.y" +#line 347 "sql.y" { (yyval.column_type) = (yyvsp[(1) - (1)].column_type); ;} @@ -1869,7 +1888,7 @@ yyreduce: case 28: /* Line 1455 of yacc.c */ -#line 332 "sql.y" +#line 351 "sql.y" { (yyval.column_type) = (yyvsp[(1) - (2)].column_type) | MSITYPE_LOCALIZABLE; ;} @@ -1878,7 +1897,7 @@ yyreduce: case 29: /* Line 1455 of yacc.c */ -#line 336 "sql.y" +#line 355 "sql.y" { (yyval.column_type) = (yyvsp[(1) - (2)].column_type) | MSITYPE_TEMPORARY; ;} @@ -1887,7 +1906,7 @@ yyreduce: case 30: /* Line 1455 of yacc.c */ -#line 343 "sql.y" +#line 362 "sql.y" { (yyval.column_type) |= MSITYPE_NULLABLE; ;} @@ -1896,7 +1915,7 @@ yyreduce: case 31: /* Line 1455 of yacc.c */ -#line 347 "sql.y" +#line 366 "sql.y" { (yyval.column_type) = (yyvsp[(1) - (3)].column_type); ;} @@ -1905,7 +1924,7 @@ yyreduce: case 32: /* Line 1455 of yacc.c */ -#line 354 "sql.y" +#line 373 "sql.y" { (yyval.column_type) = MSITYPE_STRING | 1; ;} @@ -1914,7 +1933,7 @@ yyreduce: case 33: /* Line 1455 of yacc.c */ -#line 358 "sql.y" +#line 377 "sql.y" { (yyval.column_type) = MSITYPE_STRING | 0x400 | (yyvsp[(3) - (4)].column_type); ;} @@ -1923,7 +1942,7 @@ yyreduce: case 34: /* Line 1455 of yacc.c */ -#line 362 "sql.y" +#line 381 "sql.y" { (yyval.column_type) = MSITYPE_STRING | 0x400; ;} @@ -1932,7 +1951,7 @@ yyreduce: case 35: /* Line 1455 of yacc.c */ -#line 366 "sql.y" +#line 385 "sql.y" { (yyval.column_type) = 2 | 0x400; ;} @@ -1941,7 +1960,7 @@ yyreduce: case 36: /* Line 1455 of yacc.c */ -#line 370 "sql.y" +#line 389 "sql.y" { (yyval.column_type) = 2 | 0x400; ;} @@ -1950,7 +1969,7 @@ yyreduce: case 37: /* Line 1455 of yacc.c */ -#line 374 "sql.y" +#line 393 "sql.y" { (yyval.column_type) = 4; ;} @@ -1959,7 +1978,7 @@ yyreduce: case 38: /* Line 1455 of yacc.c */ -#line 378 "sql.y" +#line 397 "sql.y" { (yyval.column_type) = MSITYPE_STRING | MSITYPE_VALID; ;} @@ -1968,7 +1987,7 @@ yyreduce: case 39: /* Line 1455 of yacc.c */ -#line 385 "sql.y" +#line 404 "sql.y" { if( ( (yyvsp[(1) - (1)].integer) > 255 ) || ( (yyvsp[(1) - (1)].integer) < 0 ) ) YYABORT; @@ -1979,7 +1998,7 @@ yyreduce: case 40: /* Line 1455 of yacc.c */ -#line 394 "sql.y" +#line 413 "sql.y" { UINT r; @@ -1997,7 +2016,7 @@ yyreduce: case 42: /* Line 1455 of yacc.c */ -#line 411 "sql.y" +#line 430 "sql.y" { (yyval.query) = (yyvsp[(2) - (2)].query); ;} @@ -2006,38 +2025,36 @@ yyreduce: case 43: /* Line 1455 of yacc.c */ -#line 415 "sql.y" +#line 434 "sql.y" { SQL_input* sql = (SQL_input*) info; + MSIVIEW* distinct = NULL; UINT r; - (yyval.query) = NULL; - r = DISTINCT_CreateView( sql->db, &(yyval.query), (yyvsp[(3) - (3)].query) ); + r = DISTINCT_CreateView( sql->db, &distinct, (yyvsp[(3) - (3)].query) ); if (r != ERROR_SUCCESS) - { - (yyvsp[(3) - (3)].query)->ops->delete((yyvsp[(3) - (3)].query)); YYABORT; - } + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), distinct ); ;} break; case 44: /* Line 1455 of yacc.c */ -#line 431 "sql.y" +#line 449 "sql.y" { SQL_input* sql = (SQL_input*) info; + MSIVIEW* select = NULL; UINT r; - (yyval.query) = NULL; if( (yyvsp[(1) - (2)].column_list) ) { - r = SELECT_CreateView( sql->db, &(yyval.query), (yyvsp[(2) - (2)].query), (yyvsp[(1) - (2)].column_list) ); + r = SELECT_CreateView( sql->db, &select, (yyvsp[(2) - (2)].query), (yyvsp[(1) - (2)].column_list) ); if (r != ERROR_SUCCESS) - { - (yyvsp[(2) - (2)].query)->ops->delete((yyvsp[(2) - (2)].query)); YYABORT; - } + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), select ); } else (yyval.query) = (yyvsp[(2) - (2)].query); @@ -2047,7 +2064,7 @@ yyreduce: case 46: /* Line 1455 of yacc.c */ -#line 453 "sql.y" +#line 470 "sql.y" { (yyvsp[(1) - (3)].column_list)->next = (yyvsp[(3) - (3)].column_list); ;} @@ -2056,7 +2073,7 @@ yyreduce: case 47: /* Line 1455 of yacc.c */ -#line 457 "sql.y" +#line 474 "sql.y" { (yyval.column_list) = NULL; ;} @@ -2065,54 +2082,58 @@ yyreduce: case 49: /* Line 1455 of yacc.c */ -#line 465 "sql.y" +#line 482 "sql.y" { SQL_input* sql = (SQL_input*) info; + MSIVIEW* where = NULL; UINT r; - (yyval.query) = NULL; - r = WHERE_CreateView( sql->db, &(yyval.query), (yyvsp[(1) - (3)].query), (yyvsp[(3) - (3)].expr) ); + r = WHERE_CreateView( sql->db, &where, (yyvsp[(1) - (3)].query), (yyvsp[(3) - (3)].expr) ); if( r != ERROR_SUCCESS ) - { - (yyvsp[(1) - (3)].query)->ops->delete( (yyvsp[(1) - (3)].query) ); YYABORT; - } + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), where ); ;} break; case 50: /* Line 1455 of yacc.c */ -#line 481 "sql.y" +#line 497 "sql.y" { SQL_input* sql = (SQL_input*) info; + MSIVIEW* table = NULL; UINT r; - (yyval.query) = NULL; - r = TABLE_CreateView( sql->db, (yyvsp[(2) - (2)].string), &(yyval.query) ); + r = TABLE_CreateView( sql->db, (yyvsp[(2) - (2)].string), &table ); if( r != ERROR_SUCCESS || !(yyval.query) ) YYABORT; + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), table ); ;} break; case 51: /* Line 1455 of yacc.c */ -#line 491 "sql.y" +#line 509 "sql.y" { SQL_input* sql = (SQL_input*) info; + MSIVIEW* join = NULL; UINT r; - r = JOIN_CreateView( sql->db, &(yyval.query), (yyvsp[(2) - (2)].string) ); + r = JOIN_CreateView( sql->db, &join, (yyvsp[(2) - (2)].string) ); if( r != ERROR_SUCCESS ) YYABORT; + + PARSER_BUBBLE_UP_VIEW( sql, (yyval.query), join ); ;} break; case 52: /* Line 1455 of yacc.c */ -#line 503 "sql.y" +#line 524 "sql.y" { (yyval.string) = (yyvsp[(1) - (1)].string); ;} @@ -2121,7 +2142,7 @@ yyreduce: case 53: /* Line 1455 of yacc.c */ -#line 508 "sql.y" +#line 529 "sql.y" { (yyval.string) = parser_add_table( info, (yyvsp[(3) - (3)].string), (yyvsp[(1) - (3)].string) ); if (!(yyval.string)) @@ -2132,7 +2153,7 @@ yyreduce: case 54: /* Line 1455 of yacc.c */ -#line 517 "sql.y" +#line 538 "sql.y" { (yyval.expr) = (yyvsp[(2) - (3)].expr); if( !(yyval.expr) ) @@ -2143,7 +2164,7 @@ yyreduce: case 55: /* Line 1455 of yacc.c */ -#line 523 "sql.y" +#line 544 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_AND, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) @@ -2154,7 +2175,7 @@ yyreduce: case 56: /* Line 1455 of yacc.c */ -#line 529 "sql.y" +#line 550 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_OR, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) @@ -2165,7 +2186,7 @@ yyreduce: case 57: /* Line 1455 of yacc.c */ -#line 535 "sql.y" +#line 556 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_EQ, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) @@ -2176,7 +2197,7 @@ yyreduce: case 58: /* Line 1455 of yacc.c */ -#line 541 "sql.y" +#line 562 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_GT, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) @@ -2187,7 +2208,7 @@ yyreduce: case 59: /* Line 1455 of yacc.c */ -#line 547 "sql.y" +#line 568 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_LT, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) @@ -2198,7 +2219,7 @@ yyreduce: case 60: /* Line 1455 of yacc.c */ -#line 553 "sql.y" +#line 574 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_LE, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) @@ -2209,7 +2230,7 @@ yyreduce: case 61: /* Line 1455 of yacc.c */ -#line 559 "sql.y" +#line 580 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_GE, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) @@ -2220,7 +2241,7 @@ yyreduce: case 62: /* Line 1455 of yacc.c */ -#line 565 "sql.y" +#line 586 "sql.y" { (yyval.expr) = EXPR_complex( info, (yyvsp[(1) - (3)].expr), OP_NE, (yyvsp[(3) - (3)].expr) ); if( !(yyval.expr) ) @@ -2231,7 +2252,7 @@ yyreduce: case 63: /* Line 1455 of yacc.c */ -#line 571 "sql.y" +#line 592 "sql.y" { (yyval.expr) = EXPR_unary( info, (yyvsp[(1) - (3)].expr), OP_ISNULL ); if( !(yyval.expr) ) @@ -2242,7 +2263,7 @@ yyreduce: case 64: /* Line 1455 of yacc.c */ -#line 577 "sql.y" +#line 598 "sql.y" { (yyval.expr) = EXPR_unary( info, (yyvsp[(1) - (4)].expr), OP_NOTNULL ); if( !(yyval.expr) ) @@ -2253,7 +2274,7 @@ yyreduce: case 67: /* Line 1455 of yacc.c */ -#line 591 "sql.y" +#line 612 "sql.y" { (yyval.column_list) = parser_alloc_column( info, NULL, NULL ); if( !(yyval.column_list) ) @@ -2265,7 +2286,7 @@ yyreduce: case 68: /* Line 1455 of yacc.c */ -#line 598 "sql.y" +#line 619 "sql.y" { (yyval.column_list) = parser_alloc_column( info, NULL, NULL ); if( !(yyval.column_list) ) @@ -2278,7 +2299,7 @@ yyreduce: case 70: /* Line 1455 of yacc.c */ -#line 610 "sql.y" +#line 631 "sql.y" { (yyval.column_list) = (yyvsp[(1) - (3)].column_list); (yyval.column_list)->next = (yyvsp[(3) - (3)].column_list); @@ -2288,7 +2309,7 @@ yyreduce: case 71: /* Line 1455 of yacc.c */ -#line 618 "sql.y" +#line 639 "sql.y" { (yyval.column_list) = (yyvsp[(1) - (3)].column_list); (yyval.column_list)->val = (yyvsp[(3) - (3)].expr); @@ -2298,7 +2319,7 @@ yyreduce: case 72: /* Line 1455 of yacc.c */ -#line 626 "sql.y" +#line 647 "sql.y" { (yyval.expr) = EXPR_ival( info, (yyvsp[(1) - (1)].integer) ); if( !(yyval.expr) ) @@ -2309,7 +2330,7 @@ yyreduce: case 73: /* Line 1455 of yacc.c */ -#line 632 "sql.y" +#line 653 "sql.y" { (yyval.expr) = EXPR_ival( info, -(yyvsp[(2) - (2)].integer) ); if( !(yyval.expr) ) @@ -2320,7 +2341,7 @@ yyreduce: case 74: /* Line 1455 of yacc.c */ -#line 638 "sql.y" +#line 659 "sql.y" { (yyval.expr) = EXPR_sval( info, &(yyvsp[(1) - (1)].str) ); if( !(yyval.expr) ) @@ -2331,7 +2352,7 @@ yyreduce: case 75: /* Line 1455 of yacc.c */ -#line 644 "sql.y" +#line 665 "sql.y" { (yyval.expr) = EXPR_wildcard( info ); if( !(yyval.expr) ) @@ -2342,7 +2363,7 @@ yyreduce: case 76: /* Line 1455 of yacc.c */ -#line 653 "sql.y" +#line 674 "sql.y" { (yyval.expr) = EXPR_column( info, (yyvsp[(1) - (1)].column_list) ); if( !(yyval.expr) ) @@ -2353,7 +2374,7 @@ yyreduce: case 77: /* Line 1455 of yacc.c */ -#line 662 "sql.y" +#line 683 "sql.y" { (yyval.column_list) = parser_alloc_column( info, (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].string) ); if( !(yyval.column_list) ) @@ -2364,7 +2385,7 @@ yyreduce: case 78: /* Line 1455 of yacc.c */ -#line 668 "sql.y" +#line 689 "sql.y" { (yyval.column_list) = parser_alloc_column( info, NULL, (yyvsp[(1) - (1)].string) ); if( !(yyval.column_list) ) @@ -2375,7 +2396,7 @@ yyreduce: case 79: /* Line 1455 of yacc.c */ -#line 677 "sql.y" +#line 698 "sql.y" { (yyval.string) = (yyvsp[(1) - (1)].string); ;} @@ -2384,7 +2405,7 @@ yyreduce: case 80: /* Line 1455 of yacc.c */ -#line 684 "sql.y" +#line 705 "sql.y" { if ( SQL_getstring( info, &(yyvsp[(1) - (1)].str), &(yyval.string) ) != ERROR_SUCCESS || !(yyval.string) ) YYABORT; @@ -2394,7 +2415,7 @@ yyreduce: case 81: /* Line 1455 of yacc.c */ -#line 692 "sql.y" +#line 713 "sql.y" { (yyval.integer) = SQL_getint( info ); ;} @@ -2403,7 +2424,7 @@ yyreduce: /* Line 1455 of yacc.c */ -#line 2407 "sql.tab.c" +#line 2428 "sql.tab.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -2615,7 +2636,7 @@ yyreturn: /* Line 1675 of yacc.c */ -#line 697 "sql.y" +#line 718 "sql.y" static LPWSTR parser_add_table( void *info, LPCWSTR list, LPCWSTR table ) diff --git a/reactos/dll/win32/msi/sql.tab.h b/reactos/dll/win32/msi/sql.tab.h index d19f0fd7a26..35f67fbf6ae 100644 --- a/reactos/dll/win32/msi/sql.tab.h +++ b/reactos/dll/win32/msi/sql.tab.h @@ -110,7 +110,7 @@ typedef union YYSTYPE { /* Line 1676 of yacc.c */ -#line 76 "sql.y" +#line 83 "sql.y" struct sql_str str; LPWSTR string; diff --git a/reactos/dll/win32/msi/sql.y b/reactos/dll/win32/msi/sql.y index e2484df9e98..548a8782444 100644 --- a/reactos/dll/win32/msi/sql.y +++ b/reactos/dll/win32/msi/sql.y @@ -47,7 +47,10 @@ typedef struct tag_SQL_input LPCWSTR command; DWORD n, len; UINT r; - MSIVIEW **view; /* view structure for the resulting query */ + MSIVIEW **view; /* View structure for the resulting query. This value + * tracks the view currently being created so we can free + * this view on syntax error. + */ struct list *mem; } SQL_input; @@ -68,6 +71,10 @@ static struct expr * EXPR_ival( void *info, int val ); static struct expr * EXPR_sval( void *info, const struct sql_str *str ); static struct expr * EXPR_wildcard( void *info ); +#define PARSER_BUBBLE_UP_VIEW( sql, result, current_view ) \ + *sql->view = current_view; \ + result = current_view + %} %pure-parser @@ -149,7 +156,8 @@ oneinsert: INSERT_CreateView( sql->db, &insert, $3, $5, $9, FALSE ); if( !insert ) YYABORT; - $$ = insert; + + PARSER_BUBBLE_UP_VIEW( sql, $$, insert ); } | TK_INSERT TK_INTO table TK_LP selcollist TK_RP TK_VALUES TK_LP constlist TK_RP TK_TEMPORARY { @@ -159,7 +167,8 @@ oneinsert: INSERT_CreateView( sql->db, &insert, $3, $5, $9, TRUE ); if( !insert ) YYABORT; - $$ = insert; + + PARSER_BUBBLE_UP_VIEW( sql, $$, insert ); } ; @@ -178,7 +187,8 @@ onecreate: sql->r = r; YYABORT; } - $$ = create; + + PARSER_BUBBLE_UP_VIEW( sql, $$, create ); } | TK_CREATE TK_TABLE table TK_LP table_def TK_RP TK_HOLD { @@ -190,7 +200,8 @@ onecreate: CREATE_CreateView( sql->db, &create, $3, $5, TRUE ); if( !create ) YYABORT; - $$ = create; + + PARSER_BUBBLE_UP_VIEW( sql, $$, create ); } ; @@ -203,7 +214,8 @@ oneupdate: UPDATE_CreateView( sql->db, &update, $2, $4, $6 ); if( !update ) YYABORT; - $$ = update; + + PARSER_BUBBLE_UP_VIEW( sql, $$, update ); } | TK_UPDATE table TK_SET update_assign_list { @@ -213,7 +225,8 @@ oneupdate: UPDATE_CreateView( sql->db, &update, $2, $4, NULL ); if( !update ) YYABORT; - $$ = update; + + PARSER_BUBBLE_UP_VIEW( sql, $$, update ); } ; @@ -226,7 +239,8 @@ onedelete: DELETE_CreateView( sql->db, &delete, $2 ); if( !delete ) YYABORT; - $$ = delete; + + PARSER_BUBBLE_UP_VIEW( sql, $$, delete ); } ; @@ -239,7 +253,8 @@ onealter: ALTER_CreateView( sql->db, &alter, $3, NULL, $4 ); if( !alter ) YYABORT; - $$ = alter; + + PARSER_BUBBLE_UP_VIEW( sql, $$, alter ); } | TK_ALTER TK_TABLE table TK_ADD column_and_type { @@ -249,7 +264,8 @@ onealter: ALTER_CreateView( sql->db, &alter, $3, $5, 0 ); if (!alter) YYABORT; - $$ = alter; + + PARSER_BUBBLE_UP_VIEW( sql, $$, alter ); } | TK_ALTER TK_TABLE table TK_ADD column_and_type TK_HOLD { @@ -259,7 +275,8 @@ onealter: ALTER_CreateView( sql->db, &alter, $3, $5, 1 ); if (!alter) YYABORT; - $$ = alter; + + PARSER_BUBBLE_UP_VIEW( sql, $$, alter ); } ; @@ -278,12 +295,14 @@ onedrop: TK_DROP TK_TABLE table { SQL_input* sql = (SQL_input*) info; + MSIVIEW* drop = NULL; UINT r; - $$ = NULL; - r = DROP_CreateView( sql->db, &$$, $3 ); + r = DROP_CreateView( sql->db, &drop, $3 ); if( r != ERROR_SUCCESS || !$$ ) YYABORT; + + PARSER_BUBBLE_UP_VIEW( sql, $$, drop ); } ; @@ -414,15 +433,14 @@ unorderedsel: | TK_SELECT TK_DISTINCT selectfrom { SQL_input* sql = (SQL_input*) info; + MSIVIEW* distinct = NULL; UINT r; - $$ = NULL; - r = DISTINCT_CreateView( sql->db, &$$, $3 ); + r = DISTINCT_CreateView( sql->db, &distinct, $3 ); if (r != ERROR_SUCCESS) - { - $3->ops->delete($3); YYABORT; - } + + PARSER_BUBBLE_UP_VIEW( sql, $$, distinct ); } ; @@ -430,17 +448,16 @@ selectfrom: selcollist from { SQL_input* sql = (SQL_input*) info; + MSIVIEW* select = NULL; UINT r; - $$ = NULL; if( $1 ) { - r = SELECT_CreateView( sql->db, &$$, $2, $1 ); + r = SELECT_CreateView( sql->db, &select, $2, $1 ); if (r != ERROR_SUCCESS) - { - $2->ops->delete($2); YYABORT; - } + + PARSER_BUBBLE_UP_VIEW( sql, $$, select ); } else $$ = $2; @@ -464,15 +481,14 @@ from: | fromtable TK_WHERE expr { SQL_input* sql = (SQL_input*) info; + MSIVIEW* where = NULL; UINT r; - $$ = NULL; - r = WHERE_CreateView( sql->db, &$$, $1, $3 ); + r = WHERE_CreateView( sql->db, &where, $1, $3 ); if( r != ERROR_SUCCESS ) - { - $1->ops->delete( $1 ); YYABORT; - } + + PARSER_BUBBLE_UP_VIEW( sql, $$, where ); } ; @@ -480,21 +496,26 @@ fromtable: TK_FROM table { SQL_input* sql = (SQL_input*) info; + MSIVIEW* table = NULL; UINT r; - $$ = NULL; - r = TABLE_CreateView( sql->db, $2, &$$ ); + r = TABLE_CreateView( sql->db, $2, &table ); if( r != ERROR_SUCCESS || !$$ ) YYABORT; + + PARSER_BUBBLE_UP_VIEW( sql, $$, table ); } | TK_FROM tablelist { SQL_input* sql = (SQL_input*) info; + MSIVIEW* join = NULL; UINT r; - r = JOIN_CreateView( sql->db, &$$, $2 ); + r = JOIN_CreateView( sql->db, &join, $2 ); if( r != ERROR_SUCCESS ) YYABORT; + + PARSER_BUBBLE_UP_VIEW( sql, $$, join ); } ; diff --git a/reactos/dll/win32/msi/storages.c b/reactos/dll/win32/msi/storages.c index 844db8d0a82..a54d46fc76e 100644 --- a/reactos/dll/win32/msi/storages.c +++ b/reactos/dll/win32/msi/storages.c @@ -437,11 +437,13 @@ static UINT STORAGES_delete(struct tagMSIVIEW *view) if (sv->storages[i]->storage) IStorage_Release(sv->storages[i]->storage); + msi_free(sv->storages[i]->name); msi_free(sv->storages[i]); } msi_free(sv->storages); sv->storages = NULL; + msi_free(sv); return ERROR_SUCCESS; } diff --git a/reactos/dll/win32/msi/streams.c b/reactos/dll/win32/msi/streams.c index faa27c8cb8f..4825ae67b18 100644 --- a/reactos/dll/win32/msi/streams.c +++ b/reactos/dll/win32/msi/streams.c @@ -400,12 +400,18 @@ static UINT STREAMS_delete(struct tagMSIVIEW *view) for (i = 0; i < sv->num_rows; i++) { - if (sv->streams[i] && sv->streams[i]->stream) - IStream_Release(sv->streams[i]->stream); - msi_free(sv->streams[i]); + if (sv->streams[i]) + { + if (sv->streams[i]->stream) + IStream_Release(sv->streams[i]->stream); + + msi_free(sv->streams[i]->name); + msi_free(sv->streams[i]); + } } msi_free(sv->streams); + msi_free(sv); return ERROR_SUCCESS; } diff --git a/reactos/dll/win32/msi/string.c b/reactos/dll/win32/msi/string.c index e5b5cc2d465..3bdc4360bd0 100644 --- a/reactos/dll/win32/msi/string.c +++ b/reactos/dll/win32/msi/string.c @@ -40,12 +40,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(msidb); -#define HASH_SIZE 0x101 #define LONG_STR_BYTES 3 typedef struct _msistring { - int hash_next; UINT persistent_refcount; UINT nonpersistent_refcount; LPWSTR str; @@ -56,30 +54,14 @@ struct string_table UINT maxcount; /* the number of strings */ UINT freeslot; UINT codepage; - int hash[HASH_SIZE]; - msistring *strings; /* an array of strings (in the tree) */ + UINT sortcount; + msistring *strings; /* an array of strings */ + UINT *sorted; /* index */ }; -static UINT msistring_makehash( const WCHAR *str ) -{ - UINT hash = 0; - - if (str==NULL) - return hash; - - while( *str ) - { - hash ^= *str++; - hash *= 53; - hash = (hash<<5) | (hash>>27); - } - return hash % HASH_SIZE; -} - static string_table *init_stringtable( int entries, UINT codepage ) { string_table *st; - int i; if (codepage != CP_ACP && !IsValidCodePage(codepage)) { @@ -92,18 +74,26 @@ static string_table *init_stringtable( int entries, UINT codepage ) return NULL; if( entries < 1 ) entries = 1; + st->strings = msi_alloc_zero( sizeof (msistring) * entries ); if( !st->strings ) { msi_free( st ); return NULL; } + + st->sorted = msi_alloc( sizeof (UINT) * entries ); + if( !st->sorted ) + { + msi_free( st->strings ); + msi_free( st ); + return NULL; + } + st->maxcount = entries; st->freeslot = 1; st->codepage = codepage; - - for( i=0; ihash[i] = -1; + st->sortcount = 0; return st; } @@ -119,12 +109,13 @@ VOID msi_destroy_stringtable( string_table *st ) msi_free( st->strings[i].str ); } msi_free( st->strings ); + msi_free( st->sorted ); msi_free( st ); } static int st_find_free_entry( string_table *st ) { - UINT i, sz; + UINT i, sz, *s; msistring *p; TRACE("%p\n", st); @@ -146,7 +137,17 @@ static int st_find_free_entry( string_table *st ) p = msi_realloc_zero( st->strings, sz*sizeof(msistring) ); if( !p ) return -1; + + s = msi_realloc( st->sorted, sz*sizeof(UINT) ); + if( !s ) + { + msi_free( p ); + return -1; + } + st->strings = p; + st->sorted = s; + st->freeslot = st->maxcount; st->maxcount = sz; if( st->strings[st->freeslot].persistent_refcount || @@ -155,10 +156,40 @@ static int st_find_free_entry( string_table *st ) return st->freeslot; } -static void set_st_entry( string_table *st, UINT n, LPWSTR str, UINT refcount, enum StringPersistence persistence ) +static int find_insert_index( const string_table *st, UINT string_id ) { - UINT hash = msistring_makehash( str ); + int i, c, low = 0, high = st->sortcount - 1; + + while (low <= high) + { + i = (low + high) / 2; + c = lstrcmpW( st->strings[string_id].str, st->strings[st->sorted[i]].str ); + if (c < 0) + high = i - 1; + else if (c > 0) + low = i + 1; + else + return -1; /* already exists */ + } + return high + 1; +} + +static void insert_string_sorted( string_table *st, UINT string_id ) +{ + int i; + + i = find_insert_index( st, string_id ); + if (i == -1) + return; + + memmove( &st->sorted[i] + 1, &st->sorted[i], (st->sortcount - i) * sizeof(UINT) ); + st->sorted[i] = string_id; + st->sortcount++; +} + +static void set_st_entry( string_table *st, UINT n, LPWSTR str, UINT refcount, enum StringPersistence persistence ) +{ if (persistence == StringPersistent) { st->strings[n].persistent_refcount = refcount; @@ -172,8 +203,7 @@ static void set_st_entry( string_table *st, UINT n, LPWSTR str, UINT refcount, e st->strings[n].str = str; - st->strings[n].hash_next = st->hash[hash]; - st->hash[hash] = n; + insert_string_sorted( st, n ); if( n < st->maxcount ) st->freeslot = n + 1; @@ -382,14 +412,20 @@ static UINT msi_id2stringA( const string_table *st, UINT id, LPSTR buffer, UINT */ UINT msi_string2idW( const string_table *st, LPCWSTR str, UINT *id ) { - UINT n, hash = msistring_makehash( str ); - msistring *se = st->strings; + int i, c, low = 0, high = st->sortcount - 1; - for (n = st->hash[hash]; n != -1; n = st->strings[n].hash_next ) + while (low <= high) { - if ((str == se[n].str) || !lstrcmpW(str, se[n].str)) + i = (low + high) / 2; + c = lstrcmpW( str, st->strings[st->sorted[i]].str ); + + if (c < 0) + high = i - 1; + else if (c > 0) + low = i + 1; + else { - *id = n; + *id = st->sorted[i]; return ERROR_SUCCESS; } } diff --git a/reactos/dll/win32/msi/table.c b/reactos/dll/win32/msi/table.c index fa32a04a21e..cc40515e664 100644 --- a/reactos/dll/win32/msi/table.c +++ b/reactos/dll/win32/msi/table.c @@ -83,11 +83,6 @@ struct tagMSITABLE WCHAR name[1]; }; -typedef struct tagMSITRANSFORM { - struct list entry; - IStorage *stg; -} MSITRANSFORM; - static const WCHAR szStringData[] = { '_','S','t','r','i','n','g','D','a','t','a',0 }; static const WCHAR szStringPool[] = { @@ -154,7 +149,7 @@ static int utf2mime(int x) return -1; } -static LPWSTR encode_streamname(BOOL bTable, LPCWSTR in) +LPWSTR encode_streamname(BOOL bTable, LPCWSTR in) { DWORD count = MAX_STREAM_NAME; DWORD ch, next; @@ -332,89 +327,6 @@ end: return ret; } -static UINT db_get_raw_stream( MSIDATABASE *db, LPCWSTR stname, IStream **stm ) -{ - LPWSTR encname; - HRESULT r; - - encname = encode_streamname(FALSE, stname); - - TRACE("%s -> %s\n",debugstr_w(stname),debugstr_w(encname)); - - r = IStorage_OpenStream(db->storage, encname, NULL, - STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm); - if( FAILED( r ) ) - { - MSITRANSFORM *transform; - - LIST_FOR_EACH_ENTRY( transform, &db->transforms, MSITRANSFORM, entry ) - { - TRACE("looking for %s in transform storage\n", debugstr_w(stname) ); - r = IStorage_OpenStream( transform->stg, encname, NULL, - STGM_READ | STGM_SHARE_EXCLUSIVE, 0, stm ); - if (SUCCEEDED(r)) - break; - } - } - - msi_free( encname ); - - return SUCCEEDED(r) ? ERROR_SUCCESS : ERROR_FUNCTION_FAILED; -} - -UINT read_raw_stream_data( MSIDATABASE *db, LPCWSTR stname, - USHORT **pdata, UINT *psz ) -{ - HRESULT r; - UINT ret = ERROR_FUNCTION_FAILED; - VOID *data; - ULONG sz, count; - IStream *stm = NULL; - STATSTG stat; - - r = db_get_raw_stream( db, stname, &stm ); - if( r != ERROR_SUCCESS) - return ret; - r = IStream_Stat(stm, &stat, STATFLAG_NONAME ); - if( FAILED( r ) ) - { - WARN("open stream failed r = %08x!\n", r); - goto end; - } - - if( stat.cbSize.QuadPart >> 32 ) - { - WARN("Too big!\n"); - goto end; - } - - sz = stat.cbSize.QuadPart; - data = msi_alloc( sz ); - if( !data ) - { - WARN("couldn't allocate memory r=%08x!\n", r); - ret = ERROR_NOT_ENOUGH_MEMORY; - goto end; - } - - r = IStream_Read(stm, data, sz, &count ); - if( FAILED( r ) || ( count != sz ) ) - { - msi_free( data ); - WARN("read stream failed r = %08x!\n", r); - goto end; - } - - *pdata = data; - *psz = sz; - ret = ERROR_SUCCESS; - -end: - IStream_Release( stm ); - - return ret; -} - UINT write_stream_data( IStorage *stg, LPCWSTR stname, LPCVOID data, UINT sz, BOOL bTable ) { @@ -1042,17 +954,22 @@ static UINT get_tablecolumns( MSIDATABASE *db, static void msi_update_table_columns( MSIDATABASE *db, LPCWSTR name ) { MSITABLE *table; + LPWSTR tablename; UINT size, offset, old_count; UINT n; - table = find_cached_table( db, name ); + /* We may free name in msi_free_colinfo. */ + tablename = strdupW( name ); + + table = find_cached_table( db, tablename ); old_count = table->col_count; + msi_free_colinfo( table->colinfo, table->col_count ); msi_free( table->colinfo ); table->colinfo = NULL; - table_get_column_info( db, name, &table->colinfo, &table->col_count ); + table_get_column_info( db, tablename, &table->colinfo, &table->col_count ); if (!table->col_count) - return; + goto done; size = msi_table_get_row_size( db, table->colinfo, table->col_count ); offset = table->colinfo[table->col_count - 1].offset; @@ -1063,6 +980,9 @@ static void msi_update_table_columns( MSIDATABASE *db, LPCWSTR name ) if (old_count < table->col_count) memset( &table->data[n][offset], 0, size - offset ); } + +done: + msi_free(tablename); } /* try to find the table name in the _Tables table */ @@ -1754,15 +1674,14 @@ static UINT TABLE_delete_row( struct tagMSIVIEW *view, UINT row ) tv->columns[i].hash_table = NULL; } - if ( row == num_rows - 1 ) - return ERROR_SUCCESS; - for (i = row + 1; i < num_rows; i++) { memcpy(tv->table->data[i - 1], tv->table->data[i], tv->row_size); tv->table->data_persistent[i - 1] = tv->table->data_persistent[i]; } + msi_free(tv->table->data[num_rows - 1]); + return ERROR_SUCCESS; } @@ -1828,6 +1747,9 @@ static UINT msi_refresh_record( struct tagMSIVIEW *view, MSIRECORD *rec, UINT ro if (r != ERROR_SUCCESS) return r; + /* Close the original record */ + MSI_CloseRecord(&rec->hdr); + count = MSI_RecordGetFieldCount(rec); for (i = 0; i < count; i++) MSI_RecordCopyField(curr, i + 1, rec, i + 1); @@ -2316,7 +2238,6 @@ static UINT TABLE_drop(struct tagMSIVIEW *view) list_remove(&tv->table->entry); free_table(tv->table); - TABLE_delete(view); done: msiobj_release(&rec->hdr); @@ -3010,25 +2931,3 @@ end: return ret; } - -void append_storage_to_db( MSIDATABASE *db, IStorage *stg ) -{ - MSITRANSFORM *t; - - t = msi_alloc( sizeof *t ); - t->stg = stg; - IStorage_AddRef( stg ); - list_add_tail( &db->transforms, &t->entry ); -} - -void msi_free_transforms( MSIDATABASE *db ) -{ - while( !list_empty( &db->transforms ) ) - { - MSITRANSFORM *t = LIST_ENTRY( list_head( &db->transforms ), - MSITRANSFORM, entry ); - list_remove( &t->entry ); - IStorage_Release( t->stg ); - msi_free( t ); - } -} diff --git a/reactos/dll/win32/msi/where.c b/reactos/dll/win32/msi/where.c index 32f71b9d1e0..545d6a84dc6 100644 --- a/reactos/dll/win32/msi/where.c +++ b/reactos/dll/win32/msi/where.c @@ -309,9 +309,7 @@ static UINT STRCMP_Evaluate( MSIWHEREVIEW *wv, UINT row, const struct expr *cond sr = lstrcmpW( l_str, r_str ); *val = ( cond->u.expr.op == OP_EQ && ( sr == 0 ) ) || - ( cond->u.expr.op == OP_NE && ( sr != 0 ) ) || - ( cond->u.expr.op == OP_LT && ( sr < 0 ) ) || - ( cond->u.expr.op == OP_GT && ( sr > 0 ) ); + ( cond->u.expr.op == OP_NE && ( sr != 0 ) ); return ERROR_SUCCESS; } @@ -644,8 +642,6 @@ static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr switch( cond->u.expr.op ) { case OP_EQ: - case OP_GT: - case OP_LT: case OP_NE: break; default: