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 @@ ...@@ -46,6 +46,7 @@
#define MSITYPE_TEMPORARY 0x4000 #define MSITYPE_TEMPORARY 0x4000
#define MAX_STREAM_NAME_LEN 62 #define MAX_STREAM_NAME_LEN 62
#define LONG_STR_BYTES 3
/* Install UI level mask for AND operation to exclude flags */ /* Install UI level mask for AND operation to exclude flags */
#define INSTALLUILEVEL_MASK 0x0007 #define INSTALLUILEVEL_MASK 0x0007
...@@ -684,7 +685,7 @@ extern VOID msi_destroy_stringtable( string_table *st ); ...@@ -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 const WCHAR *msi_string_lookup_id( const string_table *st, UINT id );
extern HRESULT msi_init_string_table( IStorage *stg ); extern HRESULT msi_init_string_table( IStorage *stg );
extern string_table *msi_load_string_table( IStorage *stg, UINT *bytes_per_strref ); 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 BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name );
extern MSICONDITION MSI_DatabaseIsTablePersistent( MSIDATABASE *db, LPCWSTR table ); extern MSICONDITION MSI_DatabaseIsTablePersistent( MSIDATABASE *db, LPCWSTR table );
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* *
* Copyright 2002-2004, Mike McCormack for CodeWeavers * Copyright 2002-2004, Mike McCormack for CodeWeavers
* Copyright 2007 Robert Shearman 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -40,8 +41,6 @@ ...@@ -40,8 +41,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(msidb); WINE_DEFAULT_DEBUG_CHANNEL(msidb);
#define LONG_STR_BYTES 3
typedef struct _msistring typedef struct _msistring
{ {
USHORT persistent_refcount; USHORT persistent_refcount;
...@@ -564,7 +563,7 @@ end: ...@@ -564,7 +563,7 @@ end:
return st; 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 i, datasize = 0, poolsize = 0, sz, used, r, codepage, n;
UINT ret = ERROR_FUNCTION_FAILED; UINT ret = ERROR_FUNCTION_FAILED;
...@@ -593,8 +592,16 @@ UINT msi_save_string_table( const string_table *st, IStorage *storage ) ...@@ -593,8 +592,16 @@ UINT msi_save_string_table( const string_table *st, IStorage *storage )
used = 0; used = 0;
codepage = st->codepage; codepage = st->codepage;
pool[0]=codepage&0xffff; pool[0] = codepage & 0xffff;
pool[1]=(codepage>>16); 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; n = 1;
for( i=1; i<st->maxcount; i++ ) for( i=1; i<st->maxcount; i++ )
{ {
......
...@@ -5498,16 +5498,13 @@ static void test_stringtable(void) ...@@ -5498,16 +5498,13 @@ static void test_stringtable(void)
sz = sizeof(buffer); sz = sizeof(buffer);
r = MsiRecordGetString(hrec, 2, buffer, &sz); r = MsiRecordGetString(hrec, 2, buffer, &sz);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 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); r = MsiCloseHandle(hrec);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
r = MsiViewFetch(hview, &hrec); 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); r = MsiViewClose(hview);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
...@@ -5535,7 +5532,7 @@ static void test_stringtable(void) ...@@ -5535,7 +5532,7 @@ static void test_stringtable(void)
sz = sizeof(buffer); sz = sizeof(buffer);
r = MsiRecordGetString(hrec, 2, buffer, &sz); r = MsiRecordGetString(hrec, 2, buffer, &sz);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 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); r = MsiCloseHandle(hrec);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
...@@ -5552,7 +5549,7 @@ static void test_stringtable(void) ...@@ -5552,7 +5549,7 @@ static void test_stringtable(void)
sz = sizeof(buffer); sz = sizeof(buffer);
r = MsiRecordGetString(hrec, 2, buffer, &sz); r = MsiRecordGetString(hrec, 2, buffer, &sz);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 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); r = MsiCloseHandle(hrec);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
...@@ -5580,11 +5577,8 @@ static void test_stringtable(void) ...@@ -5580,11 +5577,8 @@ static void test_stringtable(void)
hr = IStream_Read(stm, data, MAX_PATH, &read); hr = IStream_Read(stm, data, MAX_PATH, &read);
ok(hr == S_OK, "Expected S_OK, got %d\n", hr); ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
todo_wine ok(read == 4, "Expected 4, got %d\n", read);
{ todo_wine ok(!memcmp(data, data10, read), "Unexpected data\n");
ok(read == 4, "Expected 4, got %d\n", read);
ok(!memcmp(data, data10, read), "Unexpected data\n");
}
hr = IStream_Release(stm); hr = IStream_Release(stm);
ok(hr == S_OK, "Expected S_OK, got %d\n", hr); 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