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
,
103 MSI_CloseRecord
, (void**) &rec
);
107 rec
->count
= cParams
;
112 unsigned int WINAPI
MsiRecordGetFieldCount( MSIHANDLE handle
)
116 TRACE("%ld\n", handle
);
118 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
121 ERR("Record not found!\n");
128 static BOOL
string2intA( LPCSTR str
, int *out
)
133 if( *p
== '-' ) /* skip the minus sign */
137 if( (*p
< '0') || (*p
> '9') )
144 if( str
[0] == '-' ) /* check if it's negative */
151 static BOOL
string2intW( LPCWSTR str
, int *out
)
156 if( *p
== '-' ) /* skip the minus sign */
160 if( (*p
< '0') || (*p
> '9') )
167 if( str
[0] == '-' ) /* check if it's negative */
174 int WINAPI
MsiRecordGetInteger( MSIHANDLE handle
, unsigned int iField
)
179 TRACE("%ld %d\n", handle
, iField
);
181 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
183 return MSI_NULL_INTEGER
;
185 if( iField
> rec
->count
)
186 return MSI_NULL_INTEGER
;
188 switch( rec
->fields
[iField
].type
)
191 return rec
->fields
[iField
].u
.iVal
;
193 if( string2intA( rec
->fields
[iField
].u
.szVal
, &ret
) )
195 return MSI_NULL_INTEGER
;
197 if( string2intW( rec
->fields
[iField
].u
.szwVal
, &ret
) )
199 return MSI_NULL_INTEGER
;
204 return MSI_NULL_INTEGER
;
207 UINT WINAPI
MsiRecordClearData( MSIHANDLE handle
)
212 TRACE("%ld\n", handle
);
214 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
216 return ERROR_INVALID_HANDLE
;
218 for( i
=0; i
<=rec
->count
; i
++)
220 MSI_FreeField( &rec
->fields
[i
] );
221 rec
->fields
[i
].type
= MSIFIELD_NULL
;
222 rec
->fields
[i
].u
.iVal
= 0;
225 return ERROR_SUCCESS
;
228 UINT WINAPI
MsiRecordSetInteger( MSIHANDLE handle
, unsigned int iField
, int iVal
)
232 TRACE("%ld %u %d\n", handle
,iField
, iVal
);
234 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
236 return ERROR_INVALID_HANDLE
;
238 if( iField
<= rec
->count
)
240 MSI_FreeField( &rec
->fields
[iField
] );
241 rec
->fields
[iField
].type
= MSIFIELD_INT
;
242 rec
->fields
[iField
].u
.iVal
= iVal
;
245 return ERROR_SUCCESS
;
248 BOOL WINAPI
MsiRecordIsNull( MSIHANDLE handle
, unsigned int iField
)
253 TRACE("%ld %d\n", handle
,iField
);
255 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
257 return ERROR_INVALID_HANDLE
;
259 r
= ( iField
> rec
->count
) ||
260 ( rec
->fields
[iField
].type
== MSIFIELD_NULL
);
265 UINT WINAPI
MsiRecordGetStringA(MSIHANDLE handle
, unsigned int iField
,
266 LPSTR szValue
, DWORD
*pcchValue
)
272 TRACE("%ld %d %p %p\n", handle
, iField
, szValue
, pcchValue
);
274 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
276 return ERROR_INVALID_HANDLE
;
278 if( iField
> rec
->count
)
279 return ERROR_INVALID_PARAMETER
;
282 switch( rec
->fields
[iField
].type
)
285 wsprintfA(buffer
, "%d", rec
->fields
[iField
].u
.iVal
);
286 len
= lstrlenA( buffer
);
287 lstrcpynA(szValue
, buffer
, *pcchValue
);
290 len
= lstrlenA( rec
->fields
[iField
].u
.szVal
);
291 lstrcpynA(szValue
, rec
->fields
[iField
].u
.szVal
, *pcchValue
);
294 len
= WideCharToMultiByte( CP_ACP
, 0, rec
->fields
[iField
].u
.szwVal
, -1,
295 NULL
, 0 , NULL
, NULL
);
296 WideCharToMultiByte( CP_ACP
, 0, rec
->fields
[iField
].u
.szwVal
, -1,
297 szValue
, *pcchValue
, NULL
, NULL
);
300 ret
= ERROR_INVALID_PARAMETER
;
304 if( *pcchValue
< len
)
305 ret
= ERROR_MORE_DATA
;
311 UINT WINAPI
MsiRecordGetStringW(MSIHANDLE handle
, unsigned int iField
,
312 LPWSTR szValue
, DWORD
*pcchValue
)
317 const WCHAR szFormat
[] = { '%','d',0 };
319 TRACE("%ld %d %p %p\n", handle
, iField
, szValue
, pcchValue
);
321 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
323 return ERROR_INVALID_HANDLE
;
325 if( iField
> rec
->count
)
326 return ERROR_INVALID_PARAMETER
;
329 switch( rec
->fields
[iField
].type
)
332 wsprintfW(buffer
, szFormat
, rec
->fields
[iField
].u
.iVal
);
333 len
= lstrlenW( buffer
);
334 lstrcpynW(szValue
, buffer
, *pcchValue
);
337 len
= lstrlenW( rec
->fields
[iField
].u
.szwVal
);
338 lstrcpynW(szValue
, rec
->fields
[iField
].u
.szwVal
, *pcchValue
);
341 len
= MultiByteToWideChar( CP_ACP
, 0, rec
->fields
[iField
].u
.szVal
, -1,
343 MultiByteToWideChar( CP_ACP
, 0, rec
->fields
[iField
].u
.szVal
, -1,
344 szValue
, *pcchValue
);
350 if( *pcchValue
< len
)
351 ret
= ERROR_MORE_DATA
;
357 UINT WINAPI
MsiRecordDataSize(MSIHANDLE hRecord
, unsigned int iField
)
359 FIXME("%ld %d\n", hRecord
, iField
);
363 UINT WINAPI
MsiRecordSetStringA( MSIHANDLE handle
, unsigned int iField
, LPCSTR szValue
)
368 TRACE("%ld %d %s\n", handle
, iField
, debugstr_a(szValue
));
370 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
372 return ERROR_INVALID_HANDLE
;
374 if( iField
> rec
->count
)
375 return ERROR_INVALID_FIELD
;
377 str
= HeapAlloc( GetProcessHeap(), 0, (lstrlenA(szValue
) + 1)*sizeof str
[0]);
378 lstrcpyA( str
, szValue
);
380 MSI_FreeField( &rec
->fields
[iField
] );
381 rec
->fields
[iField
].type
= MSIFIELD_STR
;
382 rec
->fields
[iField
].u
.szVal
= str
;
387 UINT WINAPI
MsiRecordSetStringW( MSIHANDLE handle
, unsigned int iField
, LPCWSTR szValue
)
392 TRACE("%ld %d %s\n", handle
, iField
, debugstr_w(szValue
));
394 rec
= msihandle2msiinfo( handle
, MSIHANDLETYPE_RECORD
);
396 return ERROR_INVALID_HANDLE
;
398 if( iField
> rec
->count
)
399 return ERROR_INVALID_FIELD
;
401 str
= HeapAlloc( GetProcessHeap(), 0, (lstrlenW(szValue
) + 1)*sizeof str
[0]);
402 lstrcpyW( str
, szValue
);
404 MSI_FreeField( &rec
->fields
[iField
] );
405 rec
->fields
[iField
].type
= MSIFIELD_WSTR
;
406 rec
->fields
[iField
].u
.szwVal
= str
;
411 UINT WINAPI
MsiFormatRecordA(MSIHANDLE hInstall
, MSIHANDLE hRecord
, LPSTR szResult
, DWORD
*sz
)
413 FIXME("%ld %ld %p %p\n", hInstall
, hRecord
, szResult
, sz
);
414 return ERROR_CALL_NOT_IMPLEMENTED
;
417 UINT WINAPI
MsiFormatRecordW(MSIHANDLE hInstall
, MSIHANDLE hRecord
, LPWSTR szResult
, DWORD
*sz
)
419 FIXME("%ld %ld %p %p\n", hInstall
, hRecord
, szResult
, sz
);
420 return ERROR_CALL_NOT_IMPLEMENTED
;
423 UINT WINAPI
MsiRecordSetStreamA(MSIHANDLE hRecord
, unsigned int iField
, LPCSTR szFilename
)
425 FIXME("%ld %d %s\n", hRecord
, iField
, debugstr_a(szFilename
));
426 return ERROR_CALL_NOT_IMPLEMENTED
;
429 UINT WINAPI
MsiRecordSetStreamW(MSIHANDLE hRecord
, unsigned int iField
, LPCWSTR szFilename
)
431 FIXME("%ld %d %s\n", hRecord
, iField
, debugstr_w(szFilename
));
432 return ERROR_CALL_NOT_IMPLEMENTED
;
435 UINT WINAPI
MsiRecordReadStream(MSIHANDLE handle
, unsigned int iField
, char *buf
, DWORD
*sz
)
437 FIXME("%ld %d %p %p\n",handle
,iField
,buf
,sz
);
438 return ERROR_CALL_NOT_IMPLEMENTED
;