diff --git a/dlls/msi/streams.c b/dlls/msi/streams.c index 9828b7f355c..995027057a6 100644 --- a/dlls/msi/streams.c +++ b/dlls/msi/streams.c @@ -54,9 +54,9 @@ typedef struct tagMSISTREAMSVIEW UINT row_size; } MSISTREAMSVIEW; -static BOOL add_stream_to_table(MSISTREAMSVIEW *sv, STREAM *stream, int index) +static BOOL streams_set_table_size(MSISTREAMSVIEW *sv, int size) { - if (index >= sv->max_streams) + if (size >= sv->max_streams) { sv->max_streams *= 2; sv->streams = msi_realloc(sv->streams, sv->max_streams * sizeof(STREAM *)); @@ -64,7 +64,6 @@ static BOOL add_stream_to_table(MSISTREAMSVIEW *sv, STREAM *stream, int index) return FALSE; } - sv->streams[index] = stream; return TRUE; } @@ -139,12 +138,6 @@ static UINT STREAMS_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec } static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask) -{ - FIXME("(%p, %d, %p, %d): stub!\n", view, row, rec, mask); - return ERROR_SUCCESS; -} - -static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temporary) { MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; STREAM *stream; @@ -156,7 +149,10 @@ static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, BOOL tem ULONG count; UINT r = ERROR_FUNCTION_FAILED; - TRACE("(%p, %p, %d)\n", view, rec, temporary); + TRACE("(%p, %p)\n", view, rec); + + if (row > sv->num_rows) + return ERROR_FUNCTION_FAILED; r = MSI_RecordGetIStream(rec, 2, &stm); if (r != ERROR_SUCCESS) @@ -201,8 +197,7 @@ static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, BOOL tem IStorage_OpenStream(sv->db->storage, name, 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream->stream); - if (!add_stream_to_table(sv, stream, sv->num_rows++)) - goto done; + sv->streams[row] = stream; done: msi_free(name); @@ -213,6 +208,16 @@ done: return r; } +static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temporary) +{ + MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; + + if (!streams_set_table_size(sv, ++sv->num_rows)) + return ERROR_FUNCTION_FAILED; + + return STREAMS_set_row(view, sv->num_rows - 1, rec, 0); +} + static UINT STREAMS_delete_row(struct tagMSIVIEW *view, UINT row) { FIXME("(%p %d): stub!\n", view, row); @@ -278,6 +283,52 @@ static UINT STREAMS_get_column_info(struct tagMSIVIEW *view, return ERROR_SUCCESS; } +static UINT streams_find_row(MSISTREAMSVIEW *sv, MSIRECORD *rec, UINT *row) +{ + LPCWSTR str; + UINT i, id, data; + + str = MSI_RecordGetString(rec, 1); + msi_string2idW(sv->db->strings, str, &id); + + for (i = 0; i < sv->num_rows; i++) + { + STREAMS_fetch_int(&sv->view, i, 1, &data); + + if (data == id) + { + *row = i; + return ERROR_SUCCESS; + } + } + + return ERROR_FUNCTION_FAILED; +} + +static UINT streams_modify_update(struct tagMSIVIEW *view, MSIRECORD *rec) +{ + MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; + UINT r, row; + + r = streams_find_row(sv, rec, &row); + if (r != ERROR_SUCCESS) + return ERROR_FUNCTION_FAILED; + + return STREAMS_set_row(view, row, rec, 0); +} + +static UINT streams_modify_assign(struct tagMSIVIEW *view, MSIRECORD *rec) +{ + MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; + UINT r, row; + + r = streams_find_row(sv, rec, &row); + if (r == ERROR_SUCCESS) + return streams_modify_update(view, rec); + + return STREAMS_insert_row(view, rec, FALSE); +} + static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row) { UINT r; @@ -286,15 +337,21 @@ static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRE switch (eModifyMode) { + case MSIMODIFY_ASSIGN: + r = streams_modify_assign(view, rec); + break; + case MSIMODIFY_INSERT: r = STREAMS_insert_row(view, rec, FALSE); break; + case MSIMODIFY_UPDATE: + r = streams_modify_update(view, rec); + break; + case MSIMODIFY_VALIDATE_NEW: case MSIMODIFY_INSERT_TEMPORARY: - case MSIMODIFY_UPDATE: case MSIMODIFY_REFRESH: - case MSIMODIFY_ASSIGN: case MSIMODIFY_REPLACE: case MSIMODIFY_MERGE: case MSIMODIFY_DELETE: @@ -425,11 +482,13 @@ static UINT add_streams_to_table(MSISTREAMSVIEW *sv) STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream->stream); CoTaskMemFree(stat.pwcsName); - if (!add_stream_to_table(sv, stream, count++)) + if (!streams_set_table_size(sv, ++count)) { count = -1; break; } + + sv->streams[count - 1] = stream; } IEnumSTATSTG_Release(stgenum);