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

msi: Handle embedded nulls in text archives.

parent b55cbe8d
...@@ -509,7 +509,7 @@ end: ...@@ -509,7 +509,7 @@ end:
return r; return r;
} }
static LPWSTR msi_read_text_archive(LPCWSTR path) static LPWSTR msi_read_text_archive(LPCWSTR path, DWORD *len)
{ {
HANDLE file; HANDLE file;
LPSTR data = NULL; LPSTR data = NULL;
...@@ -521,15 +521,17 @@ static LPWSTR msi_read_text_archive(LPCWSTR path) ...@@ -521,15 +521,17 @@ static LPWSTR msi_read_text_archive(LPCWSTR path)
return NULL; return NULL;
size = GetFileSize( file, NULL ); size = GetFileSize( file, NULL );
data = msi_alloc( size + 1 ); if (!(data = msi_alloc( size ))) goto done;
if (!data)
goto done;
if (!ReadFile( file, data, size, &read, NULL )) if (!ReadFile( file, data, size, &read, NULL ) || read != size) goto done;
goto done;
data[size] = '\0'; while (!data[size - 1]) size--;
wdata = strdupAtoW( data ); *len = MultiByteToWideChar( CP_ACP, 0, data, size, NULL, 0 );
if ((wdata = msi_alloc( (*len + 1) * sizeof(WCHAR) )))
{
MultiByteToWideChar( CP_ACP, 0, data, size, wdata, *len );
wdata[*len] = 0;
}
done: done:
CloseHandle( file ); CloseHandle( file );
...@@ -537,21 +539,22 @@ done: ...@@ -537,21 +539,22 @@ done:
return wdata; return wdata;
} }
static void msi_parse_line(LPWSTR *line, LPWSTR **entries, DWORD *num_entries) static void msi_parse_line(LPWSTR *line, LPWSTR **entries, DWORD *num_entries, DWORD *len)
{ {
LPWSTR ptr = *line, save; LPWSTR ptr = *line, save;
DWORD i, count = 1; DWORD i, count = 1, chars_left = *len;
*entries = NULL; *entries = NULL;
/* stay on this line */ /* stay on this line */
while (*ptr && *ptr != '\n') while (chars_left && *ptr != '\n')
{ {
/* entries are separated by tabs */ /* entries are separated by tabs */
if (*ptr == '\t') if (*ptr == '\t')
count++; count++;
ptr++; ptr++;
chars_left--;
} }
*entries = msi_alloc(count * sizeof(LPWSTR)); *entries = msi_alloc(count * sizeof(LPWSTR));
...@@ -559,28 +562,43 @@ static void msi_parse_line(LPWSTR *line, LPWSTR **entries, DWORD *num_entries) ...@@ -559,28 +562,43 @@ static void msi_parse_line(LPWSTR *line, LPWSTR **entries, DWORD *num_entries)
return; return;
/* store pointers into the data */ /* store pointers into the data */
chars_left = *len;
for (i = 0, ptr = *line; i < count; i++) for (i = 0, ptr = *line; i < count; i++)
{ {
while (*ptr && *ptr == '\r') ptr++; while (chars_left && *ptr == '\r')
{
ptr++;
chars_left--;
}
save = ptr; save = ptr;
while (*ptr && *ptr != '\t' && *ptr != '\n' && *ptr != '\r') ptr++; while (chars_left && *ptr != '\t' && *ptr != '\n' && *ptr != '\r')
{
if (!*ptr) *ptr = '\n'; /* convert embedded nulls to \n */
ptr++;
chars_left--;
}
/* NULL-separate the data */ /* NULL-separate the data */
if (*ptr == '\n' || *ptr == '\r') if (*ptr == '\n' || *ptr == '\r')
{ {
while (*ptr == '\n' || *ptr == '\r') while (chars_left && (*ptr == '\n' || *ptr == '\r'))
*(ptr++) = '\0'; {
*(ptr++) = 0;
chars_left--;
}
} }
else if (*ptr) else if (*ptr)
*ptr++ = '\0'; {
*(ptr++) = 0;
chars_left--;
}
(*entries)[i] = save; (*entries)[i] = save;
} }
/* move to the next line if there's more, else EOF */ /* move to the next line if there's more, else EOF */
*line = ptr; *line = ptr;
*len = chars_left;
if (num_entries) if (num_entries)
*num_entries = count; *num_entries = count;
} }
...@@ -916,12 +934,12 @@ static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file) ...@@ -916,12 +934,12 @@ static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
lstrcatW( path, szBackSlash ); lstrcatW( path, szBackSlash );
lstrcatW( path, file ); lstrcatW( path, file );
data = msi_read_text_archive( path ); data = msi_read_text_archive( path, &len );
ptr = data; ptr = data;
msi_parse_line( &ptr, &columns, &num_columns ); msi_parse_line( &ptr, &columns, &num_columns, &len );
msi_parse_line( &ptr, &types, &num_types ); msi_parse_line( &ptr, &types, &num_types, &len );
msi_parse_line( &ptr, &labels, &num_labels ); msi_parse_line( &ptr, &labels, &num_labels, &len );
if (num_columns == 1 && !columns[0][0] && num_labels == 1 && !labels[0][0] && if (num_columns == 1 && !columns[0][0] && num_labels == 1 && !labels[0][0] &&
num_types == 2 && !strcmpW( types[1], forcecodepage )) num_types == 2 && !strcmpW( types[1], forcecodepage ))
...@@ -944,9 +962,9 @@ static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file) ...@@ -944,9 +962,9 @@ static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
} }
/* read in the table records */ /* read in the table records */
while (*ptr) while (len)
{ {
msi_parse_line( &ptr, &records[num_records], NULL ); msi_parse_line( &ptr, &records[num_records], NULL, &len );
num_records++; num_records++;
temp_records = msi_realloc(records, (num_records + 1) * sizeof(LPWSTR *)); temp_records = msi_realloc(records, (num_records + 1) * sizeof(LPWSTR *));
......
...@@ -9253,6 +9253,39 @@ static void test_createtable(void) ...@@ -9253,6 +9253,39 @@ static void test_createtable(void)
DeleteFileA(msifile); DeleteFileA(msifile);
} }
static void test_embedded_nulls(void)
{
static const char control_table[] =
"Dialog\tText\n"
"s72\tL0\n"
"Control\tDialog\n"
"LicenseAgreementDlg\ttext\0text";
UINT r, sz;
MSIHANDLE hdb, hrec;
char buffer[32];
r = MsiOpenDatabaseA( msifile, MSIDBOPEN_CREATE, &hdb );
ok( r == ERROR_SUCCESS, "failed to open database %u\n", r );
GetCurrentDirectoryA( MAX_PATH, CURR_DIR );
write_file( "temp_file", control_table, sizeof(control_table) );
r = MsiDatabaseImportA( hdb, CURR_DIR, "temp_file" );
ok( r == ERROR_SUCCESS, "failed to import table %u\n", r );
DeleteFileA( "temp_file" );
r = do_query( hdb, "SELECT `Text` FROM `Control` WHERE `Dialog` = 'LicenseAgreementDlg'", &hrec );
ok( r == ERROR_SUCCESS, "query failed %u\n", r );
buffer[0] = 0;
sz = sizeof(buffer);
r = MsiRecordGetStringA( hrec, 1, buffer, &sz );
ok( r == ERROR_SUCCESS, "failed to get string %u\n", r );
ok( !memcmp( "text\ntext", buffer, sizeof("text\ntext") - 1 ), "wrong buffer contents \"%s\"\n", buffer );
MsiCloseHandle( hrec );
MsiCloseHandle( hdb );
DeleteFileA( msifile );
}
START_TEST(db) START_TEST(db)
{ {
...@@ -9307,4 +9340,5 @@ START_TEST(db) ...@@ -9307,4 +9340,5 @@ START_TEST(db)
test_suminfo_import(); test_suminfo_import();
test_createtable(); test_createtable();
test_collation(); test_collation();
test_embedded_nulls();
} }
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