Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
17ba7419
Commit
17ba7419
authored
Jul 09, 2007
by
James Hawkins
Committed by
Alexandre Julliard
Jul 10, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
msi: Handle adding columns in transforms.
parent
9285351a
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
131 additions
and
91 deletions
+131
-91
table.c
dlls/msi/table.c
+116
-37
db.c
dlls/msi/tests/db.c
+15
-54
No files found.
dlls/msi/table.c
View file @
17ba7419
...
@@ -1944,8 +1944,34 @@ static UINT msi_table_find_row( MSITABLEVIEW *tv, MSIRECORD *rec, UINT *row )
...
@@ -1944,8 +1944,34 @@ static UINT msi_table_find_row( MSITABLEVIEW *tv, MSIRECORD *rec, UINT *row )
return
r
;
return
r
;
}
}
static
void
msi_update_table_columns
(
MSIDATABASE
*
db
,
LPWSTR
name
)
{
MSITABLE
*
table
;
UINT
size
,
offset
;
int
n
;
table
=
find_cached_table
(
db
,
name
);
msi_free
(
table
->
colinfo
);
table_get_column_info
(
db
,
name
,
&
table
->
colinfo
,
&
table
->
col_count
);
size
=
msi_table_get_row_size
(
table
->
colinfo
,
table
->
col_count
);
offset
=
table
->
colinfo
[
table
->
col_count
-
1
].
offset
;
for
(
n
=
0
;
n
<
table
->
row_count
;
n
++
)
{
table
->
data
[
n
]
=
msi_realloc
(
table
->
data
[
n
],
size
);
table
->
data
[
n
][
offset
]
=
(
BYTE
)
MSI_NULL_INTEGER
;
}
}
typedef
struct
{
struct
list
entry
;
LPWSTR
name
;
}
TRANSFORMDATA
;
static
UINT
msi_table_load_transform
(
MSIDATABASE
*
db
,
IStorage
*
stg
,
static
UINT
msi_table_load_transform
(
MSIDATABASE
*
db
,
IStorage
*
stg
,
string_table
*
st
,
LPCWSTR
name
,
string_table
*
st
,
TRANSFORMDATA
*
transform
,
UINT
bytes_per_strref
)
UINT
bytes_per_strref
)
{
{
UINT
rawsize
=
0
;
UINT
rawsize
=
0
;
...
@@ -1955,6 +1981,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
...
@@ -1955,6 +1981,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
MSIRECORD
*
rec
=
NULL
;
MSIRECORD
*
rec
=
NULL
;
UINT
colcol
=
0
;
UINT
colcol
=
0
;
WCHAR
coltable
[
32
];
WCHAR
coltable
[
32
];
LPWSTR
name
=
transform
->
name
;
coltable
[
0
]
=
0
;
coltable
[
0
]
=
0
;
TRACE
(
"%p %p %p %s
\n
"
,
db
,
stg
,
st
,
debugstr_w
(
name
)
);
TRACE
(
"%p %p %p %s
\n
"
,
db
,
stg
,
st
,
debugstr_w
(
name
)
);
...
@@ -2038,34 +2065,41 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
...
@@ -2038,34 +2065,41 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
{
{
if
(
mask
&
1
)
if
(
mask
&
1
)
{
{
WCHAR
table
[
32
];
DWORD
sz
=
32
;
UINT
number
=
MSI_NULL_INTEGER
;
TRACE
(
"inserting record
\n
"
);
TRACE
(
"inserting record
\n
"
);
/*
* Native msi seems writes nul into the
* Number (2nd) column of the _Columns table.
* Not sure that it's deliberate...
*/
if
(
!
lstrcmpW
(
name
,
szColumns
))
if
(
!
lstrcmpW
(
name
,
szColumns
))
{
{
WCHAR
table
[
32
];
DWORD
sz
=
32
;
MSI_RecordGetStringW
(
rec
,
1
,
table
,
&
sz
);
MSI_RecordGetStringW
(
rec
,
1
,
table
,
&
sz
);
number
=
MSI_RecordGetInteger
(
rec
,
2
);
/* reset the column number on a new table */
/*
if
(
lstrcmpW
(
coltable
,
table
)
)
* Native msi seems writes nul into the Number (2nd) column of
* the _Columns table, only when the columns are from a new table
*/
if
(
number
==
MSI_NULL_INTEGER
)
{
{
colcol
=
0
;
/* reset the column number on a new table */
lstrcpyW
(
coltable
,
table
);
if
(
lstrcmpW
(
coltable
,
table
)
)
{
colcol
=
0
;
lstrcpyW
(
coltable
,
table
);
}
/* fix nul column numbers */
MSI_RecordSetInteger
(
rec
,
2
,
++
colcol
);
}
}
/* fix nul column numbers */
MSI_RecordSetInteger
(
rec
,
2
,
++
colcol
);
}
}
r
=
TABLE_insert_row
(
&
tv
->
view
,
rec
,
FALSE
);
r
=
TABLE_insert_row
(
&
tv
->
view
,
rec
,
FALSE
);
if
(
r
!=
ERROR_SUCCESS
)
if
(
r
!=
ERROR_SUCCESS
)
ERR
(
"insert row failed
\n
"
);
ERR
(
"insert row failed
\n
"
);
if
(
number
!=
MSI_NULL_INTEGER
&&
!
lstrcmpW
(
name
,
szColumns
)
)
msi_update_table_columns
(
db
,
table
);
}
}
else
else
{
{
...
@@ -2108,11 +2142,12 @@ err:
...
@@ -2108,11 +2142,12 @@ err:
*/
*/
UINT
msi_table_apply_transform
(
MSIDATABASE
*
db
,
IStorage
*
stg
)
UINT
msi_table_apply_transform
(
MSIDATABASE
*
db
,
IStorage
*
stg
)
{
{
struct
list
transforms
;
IEnumSTATSTG
*
stgenum
=
NULL
;
IEnumSTATSTG
*
stgenum
=
NULL
;
TRANSFORMDATA
*
transform
;
TRANSFORMDATA
*
tables
=
NULL
,
*
columns
=
NULL
;
HRESULT
r
;
HRESULT
r
;
STATSTG
stat
;
STATSTG
stat
;
ULONG
count
;
WCHAR
name
[
0x40
];
string_table
*
strings
;
string_table
*
strings
;
UINT
ret
=
ERROR_FUNCTION_FAILED
;
UINT
ret
=
ERROR_FUNCTION_FAILED
;
UINT
bytes_per_strref
;
UINT
bytes_per_strref
;
...
@@ -2127,40 +2162,84 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
...
@@ -2127,40 +2162,84 @@ UINT msi_table_apply_transform( MSIDATABASE *db, IStorage *stg )
if
(
FAILED
(
r
)
)
if
(
FAILED
(
r
)
)
goto
end
;
goto
end
;
list_init
(
&
transforms
);
while
(
TRUE
)
{
MSITABLEVIEW
*
tv
=
NULL
;
WCHAR
name
[
0x40
];
ULONG
count
=
0
;
r
=
IEnumSTATSTG_Next
(
stgenum
,
1
,
&
stat
,
&
count
);
if
(
FAILED
(
r
)
||
!
count
)
break
;
decode_streamname
(
stat
.
pwcsName
,
name
);
if
(
name
[
0
]
!=
0x4840
)
continue
;
if
(
!
lstrcmpW
(
name
+
1
,
szStringPool
)
||
!
lstrcmpW
(
name
+
1
,
szStringData
)
)
continue
;
transform
=
msi_alloc_zero
(
sizeof
(
TRANSFORMDATA
)
);
if
(
!
transform
)
break
;
list_add_tail
(
&
transforms
,
&
transform
->
entry
);
transform
->
name
=
strdupW
(
name
+
1
);
if
(
!
lstrcmpW
(
transform
->
name
,
szTables
)
)
tables
=
transform
;
else
if
(
!
lstrcmpW
(
transform
->
name
,
szColumns
)
)
columns
=
transform
;
TRACE
(
"transform contains stream %s
\n
"
,
debugstr_w
(
name
));
/* load the table */
r
=
TABLE_CreateView
(
db
,
transform
->
name
,
(
MSIVIEW
**
)
&
tv
);
if
(
r
!=
ERROR_SUCCESS
)
continue
;
r
=
tv
->
view
.
ops
->
execute
(
&
tv
->
view
,
NULL
);
if
(
r
!=
ERROR_SUCCESS
)
{
tv
->
view
.
ops
->
delete
(
&
tv
->
view
);
continue
;
}
tv
->
view
.
ops
->
delete
(
&
tv
->
view
);
}
/*
/*
* Apply _Tables and _Columns transforms first so that
* Apply _Tables and _Columns transforms first so that
* the table metadata is correct, and empty tables exist.
* the table metadata is correct, and empty tables exist.
*/
*/
ret
=
msi_table_load_transform
(
db
,
stg
,
strings
,
szT
ables
,
bytes_per_strref
);
ret
=
msi_table_load_transform
(
db
,
stg
,
strings
,
t
ables
,
bytes_per_strref
);
if
(
ret
!=
ERROR_SUCCESS
&&
ret
!=
ERROR_INVALID_TABLE
)
if
(
ret
!=
ERROR_SUCCESS
&&
ret
!=
ERROR_INVALID_TABLE
)
goto
end
;
goto
end
;
ret
=
msi_table_load_transform
(
db
,
stg
,
strings
,
szC
olumns
,
bytes_per_strref
);
ret
=
msi_table_load_transform
(
db
,
stg
,
strings
,
c
olumns
,
bytes_per_strref
);
if
(
ret
!=
ERROR_SUCCESS
&&
ret
!=
ERROR_INVALID_TABLE
)
if
(
ret
!=
ERROR_SUCCESS
&&
ret
!=
ERROR_INVALID_TABLE
)
goto
end
;
goto
end
;
ret
=
ERROR_SUCCESS
;
ret
=
ERROR_SUCCESS
;
while
(
r
==
ERROR_SUCCESS
)
while
(
!
list_empty
(
&
transforms
)
)
{
{
count
=
0
;
transform
=
LIST_ENTRY
(
list_head
(
&
transforms
),
TRANSFORMDATA
,
entry
);
r
=
IEnumSTATSTG_Next
(
stgenum
,
1
,
&
stat
,
&
count
);
if
(
FAILED
(
r
)
||
!
count
)
break
;
decode_streamname
(
stat
.
pwcsName
,
name
);
if
(
name
[
0
]
!=
0x4840
)
continue
;
TRACE
(
"transform contains stream %s
\n
"
,
debugstr_w
(
name
));
if
(
!
lstrcmpW
(
name
+
1
,
szStringPool
)
||
if
(
lstrcmpW
(
transform
->
name
,
szColumns
)
&&
!
lstrcmpW
(
name
+
1
,
szStringData
)
||
lstrcmpW
(
transform
->
name
,
szTables
)
&&
!
lstrcmpW
(
name
+
1
,
szColumns
)
||
ret
==
ERROR_SUCCESS
)
!
lstrcmpW
(
name
+
1
,
szTables
)
)
{
continue
;
ret
=
msi_table_load_transform
(
db
,
stg
,
strings
,
transform
,
bytes_per_strref
);
}
ret
=
msi_table_load_transform
(
db
,
stg
,
strings
,
name
+
1
,
bytes_per_strref
);
list_remove
(
&
transform
->
entry
);
msi_free
(
transform
->
name
);
msi_free
(
transform
);
}
}
if
(
ret
==
ERROR_SUCCESS
)
if
(
ret
==
ERROR_SUCCESS
)
...
...
dlls/msi/tests/db.c
View file @
17ba7419
...
@@ -2049,30 +2049,21 @@ static void test_try_transform(void)
...
@@ -2049,30 +2049,21 @@ static void test_try_transform(void)
hrec
=
0
;
hrec
=
0
;
query
=
"select `NOO`,`OOO` from `MOO` where `NOO` = 1 AND `OOO` = 'c'"
;
query
=
"select `NOO`,`OOO` from `MOO` where `NOO` = 1 AND `OOO` = 'c'"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
r
=
do_query
(
hdb
,
query
,
&
hrec
);
todo_wine
ok
(
r
==
ERROR_SUCCESS
,
"select query failed
\n
"
);
{
ok
(
r
==
ERROR_SUCCESS
,
"select query failed
\n
"
);
}
MsiCloseHandle
(
hrec
);
MsiCloseHandle
(
hrec
);
/* check unchanged value */
/* check unchanged value */
hrec
=
0
;
hrec
=
0
;
query
=
"select `NOO`,`OOO` from `MOO` where `NOO` = 2 AND `OOO` = 'b'"
;
query
=
"select `NOO`,`OOO` from `MOO` where `NOO` = 2 AND `OOO` = 'b'"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
r
=
do_query
(
hdb
,
query
,
&
hrec
);
todo_wine
ok
(
r
==
ERROR_SUCCESS
,
"select query failed
\n
"
);
{
ok
(
r
==
ERROR_SUCCESS
,
"select query failed
\n
"
);
}
MsiCloseHandle
(
hrec
);
MsiCloseHandle
(
hrec
);
/* check deleted value */
/* check deleted value */
hrec
=
0
;
hrec
=
0
;
query
=
"select * from `MOO` where `NOO` = 3"
;
query
=
"select * from `MOO` where `NOO` = 3"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
r
=
do_query
(
hdb
,
query
,
&
hrec
);
todo_wine
ok
(
r
==
ERROR_NO_MORE_ITEMS
,
"select query failed
\n
"
);
{
ok
(
r
==
ERROR_NO_MORE_ITEMS
,
"select query failed
\n
"
);
}
if
(
hrec
)
MsiCloseHandle
(
hrec
);
if
(
hrec
)
MsiCloseHandle
(
hrec
);
/* check added stream */
/* check added stream */
...
@@ -2093,67 +2084,40 @@ static void test_try_transform(void)
...
@@ -2093,67 +2084,40 @@ static void test_try_transform(void)
hrec
=
0
;
hrec
=
0
;
query
=
"select * from `MOO`"
;
query
=
"select * from `MOO`"
;
r
=
MsiDatabaseOpenView
(
hdb
,
query
,
&
hview
);
r
=
MsiDatabaseOpenView
(
hdb
,
query
,
&
hview
);
todo_wine
ok
(
r
==
ERROR_SUCCESS
,
"open view failed
\n
"
);
{
ok
(
r
==
ERROR_SUCCESS
,
"open view failed
\n
"
);
}
r
=
MsiViewExecute
(
hview
,
0
);
r
=
MsiViewExecute
(
hview
,
0
);
todo_wine
ok
(
r
==
ERROR_SUCCESS
,
"view execute failed
\n
"
);
{
ok
(
r
==
ERROR_SUCCESS
,
"view execute failed
\n
"
);
}
r
=
MsiViewFetch
(
hview
,
&
hrec
);
r
=
MsiViewFetch
(
hview
,
&
hrec
);
todo_wine
ok
(
r
==
ERROR_SUCCESS
,
"view fetch failed
\n
"
);
{
ok
(
r
==
ERROR_SUCCESS
,
"view fetch failed
\n
"
);
}
r
=
MsiRecordGetInteger
(
hrec
,
1
);
r
=
MsiRecordGetInteger
(
hrec
,
1
);
todo_wine
ok
(
r
==
1
,
"Expected 1, got %d
\n
"
,
r
);
{
ok
(
r
==
1
,
"Expected 1, got %d
\n
"
,
r
);
}
sz
=
sizeof
buffer
;
sz
=
sizeof
buffer
;
r
=
MsiRecordGetString
(
hrec
,
2
,
buffer
,
&
sz
);
r
=
MsiRecordGetString
(
hrec
,
2
,
buffer
,
&
sz
);
todo_wine
ok
(
r
==
ERROR_SUCCESS
,
"record get string failed
\n
"
);
{
ok
(
!
lstrcmpA
(
buffer
,
"c"
),
"Expected c, got %s
\n
"
,
buffer
);
ok
(
r
==
ERROR_SUCCESS
,
"record get string failed
\n
"
);
ok
(
!
lstrcmpA
(
buffer
,
"c"
),
"Expected c, got %s
\n
"
,
buffer
);
}
r
=
MsiRecordGetInteger
(
hrec
,
3
);
r
=
MsiRecordGetInteger
(
hrec
,
3
);
ok
(
r
==
0x80000000
,
"Expected 0x80000000, got %d
\n
"
,
r
);
ok
(
r
==
0x80000000
,
"Expected 0x80000000, got %d
\n
"
,
r
);
r
=
MsiRecordGetInteger
(
hrec
,
4
);
r
=
MsiRecordGetInteger
(
hrec
,
4
);
todo_wine
ok
(
r
==
5
,
"Expected 5, got %d
\n
"
,
r
);
{
ok
(
r
==
5
,
"Expected 5, got %d
\n
"
,
r
);
}
MsiCloseHandle
(
hrec
);
MsiCloseHandle
(
hrec
);
r
=
MsiViewFetch
(
hview
,
&
hrec
);
r
=
MsiViewFetch
(
hview
,
&
hrec
);
todo_wine
ok
(
r
==
ERROR_SUCCESS
,
"view fetch failed
\n
"
);
{
ok
(
r
==
ERROR_SUCCESS
,
"view fetch failed
\n
"
);
}
r
=
MsiRecordGetInteger
(
hrec
,
1
);
r
=
MsiRecordGetInteger
(
hrec
,
1
);
todo_wine
ok
(
r
==
2
,
"Expected 2, got %d
\n
"
,
r
);
{
ok
(
r
==
2
,
"Expected 2, got %d
\n
"
,
r
);
}
sz
=
sizeof
buffer
;
sz
=
sizeof
buffer
;
r
=
MsiRecordGetString
(
hrec
,
2
,
buffer
,
&
sz
);
r
=
MsiRecordGetString
(
hrec
,
2
,
buffer
,
&
sz
);
todo_wine
ok
(
r
==
ERROR_SUCCESS
,
"record get string failed
\n
"
);
{
ok
(
!
lstrcmpA
(
buffer
,
"b"
),
"Expected b, got %s
\n
"
,
buffer
);
ok
(
r
==
ERROR_SUCCESS
,
"record get string failed
\n
"
);
ok
(
!
lstrcmpA
(
buffer
,
"b"
),
"Expected b, got %s
\n
"
,
buffer
);
}
r
=
MsiRecordGetInteger
(
hrec
,
3
);
r
=
MsiRecordGetInteger
(
hrec
,
3
);
ok
(
r
==
0x80000000
,
"Expected 0x80000000, got %d
\n
"
,
r
);
ok
(
r
==
0x80000000
,
"Expected 0x80000000, got %d
\n
"
,
r
);
...
@@ -2164,10 +2128,7 @@ static void test_try_transform(void)
...
@@ -2164,10 +2128,7 @@ static void test_try_transform(void)
MsiCloseHandle
(
hrec
);
MsiCloseHandle
(
hrec
);
r
=
MsiViewFetch
(
hview
,
&
hrec
);
r
=
MsiViewFetch
(
hview
,
&
hrec
);
todo_wine
ok
(
r
==
ERROR_NO_MORE_ITEMS
,
"view fetch succeeded
\n
"
);
{
ok
(
r
==
ERROR_NO_MORE_ITEMS
,
"view fetch succeeded
\n
"
);
}
MsiCloseHandle
(
hrec
);
MsiCloseHandle
(
hrec
);
MsiCloseHandle
(
hview
);
MsiCloseHandle
(
hview
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment