Commit cf6e8201 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

msi: Allocate 3 bytes instead of 2 for in-memory string references.

Fixes an installer that stores string references as 2 byte integers and grows the number of strings beyond the limit of 64k during installation.
parent b7193384
......@@ -46,6 +46,7 @@
#define MSITYPE_TEMPORARY 0x4000
#define MAX_STREAM_NAME_LEN 62
#define LONG_STR_BYTES 3
/* Install UI level mask for AND operation to exclude flags */
#define INSTALLUILEVEL_MASK 0x0007
......@@ -684,7 +685,7 @@ extern VOID msi_destroy_stringtable( string_table *st );
extern const WCHAR *msi_string_lookup_id( const string_table *st, UINT id );
extern HRESULT msi_init_string_table( IStorage *stg );
extern string_table *msi_load_string_table( IStorage *stg, UINT *bytes_per_strref );
extern UINT msi_save_string_table( const string_table *st, IStorage *storage );
extern UINT msi_save_string_table( const string_table *st, IStorage *storage, UINT *bytes_per_strref );
extern BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name );
extern MSICONDITION MSI_DatabaseIsTablePersistent( MSIDATABASE *db, LPCWSTR table );
......
......@@ -3,6 +3,7 @@
*
* Copyright 2002-2004, Mike McCormack for CodeWeavers
* Copyright 2007 Robert Shearman for CodeWeavers
* Copyright 2010 Hans Leidekker for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -40,8 +41,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(msidb);
#define LONG_STR_BYTES 3
typedef struct _msistring
{
USHORT persistent_refcount;
......@@ -564,7 +563,7 @@ end:
return st;
}
UINT msi_save_string_table( const string_table *st, IStorage *storage )
UINT msi_save_string_table( const string_table *st, IStorage *storage, UINT *bytes_per_strref )
{
UINT i, datasize = 0, poolsize = 0, sz, used, r, codepage, n;
UINT ret = ERROR_FUNCTION_FAILED;
......@@ -593,8 +592,16 @@ UINT msi_save_string_table( const string_table *st, IStorage *storage )
used = 0;
codepage = st->codepage;
pool[0]=codepage&0xffff;
pool[1]=(codepage>>16);
pool[0] = codepage & 0xffff;
pool[1] = codepage >> 16;
if (st->maxcount > 0xffff)
{
pool[1] |= 0x8000;
*bytes_per_strref = LONG_STR_BYTES;
}
else
*bytes_per_strref = sizeof(USHORT);
n = 1;
for( i=1; i<st->maxcount; i++ )
{
......
......@@ -5498,16 +5498,13 @@ static void test_stringtable(void)
sz = sizeof(buffer);
r = MsiRecordGetString(hrec, 2, buffer, &sz);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
ok(!lstrcmp(buffer, "one"), "Expected one, got %s\n", buffer);
ok(!lstrcmp(buffer, "one"), "Expected one, got '%s'\n", buffer);
r = MsiCloseHandle(hrec);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
r = MsiViewFetch(hview, &hrec);
todo_wine
{
ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
}
ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
r = MsiViewClose(hview);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
......@@ -5535,7 +5532,7 @@ static void test_stringtable(void)
sz = sizeof(buffer);
r = MsiRecordGetString(hrec, 2, buffer, &sz);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
ok(!lstrcmp(buffer, "two"), "Expected two, got %s\n", buffer);
ok(!lstrcmp(buffer, "two"), "Expected two, got '%s'\n", buffer);
r = MsiCloseHandle(hrec);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
......@@ -5552,7 +5549,7 @@ static void test_stringtable(void)
sz = sizeof(buffer);
r = MsiRecordGetString(hrec, 2, buffer, &sz);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
ok(!lstrcmp(buffer, "five"), "Expected five, got %s\n", buffer);
ok(!lstrcmp(buffer, "five"), "Expected five, got '%s'\n", buffer);
r = MsiCloseHandle(hrec);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
......@@ -5580,11 +5577,8 @@ static void test_stringtable(void)
hr = IStream_Read(stm, data, MAX_PATH, &read);
ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
todo_wine
{
ok(read == 4, "Expected 4, got %d\n", read);
ok(!memcmp(data, data10, read), "Unexpected data\n");
}
ok(read == 4, "Expected 4, got %d\n", read);
todo_wine ok(!memcmp(data, data10, read), "Unexpected data\n");
hr = IStream_Release(stm);
ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment