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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
38 typedef struct tagDISTINCTSET
43 struct tagDISTINCTSET
*nextrow
;
44 struct tagDISTINCTSET
*nextcol
;
47 typedef struct tagMSIDISTINCTVIEW
56 static DISTINCTSET
** distinct_insert( DISTINCTSET
**x
, UINT val
, UINT row
)
58 /* horrible O(n) find */
61 if( (*x
)->val
== val
)
69 /* nothing found, so add one */
70 *x
= HeapAlloc( GetProcessHeap(), 0, sizeof (DISTINCTSET
) );
82 static void distinct_free( DISTINCTSET
*x
)
86 DISTINCTSET
*next
= x
->nextrow
;
87 distinct_free( x
->nextcol
);
88 HeapFree( GetProcessHeap(), 0, x
);
93 static UINT
DISTINCT_fetch_int( struct tagMSIVIEW
*view
, UINT row
, UINT col
, UINT
*val
)
95 MSIDISTINCTVIEW
*dv
= (MSIDISTINCTVIEW
*)view
;
97 TRACE("%p %d %d %p\n", dv
, row
, col
, val
);
100 return ERROR_FUNCTION_FAILED
;
102 if( row
>= dv
->row_count
)
103 return ERROR_INVALID_PARAMETER
;
105 row
= dv
->translation
[ row
];
107 return dv
->table
->ops
->fetch_int( dv
->table
, row
, col
, val
);
110 static UINT
DISTINCT_execute( struct tagMSIVIEW
*view
, MSIHANDLE record
)
112 MSIDISTINCTVIEW
*dv
= (MSIDISTINCTVIEW
*)view
;
113 UINT r
, i
, j
, r_count
, c_count
;
114 DISTINCTSET
*rowset
= NULL
;
116 TRACE("%p %ld\n", dv
, record
);
119 return ERROR_FUNCTION_FAILED
;
121 r
= dv
->table
->ops
->execute( dv
->table
, record
);
122 if( r
!= ERROR_SUCCESS
)
125 r
= dv
->table
->ops
->get_dimensions( dv
->table
, &r_count
, &c_count
);
126 if( r
!= ERROR_SUCCESS
)
129 dv
->translation
= HeapAlloc( GetProcessHeap(), 0, r_count
*sizeof(UINT
) );
130 if( !dv
->translation
)
131 return ERROR_FUNCTION_FAILED
;
134 for( i
=0; i
<r_count
; i
++ )
136 DISTINCTSET
**x
= &rowset
;
138 for( j
=1; j
<=c_count
; j
++ )
141 r
= dv
->table
->ops
->fetch_int( dv
->table
, i
, j
, &val
);
142 if( r
!= ERROR_SUCCESS
)
144 ERR("Failed to fetch int at %d %d\n", i
, j
);
145 distinct_free( rowset
);
148 x
= distinct_insert( x
, val
, i
);
151 ERR("Failed to insert at %d %d\n", i
, j
);
152 distinct_free( rowset
);
153 return ERROR_FUNCTION_FAILED
;
159 /* check if it was distinct and if so, include it */
162 TRACE("Row %d -> %d\n", dv
->row_count
, i
);
163 dv
->translation
[dv
->row_count
++] = i
;
167 distinct_free( rowset
);
169 return ERROR_SUCCESS
;
172 static UINT
DISTINCT_close( struct tagMSIVIEW
*view
)
174 MSIDISTINCTVIEW
*dv
= (MSIDISTINCTVIEW
*)view
;
179 return ERROR_FUNCTION_FAILED
;
181 if( dv
->translation
)
182 HeapFree( GetProcessHeap(), 0, dv
->translation
);
183 dv
->translation
= NULL
;
186 return dv
->table
->ops
->close( dv
->table
);
189 static UINT
DISTINCT_get_dimensions( struct tagMSIVIEW
*view
, UINT
*rows
, UINT
*cols
)
191 MSIDISTINCTVIEW
*dv
= (MSIDISTINCTVIEW
*)view
;
193 TRACE("%p %p %p\n", dv
, rows
, cols
);
196 return ERROR_FUNCTION_FAILED
;
200 if( !dv
->translation
)
201 return ERROR_FUNCTION_FAILED
;
202 *rows
= dv
->row_count
;
205 return dv
->table
->ops
->get_dimensions( dv
->table
, NULL
, cols
);
208 static UINT
DISTINCT_get_column_info( struct tagMSIVIEW
*view
,
209 UINT n
, LPWSTR
*name
, UINT
*type
)
211 MSIDISTINCTVIEW
*dv
= (MSIDISTINCTVIEW
*)view
;
213 TRACE("%p %d %p %p\n", dv
, n
, name
, type
);
216 return ERROR_FUNCTION_FAILED
;
218 return dv
->table
->ops
->get_column_info( dv
->table
, n
, name
, type
);
221 static UINT
DISTINCT_modify( struct tagMSIVIEW
*view
, MSIMODIFY eModifyMode
, MSIHANDLE hrec
)
223 MSIDISTINCTVIEW
*dv
= (MSIDISTINCTVIEW
*)view
;
225 TRACE("%p %d %ld\n", dv
, eModifyMode
, hrec
);
228 return ERROR_FUNCTION_FAILED
;
230 return dv
->table
->ops
->modify( dv
->table
, eModifyMode
, hrec
);
233 static UINT
DISTINCT_delete( struct tagMSIVIEW
*view
)
235 MSIDISTINCTVIEW
*dv
= (MSIDISTINCTVIEW
*)view
;
240 dv
->table
->ops
->delete( dv
->table
);
242 if( dv
->translation
)
243 HeapFree( GetProcessHeap(), 0, dv
->translation
);
244 HeapFree( GetProcessHeap(), 0, dv
);
246 return ERROR_SUCCESS
;
250 MSIVIEWOPS distinct_ops
=
258 DISTINCT_get_dimensions
,
259 DISTINCT_get_column_info
,
264 UINT
DISTINCT_CreateView( MSIDATABASE
*db
, MSIVIEW
**view
, MSIVIEW
*table
)
266 MSIDISTINCTVIEW
*dv
= NULL
;
271 r
= table
->ops
->get_dimensions( table
, NULL
, &count
);
272 if( r
!= ERROR_SUCCESS
)
274 ERR("can't get table dimensions\n");
278 dv
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof *dv
);
280 return ERROR_FUNCTION_FAILED
;
282 /* fill the structure */
283 dv
->view
.ops
= &distinct_ops
;
286 dv
->translation
= NULL
;
288 *view
= (MSIVIEW
*) dv
;
290 return ERROR_SUCCESS
;