mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-05 18:01:34 +00:00
Implement MsiRecordSetStreamA/W and add tests for records containing
streams.
This commit is contained in:
parent
dd8fccfe72
commit
921be0a87c
2 changed files with 219 additions and 15 deletions
|
@ -32,6 +32,7 @@
|
|||
#include "msipriv.h"
|
||||
#include "objidl.h"
|
||||
#include "winnls.h"
|
||||
#include "ole2.h"
|
||||
|
||||
#include "query.h"
|
||||
|
||||
|
@ -531,16 +532,133 @@ UINT WINAPI MsiFormatRecordW(MSIHANDLE hInstall, MSIHANDLE hRecord, LPWSTR szRes
|
|||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiRecordSetStreamA(MSIHANDLE hRecord, unsigned int iField, LPCSTR szFilename)
|
||||
/* read the data in a file into an IStream */
|
||||
UINT RECORD_StreamFromFile(LPCWSTR szFile, IStream **pstm)
|
||||
{
|
||||
FIXME("%ld %d %s\n", hRecord, iField, debugstr_a(szFilename));
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
DWORD sz, szHighWord = 0, read;
|
||||
HANDLE handle;
|
||||
HGLOBAL hGlob = 0;
|
||||
HRESULT hr;
|
||||
ULARGE_INTEGER ulSize;
|
||||
|
||||
TRACE("reading %s\n", debugstr_w(szFile));
|
||||
|
||||
/* read the file into memory */
|
||||
handle = CreateFileW(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if( handle == INVALID_HANDLE_VALUE )
|
||||
return GetLastError();
|
||||
sz = GetFileSize(handle, &szHighWord);
|
||||
if( sz != INVALID_FILE_SIZE && szHighWord == 0 )
|
||||
{
|
||||
hGlob = GlobalAlloc(GMEM_FIXED, sz);
|
||||
if( hGlob )
|
||||
{
|
||||
BOOL r = ReadFile(handle, hGlob, sz, &read, NULL);
|
||||
if( !r )
|
||||
{
|
||||
GlobalFree(hGlob);
|
||||
hGlob = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(handle);
|
||||
if( !hGlob )
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
/* make a stream out of it, and set the correct file size */
|
||||
hr = CreateStreamOnHGlobal(hGlob, TRUE, pstm);
|
||||
if( FAILED( hr ) )
|
||||
{
|
||||
GlobalFree(hGlob);
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
/* set the correct size - CreateStreamOnHGlobal screws it up */
|
||||
ulSize.QuadPart = sz;
|
||||
IStream_SetSize(*pstm, ulSize);
|
||||
|
||||
TRACE("read %s, %ld bytes into IStream %p\n", debugstr_w(szFile), sz, *pstm);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiRecordSetStreamW(MSIHANDLE hRecord, unsigned int iField, LPCWSTR szFilename)
|
||||
UINT MSI_RecordSetStreamW(MSIRECORD *rec, unsigned int iField, LPCWSTR szFilename)
|
||||
{
|
||||
FIXME("%ld %d %s\n", hRecord, iField, debugstr_w(szFilename));
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
IStream *stm = NULL;
|
||||
HRESULT r;
|
||||
|
||||
if( (iField == 0) || (iField > rec->count) )
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
/* no filename means we should seek back to the start of the stream */
|
||||
if( !szFilename )
|
||||
{
|
||||
LARGE_INTEGER ofs;
|
||||
ULARGE_INTEGER cur;
|
||||
|
||||
if( rec->fields[iField].type != MSIFIELD_STREAM )
|
||||
return ERROR_INVALID_FIELD;
|
||||
|
||||
stm = rec->fields[iField].u.stream;
|
||||
if( !stm )
|
||||
return ERROR_INVALID_FIELD;
|
||||
|
||||
ofs.QuadPart = 0;
|
||||
r = IStream_Seek( stm, ofs, STREAM_SEEK_SET, &cur );
|
||||
if( FAILED( r ) )
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* read the file into a stream and save the stream in the record */
|
||||
r = RECORD_StreamFromFile(szFilename, &stm);
|
||||
if( r != ERROR_SUCCESS )
|
||||
return r;
|
||||
|
||||
/* if all's good, store it in the record */
|
||||
MSI_FreeField( &rec->fields[iField] );
|
||||
rec->fields[iField].type = MSIFIELD_STREAM;
|
||||
rec->fields[iField].u.stream = stm;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiRecordSetStreamA(MSIHANDLE hRecord, unsigned int iField, LPCSTR szFilename)
|
||||
{
|
||||
LPWSTR wstr = NULL;
|
||||
UINT ret, len;
|
||||
|
||||
TRACE("%ld %d %s\n", hRecord, iField, debugstr_a(szFilename));
|
||||
|
||||
if( szFilename )
|
||||
{
|
||||
len = MultiByteToWideChar(CP_ACP,0,szFilename,-1,NULL,0);
|
||||
wstr = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
|
||||
MultiByteToWideChar(CP_ACP,0,szFilename,-1,wstr,len);
|
||||
}
|
||||
ret = MsiRecordSetStreamW(hRecord, iField, wstr);
|
||||
HeapFree(GetProcessHeap(),0,wstr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
UINT WINAPI MsiRecordSetStreamW(MSIHANDLE handle, unsigned int iField, LPCWSTR szFilename)
|
||||
{
|
||||
MSIRECORD *rec;
|
||||
UINT ret;
|
||||
|
||||
TRACE("%ld %d %s\n", handle, iField, debugstr_w(szFilename));
|
||||
|
||||
rec = msihandle2msiinfo( handle, MSIHANDLETYPE_RECORD );
|
||||
if( !rec )
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
msiobj_lock( &rec->hdr );
|
||||
ret = MSI_RecordSetStreamW( rec, iField, szFilename );
|
||||
msiobj_unlock( &rec->hdr );
|
||||
msiobj_release( &rec->hdr );
|
||||
return ret;
|
||||
}
|
||||
|
||||
UINT MSI_RecordReadStream(MSIRECORD *rec, unsigned int iField, char *buf, DWORD *sz)
|
||||
|
@ -551,18 +669,18 @@ UINT MSI_RecordReadStream(MSIRECORD *rec, unsigned int iField, char *buf, DWORD
|
|||
|
||||
TRACE("%p %d %p %p\n", rec, iField, buf, sz);
|
||||
|
||||
if( iField > rec->count )
|
||||
return ERROR_INVALID_FIELD;
|
||||
if( !sz )
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if( iField > rec->count)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if( rec->fields[iField].type != MSIFIELD_STREAM )
|
||||
{
|
||||
*sz = 0;
|
||||
return ERROR_INVALID_FIELD;
|
||||
}
|
||||
return ERROR_INVALID_DATATYPE;
|
||||
|
||||
stm = rec->fields[iField].u.stream;
|
||||
if( !stm )
|
||||
return ERROR_INVALID_FIELD;
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
/* if there's no buffer pointer, calculate the length to the end */
|
||||
if( !buf )
|
||||
|
|
|
@ -24,6 +24,27 @@
|
|||
|
||||
#include "wine/test.h"
|
||||
|
||||
static BOOL create_temp_file(char *name)
|
||||
{
|
||||
UINT r;
|
||||
unsigned char buffer[26], i;
|
||||
DWORD sz;
|
||||
HANDLE handle;
|
||||
|
||||
r = GetTempFileName(".", "msitest",0,name);
|
||||
if(!r)
|
||||
return r;
|
||||
handle = CreateFile(name, GENERIC_READ|GENERIC_WRITE,
|
||||
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(handle==INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
for(i=0; i<26; i++)
|
||||
buffer[i]=i+'a';
|
||||
r = WriteFile(handle,buffer,sizeof buffer,&sz,NULL);
|
||||
CloseHandle(handle);
|
||||
return r;
|
||||
}
|
||||
|
||||
void test_msirecord(void)
|
||||
{
|
||||
DWORD r, sz;
|
||||
|
@ -31,6 +52,7 @@ void test_msirecord(void)
|
|||
MSIHANDLE h;
|
||||
char buf[10];
|
||||
const char str[] = "hello";
|
||||
char filename[MAX_PATH];
|
||||
|
||||
/* check behaviour with an invalid record */
|
||||
r = MsiRecordGetFieldCount(0);
|
||||
|
@ -88,10 +110,8 @@ void test_msirecord(void)
|
|||
r = MsiRecordSetInteger(h, 0, 1);
|
||||
ok(r == ERROR_SUCCESS, "Failed to set integer at 0 to 1\n");
|
||||
r = MsiRecordSetInteger(h, 1, 1);
|
||||
/*printf("r = %d\n",r); */
|
||||
ok(r == ERROR_INVALID_PARAMETER, "set integer at 1\n");
|
||||
r = MsiRecordSetInteger(h, -1, 0);
|
||||
/*printf("r = %d\n",r); */
|
||||
ok(r == ERROR_INVALID_PARAMETER, "set integer at -1\n");
|
||||
r = MsiRecordIsNull(h,0);
|
||||
ok(r==0, "new record is null after setting an integer\n");
|
||||
|
@ -185,9 +205,75 @@ void test_msirecord(void)
|
|||
ok(r == ERROR_SUCCESS, "failed to get string from integer\n");
|
||||
ok(0==strcmp(buf,"-32"), "failed to get string from integer\n");
|
||||
|
||||
/* same record, now try streams */
|
||||
r = MsiRecordSetStream(h, 0, NULL);
|
||||
ok(r == ERROR_INVALID_PARAMETER, "set NULL stream\n");
|
||||
sz = sizeof buf;
|
||||
r = MsiRecordReadStream(h, 0, buf, &sz);
|
||||
ok(r == ERROR_INVALID_DATATYPE, "read non-stream type\n");
|
||||
ok(sz == sizeof buf, "set sz\n");
|
||||
|
||||
/* same record, now close it */
|
||||
r = MsiCloseHandle(h);
|
||||
ok(r == ERROR_SUCCESS, "Failed to close handle\n");
|
||||
|
||||
/* now try streams in a new record - need to create a file to play with */
|
||||
r = create_temp_file(filename);
|
||||
if(!r)
|
||||
return;
|
||||
|
||||
/* streams can't be inserted in field 0 for some reason */
|
||||
h = MsiCreateRecord(2);
|
||||
ok(h, "couldn't create a two field record\n");
|
||||
r = MsiRecordSetStream(h, 0, filename);
|
||||
ok(r == ERROR_INVALID_PARAMETER, "added stream to field 0\n");
|
||||
r = MsiRecordSetStream(h, 1, filename);
|
||||
ok(r == ERROR_SUCCESS, "failed to add stream to record\n");
|
||||
r = MsiRecordReadStream(h, 1, buf, NULL);
|
||||
ok(r == ERROR_INVALID_PARAMETER, "should return error\n");
|
||||
ok(DeleteFile(filename), "failed to delete stream temp file\n");
|
||||
r = MsiRecordReadStream(h, 1, NULL, NULL);
|
||||
ok(r == ERROR_INVALID_PARAMETER, "should return error\n");
|
||||
sz = sizeof buf;
|
||||
r = MsiRecordReadStream(h, 1, NULL, &sz);
|
||||
ok(r == ERROR_SUCCESS, "failed to read stream\n");
|
||||
ok(sz==26,"couldn't get size of stream");
|
||||
sz = 0;
|
||||
r = MsiRecordReadStream(h, 1, buf, &sz);
|
||||
ok(r == ERROR_SUCCESS, "failed to read stream\n");
|
||||
ok(sz==0,"short read");
|
||||
sz = sizeof buf;
|
||||
r = MsiRecordReadStream(h, 1, buf, &sz);
|
||||
ok(r == ERROR_SUCCESS, "failed to read stream\n");
|
||||
ok(sz==sizeof buf,"short read");
|
||||
ok(!strncmp(buf,"abcdefghij",10), "read the wrong thing\n");
|
||||
sz = sizeof buf;
|
||||
r = MsiRecordReadStream(h, 1, buf, &sz);
|
||||
ok(r == ERROR_SUCCESS, "failed to read stream\n");
|
||||
ok(sz==sizeof buf,"short read");
|
||||
ok(!strncmp(buf,"klmnopqrst",10), "read the wrong thing\n");
|
||||
memset(buf,0,sizeof buf);
|
||||
sz = sizeof buf;
|
||||
r = MsiRecordReadStream(h, 1, buf, &sz);
|
||||
ok(r == ERROR_SUCCESS, "failed to read stream\n");
|
||||
ok(sz==6,"short read");
|
||||
ok(!strcmp(buf,"uvwxyz"), "read the wrong thing\n");
|
||||
memset(buf,0,sizeof buf);
|
||||
sz = sizeof buf;
|
||||
r = MsiRecordReadStream(h, 1, buf, &sz);
|
||||
ok(r == ERROR_SUCCESS, "failed to read stream\n");
|
||||
ok(sz==0,"size non-zero at end of stream\n");
|
||||
ok(buf[0]==0, "read something at end of the stream\n");
|
||||
r = MsiRecordSetStream(h, 1, NULL);
|
||||
ok(r == ERROR_SUCCESS, "failed to reset stream\n");
|
||||
sz = 0;
|
||||
r = MsiRecordReadStream(h, 1, NULL, &sz);
|
||||
ok(r == ERROR_SUCCESS, "bytes left wrong after reset\n");
|
||||
ok(sz==26,"couldn't get size of stream\n");
|
||||
|
||||
/* now close the stream record */
|
||||
r = MsiCloseHandle(h);
|
||||
ok(r == ERROR_SUCCESS, "Failed to close handle\n");
|
||||
}
|
||||
|
||||
START_TEST(record)
|
||||
|
|
Loading…
Reference in a new issue