2 * Implementation of the Microsoft Installer (msi.dll)
4 * Copyright 2002 Mike McCormack for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(msidb
);
39 /* below is the query interface to a table */
41 typedef struct tagMSIORDERVIEW
51 static UINT
ORDER_compare( MSIORDERVIEW
*ov
, UINT a
, UINT b
, UINT
*swap
)
53 UINT r
, i
, a_val
= 0, b_val
= 0;
56 for( i
=0; i
<ov
->num_cols
; i
++ )
58 r
= ov
->table
->ops
->fetch_int( ov
->table
, a
, ov
->cols
[i
], &a_val
);
59 if( r
!= ERROR_SUCCESS
)
62 r
= ov
->table
->ops
->fetch_int( ov
->table
, b
, ov
->cols
[i
], &b_val
);
63 if( r
!= ERROR_SUCCESS
)
77 static UINT
ORDER_mergesort( MSIORDERVIEW
*ov
, UINT left
, UINT right
)
79 UINT r
, centre
= (left
+ right
)/2, temp
, swap
= 0, i
, j
;
80 UINT
*array
= ov
->reorder
;
85 /* sort the left half */
86 r
= ORDER_mergesort( ov
, left
, centre
);
87 if( r
!= ERROR_SUCCESS
)
90 /* sort the right half */
91 r
= ORDER_mergesort( ov
, centre
+1, right
);
92 if( r
!= ERROR_SUCCESS
)
95 for( i
=left
, j
=centre
+1; (i
<=centre
) && (j
<=right
); i
++ )
97 r
= ORDER_compare( ov
, array
[i
], array
[j
], &swap
);
98 if( r
!= ERROR_SUCCESS
)
103 memmove( &array
[i
+1], &array
[i
], (j
-i
)*sizeof (UINT
) );
110 return ERROR_SUCCESS
;
113 static UINT
ORDER_verify( MSIORDERVIEW
*ov
, UINT num_rows
)
117 for( i
=1; i
<num_rows
; i
++ )
119 r
= ORDER_compare( ov
, ov
->reorder
[i
-1], ov
->reorder
[i
], &swap
);
120 if( r
!= ERROR_SUCCESS
)
124 ERR("Bad order! %d\n", i
);
125 return ERROR_FUNCTION_FAILED
;
128 return ERROR_SUCCESS
;
131 static UINT
ORDER_fetch_int( struct tagMSIVIEW
*view
, UINT row
, UINT col
, UINT
*val
)
133 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
135 TRACE("%p %d %d %p\n", ov
, row
, col
, val
);
138 return ERROR_FUNCTION_FAILED
;
140 row
= ov
->reorder
[ row
];
142 return ov
->table
->ops
->fetch_int( ov
->table
, row
, col
, val
);
145 static UINT
ORDER_get_row( struct tagMSIVIEW
*view
, UINT row
, MSIRECORD
**rec
)
147 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
149 TRACE("%p %d %p\n", ov
, row
, rec
);
152 return ERROR_FUNCTION_FAILED
;
154 row
= ov
->reorder
[row
];
156 return ov
->table
->ops
->get_row(ov
->table
, row
, rec
);
159 static UINT
ORDER_execute( struct tagMSIVIEW
*view
, MSIRECORD
*record
)
161 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
162 UINT r
, num_rows
= 0, i
;
164 TRACE("%p %p\n", ov
, record
);
167 return ERROR_FUNCTION_FAILED
;
169 r
= ov
->table
->ops
->execute( ov
->table
, record
);
170 if( r
!= ERROR_SUCCESS
)
173 r
= ov
->table
->ops
->get_dimensions( ov
->table
, &num_rows
, NULL
);
174 if( r
!= ERROR_SUCCESS
)
177 ov
->reorder
= msi_alloc( num_rows
*sizeof(UINT
) );
179 return ERROR_FUNCTION_FAILED
;
181 for( i
=0; i
<num_rows
; i
++ )
184 r
= ORDER_mergesort( ov
, 0, num_rows
- 1 );
185 if( r
!= ERROR_SUCCESS
)
188 r
= ORDER_verify( ov
, num_rows
);
189 if( r
!= ERROR_SUCCESS
)
192 return ERROR_SUCCESS
;
195 static UINT
ORDER_close( struct tagMSIVIEW
*view
)
197 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
202 return ERROR_FUNCTION_FAILED
;
204 msi_free( ov
->reorder
);
207 return ov
->table
->ops
->close( ov
->table
);
210 static UINT
ORDER_get_dimensions( struct tagMSIVIEW
*view
, UINT
*rows
, UINT
*cols
)
212 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
214 TRACE("%p %p %p\n", ov
, rows
, cols
);
217 return ERROR_FUNCTION_FAILED
;
219 return ov
->table
->ops
->get_dimensions( ov
->table
, rows
, cols
);
222 static UINT
ORDER_get_column_info( struct tagMSIVIEW
*view
,
223 UINT n
, LPWSTR
*name
, UINT
*type
)
225 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
227 TRACE("%p %d %p %p\n", ov
, n
, name
, type
);
230 return ERROR_FUNCTION_FAILED
;
232 return ov
->table
->ops
->get_column_info( ov
->table
, n
, name
, type
);
235 static UINT
ORDER_modify( struct tagMSIVIEW
*view
, MSIMODIFY eModifyMode
,
236 MSIRECORD
*rec
, UINT row
)
238 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
240 TRACE("%p %d %p\n", ov
, eModifyMode
, rec
);
243 return ERROR_FUNCTION_FAILED
;
245 return ov
->table
->ops
->modify( ov
->table
, eModifyMode
, rec
, row
);
248 static UINT
ORDER_delete( struct tagMSIVIEW
*view
)
250 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
255 ov
->table
->ops
->delete( ov
->table
);
257 msi_free( ov
->reorder
);
260 msiobj_release( &ov
->db
->hdr
);
263 return ERROR_SUCCESS
;
266 static UINT
ORDER_find_matching_rows( struct tagMSIVIEW
*view
, UINT col
,
267 UINT val
, UINT
*row
, MSIITERHANDLE
*handle
)
269 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
272 TRACE("%p, %d, %u, %p\n", ov
, col
, val
, *handle
);
275 return ERROR_FUNCTION_FAILED
;
277 r
= ov
->table
->ops
->find_matching_rows( ov
->table
, col
, val
, row
, handle
);
279 *row
= ov
->reorder
[ *row
];
285 static const MSIVIEWOPS order_ops
=
295 ORDER_get_dimensions
,
296 ORDER_get_column_info
,
299 ORDER_find_matching_rows
,
306 static UINT
ORDER_AddColumn( MSIORDERVIEW
*ov
, LPCWSTR name
)
311 TRACE("%p adding %s\n", ov
, debugstr_w( name
) );
313 if( ov
->view
.ops
!= &order_ops
)
314 return ERROR_FUNCTION_FAILED
;
318 return ERROR_FUNCTION_FAILED
;
319 if( !table
->ops
->get_dimensions
)
320 return ERROR_FUNCTION_FAILED
;
321 if( !table
->ops
->get_column_info
)
322 return ERROR_FUNCTION_FAILED
;
324 r
= table
->ops
->get_dimensions( table
, NULL
, &count
);
325 if( r
!= ERROR_SUCCESS
)
328 if( ov
->num_cols
>= count
)
329 return ERROR_FUNCTION_FAILED
;
331 r
= VIEW_find_column( table
, name
, &n
);
332 if( r
!= ERROR_SUCCESS
)
335 ov
->cols
[ov
->num_cols
] = n
;
336 TRACE("Ordering by column %s (%d)\n", debugstr_w( name
), n
);
340 return ERROR_SUCCESS
;
343 UINT
ORDER_CreateView( MSIDATABASE
*db
, MSIVIEW
**view
, MSIVIEW
*table
,
344 column_info
*columns
)
346 MSIORDERVIEW
*ov
= NULL
;
352 r
= table
->ops
->get_dimensions( table
, NULL
, &count
);
353 if( r
!= ERROR_SUCCESS
)
355 ERR("can't get table dimensions\n");
359 ov
= msi_alloc_zero( sizeof *ov
+ sizeof (UINT
) * count
);
361 return ERROR_FUNCTION_FAILED
;
363 /* fill the structure */
364 ov
->view
.ops
= &order_ops
;
365 msiobj_addref( &db
->hdr
);
370 *view
= (MSIVIEW
*) ov
;
372 for( x
= columns
; x
; x
= x
->next
)
373 ORDER_AddColumn( ov
, x
->column
);
375 return ERROR_SUCCESS
;