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_execute( struct tagMSIVIEW
*view
, MSIRECORD
*record
)
147 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
148 UINT r
, num_rows
= 0, i
;
150 TRACE("%p %p\n", ov
, record
);
153 return ERROR_FUNCTION_FAILED
;
155 r
= ov
->table
->ops
->execute( ov
->table
, record
);
156 if( r
!= ERROR_SUCCESS
)
159 r
= ov
->table
->ops
->get_dimensions( ov
->table
, &num_rows
, NULL
);
160 if( r
!= ERROR_SUCCESS
)
163 ov
->reorder
= msi_alloc( num_rows
*sizeof(UINT
) );
165 return ERROR_FUNCTION_FAILED
;
167 for( i
=0; i
<num_rows
; i
++ )
170 r
= ORDER_mergesort( ov
, 0, num_rows
- 1 );
171 if( r
!= ERROR_SUCCESS
)
174 r
= ORDER_verify( ov
, num_rows
);
175 if( r
!= ERROR_SUCCESS
)
178 return ERROR_SUCCESS
;
181 static UINT
ORDER_close( struct tagMSIVIEW
*view
)
183 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
188 return ERROR_FUNCTION_FAILED
;
190 msi_free( ov
->reorder
);
193 return ov
->table
->ops
->close( ov
->table
);
196 static UINT
ORDER_get_dimensions( struct tagMSIVIEW
*view
, UINT
*rows
, UINT
*cols
)
198 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
200 TRACE("%p %p %p\n", ov
, rows
, cols
);
203 return ERROR_FUNCTION_FAILED
;
205 return ov
->table
->ops
->get_dimensions( ov
->table
, rows
, cols
);
208 static UINT
ORDER_get_column_info( struct tagMSIVIEW
*view
,
209 UINT n
, LPWSTR
*name
, UINT
*type
)
211 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
213 TRACE("%p %d %p %p\n", ov
, n
, name
, type
);
216 return ERROR_FUNCTION_FAILED
;
218 return ov
->table
->ops
->get_column_info( ov
->table
, n
, name
, type
);
221 static UINT
ORDER_modify( struct tagMSIVIEW
*view
, MSIMODIFY eModifyMode
,
224 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
226 TRACE("%p %d %p\n", ov
, eModifyMode
, rec
);
229 return ERROR_FUNCTION_FAILED
;
231 return ov
->table
->ops
->modify( ov
->table
, eModifyMode
, rec
);
234 static UINT
ORDER_delete( struct tagMSIVIEW
*view
)
236 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
241 ov
->table
->ops
->delete( ov
->table
);
243 msi_free( ov
->reorder
);
246 msiobj_release( &ov
->db
->hdr
);
249 return ERROR_SUCCESS
;
252 static UINT
ORDER_find_matching_rows( struct tagMSIVIEW
*view
, UINT col
,
253 UINT val
, UINT
*row
, MSIITERHANDLE
*handle
)
255 MSIORDERVIEW
*ov
= (MSIORDERVIEW
*)view
;
258 TRACE("%p, %d, %u, %p\n", ov
, col
, val
, *handle
);
261 return ERROR_FUNCTION_FAILED
;
263 r
= ov
->table
->ops
->find_matching_rows( ov
->table
, col
, val
, row
, handle
);
265 *row
= ov
->reorder
[ *row
];
271 static const MSIVIEWOPS order_ops
=
279 ORDER_get_dimensions
,
280 ORDER_get_column_info
,
283 ORDER_find_matching_rows
286 static UINT
ORDER_AddColumn( MSIORDERVIEW
*ov
, LPCWSTR name
)
291 TRACE("%p adding %s\n", ov
, debugstr_w( name
) );
293 if( ov
->view
.ops
!= &order_ops
)
294 return ERROR_FUNCTION_FAILED
;
298 return ERROR_FUNCTION_FAILED
;
299 if( !table
->ops
->get_dimensions
)
300 return ERROR_FUNCTION_FAILED
;
301 if( !table
->ops
->get_column_info
)
302 return ERROR_FUNCTION_FAILED
;
304 r
= table
->ops
->get_dimensions( table
, NULL
, &count
);
305 if( r
!= ERROR_SUCCESS
)
308 if( ov
->num_cols
>= count
)
309 return ERROR_FUNCTION_FAILED
;
311 r
= VIEW_find_column( table
, name
, &n
);
312 if( r
!= ERROR_SUCCESS
)
315 ov
->cols
[ov
->num_cols
] = n
;
316 TRACE("Ordering by column %s (%d)\n", debugstr_w( name
), n
);
320 return ERROR_SUCCESS
;
323 UINT
ORDER_CreateView( MSIDATABASE
*db
, MSIVIEW
**view
, MSIVIEW
*table
,
324 column_info
*columns
)
326 MSIORDERVIEW
*ov
= NULL
;
332 r
= table
->ops
->get_dimensions( table
, NULL
, &count
);
333 if( r
!= ERROR_SUCCESS
)
335 ERR("can't get table dimensions\n");
339 ov
= msi_alloc_zero( sizeof *ov
+ sizeof (UINT
) * count
);
341 return ERROR_FUNCTION_FAILED
;
343 /* fill the structure */
344 ov
->view
.ops
= &order_ops
;
345 msiobj_addref( &db
->hdr
);
350 *view
= (MSIVIEW
*) ov
;
352 for( x
= columns
; x
; x
= x
->next
)
353 ORDER_AddColumn( ov
, x
->column
);
355 return ERROR_SUCCESS
;