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
21 #define WIN32_NO_STATUS
23 #define COM_NO_WINDOWS_H
28 //#include "winbase.h"
29 //#include "winerror.h"
30 #include <wine/debug.h>
32 //#include "msiquery.h"
33 //#include "objbase.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msidb
);
42 typedef struct tagDISTINCTSET
47 struct tagDISTINCTSET
*nextrow
;
48 struct tagDISTINCTSET
*nextcol
;
51 typedef struct tagMSIDISTINCTVIEW
60 static DISTINCTSET
** distinct_insert( DISTINCTSET
**x
, UINT val
, UINT row
)
62 /* horrible O(n) find */
65 if( (*x
)->val
== val
)
73 /* nothing found, so add one */
74 *x
= msi_alloc( sizeof (DISTINCTSET
) );
86 static void distinct_free( DISTINCTSET
*x
)
90 DISTINCTSET
*next
= x
->nextrow
;
91 distinct_free( x
->nextcol
);
97 static UINT
DISTINCT_fetch_int( struct tagMSIVIEW
*view
, UINT row
, UINT col
, UINT
*val
)
99 MSIDISTINCTVIEW
*dv
= (MSIDISTINCTVIEW
*)view
;
101 TRACE("%p %d %d %p\n", dv
, row
, col
, val
);
104 return ERROR_FUNCTION_FAILED
;
106 if( row
>= dv
->row_count
)
107 return ERROR_INVALID_PARAMETER
;
109 row
= dv
->translation
[ row
];
111 return dv
->table
->ops
->fetch_int( dv
->table
, row
, col
, val
);
114 static UINT
DISTINCT_execute( struct tagMSIVIEW
*view
, MSIRECORD
*record
)
116 MSIDISTINCTVIEW
*dv
= (MSIDISTINCTVIEW
*)view
;
117 UINT r
, i
, j
, r_count
, c_count
;
118 DISTINCTSET
*rowset
= NULL
;
120 TRACE("%p %p\n", dv
, record
);
123 return ERROR_FUNCTION_FAILED
;
125 r
= dv
->table
->ops
->execute( dv
->table
, record
);
126 if( r
!= ERROR_SUCCESS
)
129 r
= dv
->table
->ops
->get_dimensions( dv
->table
, &r_count
, &c_count
);
130 if( r
!= ERROR_SUCCESS
)
133 dv
->translation
= msi_alloc( r_count
*sizeof(UINT
) );
134 if( !dv
->translation
)
135 return ERROR_FUNCTION_FAILED
;
138 for( i
=0; i
<r_count
; i
++ )
140 DISTINCTSET
**x
= &rowset
;
142 for( j
=1; j
<=c_count
; j
++ )
145 r
= dv
->table
->ops
->fetch_int( dv
->table
, i
, j
, &val
);
146 if( r
!= ERROR_SUCCESS
)
148 ERR("Failed to fetch int at %d %d\n", i
, j
);
149 distinct_free( rowset
);
152 x
= distinct_insert( x
, val
, i
);
155 ERR("Failed to insert at %d %d\n", i
, j
);
156 distinct_free( rowset
);
157 return ERROR_FUNCTION_FAILED
;
163 /* check if it was distinct and if so, include it */
166 TRACE("Row %d -> %d\n", dv
->row_count
, i
);
167 dv
->translation
[dv
->row_count
++] = i
;
171 distinct_free( rowset
);
173 return ERROR_SUCCESS
;
176 static UINT
DISTINCT_close( struct tagMSIVIEW
*view
)
178 MSIDISTINCTVIEW
*dv
= (MSIDISTINCTVIEW
*)view
;
183 return ERROR_FUNCTION_FAILED
;
185 msi_free( dv
->translation
);
186 dv
->translation
= NULL
;
189 return dv
->table
->ops
->close( dv
->table
);
192 static UINT
DISTINCT_get_dimensions( struct tagMSIVIEW
*view
, UINT
*rows
, UINT
*cols
)
194 MSIDISTINCTVIEW
*dv
= (MSIDISTINCTVIEW
*)view
;
196 TRACE("%p %p %p\n", dv
, rows
, cols
);
199 return ERROR_FUNCTION_FAILED
;
203 if( !dv
->translation
)
204 return ERROR_FUNCTION_FAILED
;
205 *rows
= dv
->row_count
;
208 return dv
->table
->ops
->get_dimensions( dv
->table
, NULL
, cols
);
211 static UINT
DISTINCT_get_column_info( struct tagMSIVIEW
*view
, UINT n
, LPCWSTR
*name
,
212 UINT
*type
, BOOL
*temporary
, LPCWSTR
*table_name
)
214 MSIDISTINCTVIEW
*dv
= (MSIDISTINCTVIEW
*)view
;
216 TRACE("%p %d %p %p %p %p\n", dv
, n
, name
, type
, temporary
, table_name
);
219 return ERROR_FUNCTION_FAILED
;
221 return dv
->table
->ops
->get_column_info( dv
->table
, n
, name
,
222 type
, temporary
, table_name
);
225 static UINT
DISTINCT_modify( struct tagMSIVIEW
*view
, MSIMODIFY eModifyMode
,
226 MSIRECORD
*rec
, UINT row
)
228 MSIDISTINCTVIEW
*dv
= (MSIDISTINCTVIEW
*)view
;
230 TRACE("%p %d %p\n", dv
, eModifyMode
, rec
);
233 return ERROR_FUNCTION_FAILED
;
235 return dv
->table
->ops
->modify( dv
->table
, eModifyMode
, rec
, row
);
238 static UINT
DISTINCT_delete( struct tagMSIVIEW
*view
)
240 MSIDISTINCTVIEW
*dv
= (MSIDISTINCTVIEW
*)view
;
245 dv
->table
->ops
->delete( dv
->table
);
247 msi_free( dv
->translation
);
248 msiobj_release( &dv
->db
->hdr
);
251 return ERROR_SUCCESS
;
254 static UINT
DISTINCT_find_matching_rows( struct tagMSIVIEW
*view
, UINT col
,
255 UINT val
, UINT
*row
, MSIITERHANDLE
*handle
)
257 MSIDISTINCTVIEW
*dv
= (MSIDISTINCTVIEW
*)view
;
260 TRACE("%p, %d, %u, %p\n", view
, col
, val
, *handle
);
263 return ERROR_FUNCTION_FAILED
;
265 r
= dv
->table
->ops
->find_matching_rows( dv
->table
, col
, val
, row
, handle
);
267 if( *row
> dv
->row_count
)
268 return ERROR_NO_MORE_ITEMS
;
270 *row
= dv
->translation
[ *row
];
275 static const MSIVIEWOPS distinct_ops
=
285 DISTINCT_get_dimensions
,
286 DISTINCT_get_column_info
,
289 DISTINCT_find_matching_rows
,
298 UINT
DISTINCT_CreateView( MSIDATABASE
*db
, MSIVIEW
**view
, MSIVIEW
*table
)
300 MSIDISTINCTVIEW
*dv
= NULL
;
305 r
= table
->ops
->get_dimensions( table
, NULL
, &count
);
306 if( r
!= ERROR_SUCCESS
)
308 ERR("can't get table dimensions\n");
312 dv
= msi_alloc_zero( sizeof *dv
);
314 return ERROR_FUNCTION_FAILED
;
316 /* fill the structure */
317 dv
->view
.ops
= &distinct_ops
;
318 msiobj_addref( &db
->hdr
);
321 dv
->translation
= NULL
;
323 *view
= (MSIVIEW
*) dv
;
325 return ERROR_SUCCESS
;