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
27 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(msi
);
38 #define MSIFIELD_NULL 0
39 #define MSIFIELD_INT 1
40 #define MSIFIELD_STR 2
41 #define MSIFIELD_WSTR 3
42 #define MSIFIELD_STREAM 4
44 /* maybe we can use a Variant instead of doing it ourselves? */
45 typedef struct tagMSIFIELD
57 typedef struct tagMSIRECORD
59 UINT count
; /* as passed to MsiCreateRecord */
60 MSIFIELD fields
[1]; /* nb. array size is count+1 */
63 void MSI_FreeField( MSIFIELD
*field
)
71 HeapFree( GetProcessHeap(), 0, field
->u
.szVal
);
74 HeapFree( GetProcessHeap(), 0, field
->u
.szwVal
);
77 IStream_Release( field
->u
.stream
);
80 ERR("Invalid field type %d\n", field
->type
);
84 void MSI_CloseRecord( VOID
*arg
)
86 MSIRECORD
*rec
= (MSIRECORD
*) arg
;
89 for( i
=0; i
<rec
->count
; i
++ )
90 MSI_FreeField( &rec
->fields
[i
] );
93 MSIHANDLE WINAPI
MsiCreateRecord( unsigned int cParams
)
99 TRACE("%d\n", cParams
);
101 sz
= sizeof (MSIRECORD
) + sizeof(MSIFIELD
)*(cParams
+1) ;
102 handle
= alloc_msihandle( MSIHANDLETYPE_RECORD
, sz
, MSI_CloseRecord
);
106 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
110 rec
->count
= cParams
;
115 unsigned int WINAPI
MsiRecordGetFieldCount( MSIHANDLE handle
)
119 TRACE("%ld\n", handle
);
121 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
124 ERR("Record not found!\n");
131 static BOOL
string2intA( LPCSTR str
, int *out
)
136 if( *p
== '-' ) /* skip the minus sign */
140 if( (*p
< '0') || (*p
> '9') )
147 if( str
[0] == '-' ) /* check if it's negative */
154 static BOOL
string2intW( LPCWSTR str
, int *out
)
159 if( *p
== '-' ) /* skip the minus sign */
163 if( (*p
< '0') || (*p
> '9') )
170 if( str
[0] == '-' ) /* check if it's negative */
177 int WINAPI
MsiRecordGetInteger( MSIHANDLE handle
, unsigned int iField
)
182 TRACE("%ld %d\n", handle
, iField
);
184 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
186 return MSI_NULL_INTEGER
;
188 if( iField
> rec
->count
)
189 return MSI_NULL_INTEGER
;
191 switch( rec
->fields
[iField
].type
)
194 return rec
->fields
[iField
].u
.iVal
;
196 if( string2intA( rec
->fields
[iField
].u
.szVal
, &ret
) )
198 return MSI_NULL_INTEGER
;
200 if( string2intW( rec
->fields
[iField
].u
.szwVal
, &ret
) )
202 return MSI_NULL_INTEGER
;
207 return MSI_NULL_INTEGER
;
210 UINT WINAPI
MsiRecordClearData( MSIHANDLE handle
)
215 TRACE("%ld\n", handle
);
217 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
219 return ERROR_INVALID_HANDLE
;
221 for( i
=0; i
<=rec
->count
; i
++)
223 MSI_FreeField( &rec
->fields
[i
] );
224 rec
->fields
[i
].type
= MSIFIELD_NULL
;
225 rec
->fields
[i
].u
.iVal
= 0;
228 return ERROR_SUCCESS
;
231 UINT WINAPI
MsiRecordSetInteger( MSIHANDLE handle
, unsigned int iField
, int iVal
)
235 TRACE("%ld %u %d\n", handle
,iField
, iVal
);
237 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
239 return ERROR_INVALID_HANDLE
;
241 if( iField
> rec
->count
)
242 return ERROR_INVALID_FIELD
;
244 MSI_FreeField( &rec
->fields
[iField
] );
245 rec
->fields
[iField
].type
= MSIFIELD_INT
;
246 rec
->fields
[iField
].u
.iVal
= iVal
;
248 return ERROR_SUCCESS
;
251 BOOL WINAPI
MsiRecordIsNull( MSIHANDLE handle
, unsigned int iField
)
255 TRACE("%ld %d\n", handle
,iField
);
257 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
259 return ERROR_INVALID_HANDLE
;
261 if( iField
> rec
->count
)
264 if( rec
->fields
[iField
].type
== MSIFIELD_NULL
)
270 UINT WINAPI
MsiRecordGetStringA(MSIHANDLE handle
, unsigned int iField
,
271 LPSTR szValue
, DWORD
*pcchValue
)
277 TRACE("%ld %d %p %p\n", handle
, iField
, szValue
, pcchValue
);
279 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
281 return ERROR_INVALID_HANDLE
;
283 if( iField
> rec
->count
)
284 return ERROR_INVALID_PARAMETER
;
287 switch( rec
->fields
[iField
].type
)
290 wsprintfA(buffer
, "%d", rec
->fields
[iField
].u
.iVal
);
291 len
= lstrlenA( buffer
);
292 lstrcpynA(szValue
, buffer
, *pcchValue
);
295 len
= lstrlenA( rec
->fields
[iField
].u
.szVal
);
296 lstrcpynA(szValue
, rec
->fields
[iField
].u
.szVal
, *pcchValue
);
299 len
= WideCharToMultiByte( CP_ACP
, 0, rec
->fields
[iField
].u
.szwVal
, -1,
300 NULL
, 0 , NULL
, NULL
);
301 WideCharToMultiByte( CP_ACP
, 0, rec
->fields
[iField
].u
.szwVal
, -1,
302 szValue
, *pcchValue
, NULL
, NULL
);
305 ret
= ERROR_INVALID_PARAMETER
;
309 if( *pcchValue
< len
)
310 ret
= ERROR_MORE_DATA
;
316 UINT WINAPI
MsiRecordGetStringW(MSIHANDLE handle
, unsigned int iField
,
317 LPWSTR szValue
, DWORD
*pcchValue
)
322 const WCHAR szFormat
[] = { '%','d',0 };
324 TRACE("%ld %d %p %p\n", handle
, iField
, szValue
, pcchValue
);
326 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
328 return ERROR_INVALID_HANDLE
;
330 if( iField
> rec
->count
)
331 return ERROR_INVALID_PARAMETER
;
334 switch( rec
->fields
[iField
].type
)
337 wsprintfW(buffer
, szFormat
, rec
->fields
[iField
].u
.iVal
);
338 len
= lstrlenW( buffer
);
339 lstrcpynW(szValue
, buffer
, *pcchValue
);
342 len
= lstrlenW( rec
->fields
[iField
].u
.szwVal
);
343 lstrcpynW(szValue
, rec
->fields
[iField
].u
.szwVal
, *pcchValue
);
346 len
= MultiByteToWideChar( CP_ACP
, 0, rec
->fields
[iField
].u
.szVal
, -1,
348 MultiByteToWideChar( CP_ACP
, 0, rec
->fields
[iField
].u
.szVal
, -1,
349 szValue
, *pcchValue
);
355 if( *pcchValue
< len
)
356 ret
= ERROR_MORE_DATA
;
362 UINT WINAPI
MsiRecordDataSize(MSIHANDLE hRecord
, unsigned int iField
)
364 FIXME("%ld %d\n", hRecord
, iField
);
368 UINT WINAPI
MsiRecordSetStringA( MSIHANDLE handle
, unsigned int iField
, LPCSTR szValue
)
373 TRACE("%ld %d %s\n", handle
, iField
, debugstr_a(szValue
));
375 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
377 return ERROR_INVALID_HANDLE
;
379 if( iField
> rec
->count
)
380 return ERROR_INVALID_FIELD
;
382 str
= HeapAlloc( GetProcessHeap(), 0, (lstrlenA(szValue
) + 1)*sizeof str
[0]);
383 lstrcpyA( str
, szValue
);
385 MSI_FreeField( &rec
->fields
[iField
] );
386 rec
->fields
[iField
].type
= MSIFIELD_STR
;
387 rec
->fields
[iField
].u
.szVal
= str
;
392 UINT WINAPI
MsiRecordSetStringW( MSIHANDLE handle
, unsigned int iField
, LPCWSTR szValue
)
397 TRACE("%ld %d %s\n", handle
, iField
, debugstr_w(szValue
));
399 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
401 return ERROR_INVALID_HANDLE
;
403 if( iField
> rec
->count
)
404 return ERROR_INVALID_FIELD
;
406 str
= HeapAlloc( GetProcessHeap(), 0, (lstrlenW(szValue
) + 1)*sizeof str
[0]);
407 lstrcpyW( str
, szValue
);
409 MSI_FreeField( &rec
->fields
[iField
] );
410 rec
->fields
[iField
].type
= MSIFIELD_WSTR
;
411 rec
->fields
[iField
].u
.szwVal
= str
;
416 UINT WINAPI
MsiFormatRecordA(MSIHANDLE hInstall
, MSIHANDLE hRecord
, LPSTR szResult
, DWORD
*sz
)
418 FIXME("%ld %ld %p %p\n", hInstall
, hRecord
, szResult
, sz
);
419 return ERROR_CALL_NOT_IMPLEMENTED
;
422 UINT WINAPI
MsiFormatRecordW(MSIHANDLE hInstall
, MSIHANDLE hRecord
, LPWSTR szResult
, DWORD
*sz
)
424 FIXME("%ld %ld %p %p\n", hInstall
, hRecord
, szResult
, sz
);
425 return ERROR_CALL_NOT_IMPLEMENTED
;
428 UINT WINAPI
MsiRecordSetStreamA(MSIHANDLE hRecord
, unsigned int iField
, LPCSTR szFilename
)
430 FIXME("%ld %d %s\n", hRecord
, iField
, debugstr_a(szFilename
));
431 return ERROR_CALL_NOT_IMPLEMENTED
;
434 UINT WINAPI
MsiRecordSetStreamW(MSIHANDLE hRecord
, unsigned int iField
, LPCWSTR szFilename
)
436 FIXME("%ld %d %s\n", hRecord
, iField
, debugstr_w(szFilename
));
437 return ERROR_CALL_NOT_IMPLEMENTED
;
440 UINT WINAPI
MsiRecordReadStream(MSIHANDLE handle
, unsigned int iField
, char *buf
, DWORD
*sz
)
442 FIXME("%ld %d %p %p\n",handle
,iField
,buf
,sz
);
443 return ERROR_CALL_NOT_IMPLEMENTED
;