janitorial: Remove remaining NULL checks before free() (found by Smatch).
[wine] / dlls / msi / tests / format.c
1 /*
2  * Copyright (C) 2005 Mike McCormack for CodeWeavers
3  * Copyright (C) 2005 Aric Stewart for CodeWeavers
4  *
5  * A test program for MSI record formatting
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdio.h>
23 #include <windows.h>
24 #include <msi.h>
25 #include <msiquery.h>
26
27 #include "wine/test.h"
28
29 static const char msifile[] = "winetest.msi";
30
31 static UINT run_query( MSIHANDLE hdb, const char *query )
32 {
33     MSIHANDLE hview = 0;
34     UINT r;
35
36     r = MsiDatabaseOpenView(hdb, query, &hview);
37     if( r != ERROR_SUCCESS )
38         return r;
39
40     r = MsiViewExecute(hview, 0);
41     if( r == ERROR_SUCCESS )
42         r = MsiViewClose(hview);
43     MsiCloseHandle(hview);
44     return r;
45 }
46
47 static UINT create_feature_table( MSIHANDLE hdb )
48 {
49     return run_query( hdb,
50             "CREATE TABLE `Feature` ( "
51             "`Feature` CHAR(38) NOT NULL, "
52             "`Feature_Parent` CHAR(38), "
53             "`Title` CHAR(64), "
54             "`Description` CHAR(255), "
55             "`Display` SHORT NOT NULL, "
56             "`Level` SHORT NOT NULL, "
57             "`Directory_` CHAR(72), "
58             "`Attributes` SHORT NOT NULL "
59             "PRIMARY KEY `Feature`)" );
60 }
61
62 static UINT create_component_table( MSIHANDLE hdb )
63 {
64     return run_query( hdb,
65             "CREATE TABLE `Component` ( "
66             "`Component` CHAR(72) NOT NULL, "
67             "`ComponentId` CHAR(38), "
68             "`Directory_` CHAR(72) NOT NULL, "
69             "`Attributes` SHORT NOT NULL, "
70             "`Condition` CHAR(255), "
71             "`KeyPath` CHAR(72) "
72             "PRIMARY KEY `Component`)" );
73 }
74
75 static UINT create_feature_components_table( MSIHANDLE hdb )
76 {
77     return run_query( hdb,
78             "CREATE TABLE `FeatureComponents` ( "
79             "`Feature_` CHAR(38) NOT NULL, "
80             "`Component_` CHAR(72) NOT NULL "
81             "PRIMARY KEY `Feature_`, `Component_` )" );
82 }
83
84 static UINT create_file_table( MSIHANDLE hdb )
85 {
86     return run_query( hdb,
87             "CREATE TABLE `File` ("
88             "`File` CHAR(72) NOT NULL, "
89             "`Component_` CHAR(72) NOT NULL, "
90             "`FileName` CHAR(255) NOT NULL, "
91             "`FileSize` LONG NOT NULL, "
92             "`Version` CHAR(72), "
93             "`Language` CHAR(20), "
94             "`Attributes` SHORT, "
95             "`Sequence` SHORT NOT NULL "
96             "PRIMARY KEY `File`)" );
97 }
98
99 static UINT create_custom_action_table( MSIHANDLE hdb )
100 {
101     return run_query( hdb,
102             "CREATE TABLE `CustomAction` ("
103             "`Action` CHAR(72) NOT NULL, "
104             "`Type` SHORT NOT NULL, "
105             "`Source` CHAR(75), "
106             "`Target` CHAR(255) "
107             "PRIMARY KEY `Action`)" );
108 }
109
110 static UINT add_feature_entry( MSIHANDLE hdb, const char *values )
111 {
112     char insert[] = "INSERT INTO `Feature` (`Feature`, `Feature_Parent`, "
113                     "`Title`, `Description`, `Display`, `Level`, `Directory_`, `Attributes`) VALUES( %s )";
114     char *query;
115     UINT sz, r;
116
117     sz = strlen(values) + sizeof insert;
118     query = HeapAlloc(GetProcessHeap(),0,sz);
119     sprintf(query,insert,values);
120     r = run_query( hdb, query );
121     HeapFree(GetProcessHeap(), 0, query);
122     return r;
123 }
124
125 static UINT add_component_entry( MSIHANDLE hdb, const char *values )
126 {
127     char insert[] = "INSERT INTO `Component`  "
128             "(`Component`, `ComponentId`, `Directory_`, `Attributes`, `Condition`, `KeyPath`) "
129             "VALUES( %s )";
130     char *query;
131     UINT sz, r;
132
133     sz = strlen(values) + sizeof insert;
134     query = HeapAlloc(GetProcessHeap(),0,sz);
135     sprintf(query,insert,values);
136     r = run_query( hdb, query );
137     HeapFree(GetProcessHeap(), 0, query);
138     return r;
139 }
140
141 static UINT add_feature_components_entry( MSIHANDLE hdb, const char *values )
142 {
143     char insert[] = "INSERT INTO `FeatureComponents` "
144             "(`Feature_`, `Component_`) "
145             "VALUES( %s )";
146     char *query;
147     UINT sz, r;
148
149     sz = strlen(values) + sizeof insert;
150     query = HeapAlloc(GetProcessHeap(),0,sz);
151     sprintf(query,insert,values);
152     r = run_query( hdb, query );
153     HeapFree(GetProcessHeap(), 0, query);
154     return r;
155 }
156
157 static UINT add_file_entry( MSIHANDLE hdb, const char *values )
158 {
159     char insert[] = "INSERT INTO `File` "
160             "(`File`, `Component_`, `FileName`, `FileSize`, `Version`, `Language`, `Attributes`, `Sequence`) "
161             "VALUES( %s )";
162     char *query;
163     UINT sz, r;
164
165     sz = strlen(values) + sizeof insert;
166     query = HeapAlloc(GetProcessHeap(),0,sz);
167     sprintf(query,insert,values);
168     r = run_query( hdb, query );
169     HeapFree(GetProcessHeap(), 0, query);
170     return r;
171 }
172
173 static UINT add_directory_entry( MSIHANDLE hdb, const char *values )
174 {
175     char insert[] = "INSERT INTO `Directory` (`Directory`,`Directory_Parent`,`DefaultDir`) VALUES( %s )";
176     char *query;
177     UINT sz, r;
178
179     sz = strlen(values) + sizeof insert;
180     query = HeapAlloc(GetProcessHeap(),0,sz);
181     sprintf(query,insert,values);
182     r = run_query( hdb, query );
183     HeapFree(GetProcessHeap(), 0, query);
184     return r;
185 }
186
187 static UINT add_custom_action_entry( MSIHANDLE hdb, const char *values )
188 {
189     char insert[] = "INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, "
190                     "`Target`) VALUES( %s )";
191     char *query;
192     UINT sz, r;
193
194     sz = strlen(values) + sizeof insert;
195     query = HeapAlloc(GetProcessHeap(),0,sz);
196     sprintf(query,insert,values);
197     r = run_query( hdb, query );
198     HeapFree(GetProcessHeap(), 0, query);
199     return r;
200 }
201
202 static UINT set_summary_info(MSIHANDLE hdb)
203 {
204     UINT res;
205     MSIHANDLE suminfo;
206
207     /* build summmary info */
208     res = MsiGetSummaryInformation(hdb, NULL, 7, &suminfo);
209     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
210
211     res = MsiSummaryInfoSetProperty(suminfo,2, VT_LPSTR, 0,NULL,
212                         "Installation Database");
213     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
214
215     res = MsiSummaryInfoSetProperty(suminfo,3, VT_LPSTR, 0,NULL,
216                         "Installation Database");
217     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
218
219     res = MsiSummaryInfoSetProperty(suminfo,4, VT_LPSTR, 0,NULL,
220                         "Wine Hackers");
221     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
222
223     res = MsiSummaryInfoSetProperty(suminfo,7, VT_LPSTR, 0,NULL,
224                     ";1033");
225     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
226
227     res = MsiSummaryInfoSetProperty(suminfo,9, VT_LPSTR, 0,NULL,
228                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
229     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
230
231     res = MsiSummaryInfoSetProperty(suminfo, 14, VT_I4, 100, NULL, NULL);
232     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
233
234     res = MsiSummaryInfoSetProperty(suminfo, 15, VT_I4, 0, NULL, NULL);
235     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
236
237     res = MsiSummaryInfoPersist(suminfo);
238     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
239
240     res = MsiCloseHandle( suminfo);
241     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
242
243     return res;
244 }
245
246 static MSIHANDLE create_package_db(void)
247 {
248     MSIHANDLE hdb = 0;
249     UINT res;
250
251     DeleteFile(msifile);
252
253     /* create an empty database */
254     res = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
255     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
256     if( res != ERROR_SUCCESS )
257         return hdb;
258
259     res = MsiDatabaseCommit( hdb );
260     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
261
262     res = set_summary_info(hdb);
263
264     res = run_query( hdb,
265             "CREATE TABLE `Directory` ( "
266             "`Directory` CHAR(255) NOT NULL, "
267             "`Directory_Parent` CHAR(255), "
268             "`DefaultDir` CHAR(255) NOT NULL "
269             "PRIMARY KEY `Directory`)" );
270     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
271
272     return hdb;
273 }
274
275 static MSIHANDLE package_from_db(MSIHANDLE hdb)
276 {
277     UINT res;
278     CHAR szPackage[10];
279     MSIHANDLE hPackage;
280
281     sprintf(szPackage,"#%li",hdb);
282     res = MsiOpenPackage(szPackage,&hPackage);
283     ok( res == ERROR_SUCCESS , "Failed to open package\n" );
284
285     res = MsiCloseHandle(hdb);
286     ok( res == ERROR_SUCCESS , "Failed to close db handle\n" );
287
288     return hPackage;
289 }
290
291 static void create_test_file(const CHAR *name)
292 {
293     HANDLE file;
294     DWORD written;
295
296     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
297     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
298     WriteFile(file, name, strlen(name), &written, NULL);
299     WriteFile(file, "\n", strlen("\n"), &written, NULL);
300     CloseHandle(file);
301 }
302
303 static MSIHANDLE helper_createpackage( const char *szName )
304 {
305     MSIHANDLE hdb = 0;
306     UINT res;
307     CHAR szPackage[10];
308     MSIHANDLE hPackage;
309     MSIHANDLE suminfo;
310
311     DeleteFile(szName);
312
313     /* create an empty database */
314     res = MsiOpenDatabase(szName, MSIDBOPEN_CREATE, &hdb );
315     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
316
317     res = MsiDatabaseCommit( hdb );
318     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
319
320     /* build summmary info */
321     res = MsiGetSummaryInformation(hdb, NULL, 7, &suminfo);
322     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
323
324     res = MsiSummaryInfoSetProperty(suminfo,2, VT_LPSTR, 0,NULL,
325                         "Installation Database");
326     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
327
328     res = MsiSummaryInfoSetProperty(suminfo,3, VT_LPSTR, 0,NULL,
329                         "Installation Database");
330     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
331
332     res = MsiSummaryInfoSetProperty(suminfo,4, VT_LPSTR, 0,NULL,
333                         "Wine Hackers");
334     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
335
336     res = MsiSummaryInfoSetProperty(suminfo,7, VT_LPSTR, 0,NULL,
337                     ";1033");
338     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
339
340     res = MsiSummaryInfoSetProperty(suminfo,9, VT_LPSTR, 0,NULL,
341                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
342     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
343
344     res = MsiSummaryInfoSetProperty(suminfo, 14, VT_I4, 100, NULL, NULL);
345     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
346
347     res = MsiSummaryInfoSetProperty(suminfo, 15, VT_I4, 0, NULL, NULL);
348     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
349
350     res = MsiSummaryInfoPersist(suminfo);
351     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
352
353     res = MsiCloseHandle( suminfo);
354     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
355
356     sprintf(szPackage,"#%li",(DWORD)hdb);
357     res = MsiOpenPackage(szPackage,&hPackage);
358     ok( res == ERROR_SUCCESS , "Failed to open package\n" );
359
360     res = MsiCloseHandle( hdb );
361     ok( res == ERROR_SUCCESS , "Failed to close database\n" );
362
363     return hPackage;
364 }
365
366 static void test_createpackage(void)
367 {
368     static const CHAR filename[] = "winetest.msi";
369     MSIHANDLE hPackage = 0;
370     UINT res;
371
372     hPackage = helper_createpackage( filename );
373     ok ( hPackage != 0, " Failed to create package\n");
374
375     res = MsiCloseHandle( hPackage);
376     ok( res == ERROR_SUCCESS , "Failed to close package\n" );
377
378     DeleteFile( filename );
379 }
380
381 static void test_formatrecord(void)
382 {
383     char buffer[100];
384     MSIHANDLE hrec;
385     UINT r;
386     DWORD sz;
387
388     r = MsiFormatRecord(0, 0, NULL, NULL );
389     ok( r == ERROR_INVALID_HANDLE, "wrong error\n");
390
391     hrec = MsiCreateRecord(4);
392     ok( hrec, "failed to create record\n");
393
394     /* format an empty record */
395     r = MsiFormatRecord(0, hrec, NULL, NULL );
396     ok( r == ERROR_SUCCESS, "format failed\n");
397     buffer[0] = 'x';
398     buffer[1] = 0;
399     sz=0;
400     r = MsiFormatRecord(0, hrec, buffer+1, &sz);
401     ok( r == ERROR_MORE_DATA && buffer[0] == 'x', "format failed measuring with buffer\n");
402     ok( sz == 16, "size wrong\n");
403     sz=100;
404     r = MsiFormatRecord(0, hrec, buffer, &sz);
405     ok( r == ERROR_SUCCESS, "format failed with empty buffer\n");
406     ok( sz == 16, "size wrong\n");
407     ok( 0 == strcmp(buffer,"1:  2:  3:  4:  "), "wrong output\n");
408
409     r = MsiCloseHandle(hrec);
410     ok(r==ERROR_SUCCESS, "Unable to close record\n");
411
412     hrec = MsiCreateRecord(6);
413     ok( hrec, "failed to create record\n");
414
415     sz = 100;
416     buffer[0] = 'x';
417     buffer[1] = 0;
418     r = MsiFormatRecord(0, hrec, buffer, &sz);
419     ok( r == ERROR_SUCCESS, "format failed with empty buffer\n");
420     ok( sz == 24, "size wrong\n");
421     ok( 0 == strcmp(buffer,"1:  2:  3:  4:  5:  6:  "), "wrong output\n");
422
423
424     /* format a format string with everything else empty */
425     r = MsiRecordSetString(hrec, 0, "%1");
426     ok( r == ERROR_SUCCESS, "set string failed\n");
427     r = MsiFormatRecord(0, hrec, NULL, NULL );
428     ok( r == ERROR_SUCCESS, "format failed\n");
429     r = MsiFormatRecord(0, hrec, buffer, NULL);
430     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
431
432     sz = 123;
433     r = MsiFormatRecord(0, hrec, NULL, &sz);
434     ok( r == ERROR_SUCCESS, "format failed with empty buffer\n");
435     ok( sz == 2, "size wrong (%li)\n",sz);
436     sz = sizeof buffer;
437     buffer[0] = 'x';
438     buffer[1] = 0;
439     r = MsiFormatRecord(0, hrec, buffer, &sz);
440     ok( r == ERROR_SUCCESS, "format failed with empty buffer\n");
441     ok( sz == 2, "size wrong\n");
442     ok( 0 == strcmp(buffer,"%1"), "wrong output\n");
443
444     /* make the buffer too small */
445     sz = 0;
446     buffer[0] = 'x';
447     buffer[1] = 0;
448     r = MsiFormatRecord(0, hrec, buffer, &sz);
449     ok( r == ERROR_MORE_DATA, "format failed with empty buffer\n");
450     ok( sz == 2, "size wrong\n");
451     ok( 0 == strcmp(buffer,"x"), "wrong output\n");
452
453     /* make the buffer a little bit bigger */
454     sz = 1;
455     buffer[0] = 'x';
456     buffer[1] = 0;
457     r = MsiFormatRecord(0, hrec, buffer, &sz);
458     ok( r == ERROR_MORE_DATA, "format failed with empty buffer\n");
459     ok( sz == 2, "size wrong\n");
460     ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
461
462     /* and again */
463     sz = 2;
464     buffer[0] = 'x';
465     buffer[1] = 0;
466     r = MsiFormatRecord(0, hrec, buffer, &sz);
467     ok( r == ERROR_MORE_DATA, "format failed with empty buffer\n");
468     ok( sz == 2, "size wrong\n");
469     ok( 0 == strcmp(buffer,"%"), "wrong output\n");
470
471     /* and again */
472     sz = 3;
473     buffer[0] = 'x';
474     buffer[1] = 0;
475     r = MsiFormatRecord(0, hrec, buffer, &sz);
476     ok( r == ERROR_SUCCESS, "format failed with empty buffer\n");
477     ok( sz == 2, "size wrong\n");
478     ok( 0 == strcmp(buffer,"%1"), "wrong output\n");
479
480     /* now try a real format string */
481     r = MsiRecordSetString(hrec, 0, "[1]");
482     ok( r == ERROR_SUCCESS, "set string failed\n");
483     sz = sizeof buffer;
484     r = MsiFormatRecord(0, hrec, buffer, &sz);
485     ok( r == ERROR_SUCCESS, "format failed\n");
486     ok( sz == 0, "size wrong\n");
487     ok( 0 == strcmp(buffer,""), "wrong output\n");
488
489     /* now put something in the first field */
490     r = MsiRecordSetString(hrec, 1, "boo hoo");
491     ok( r == ERROR_SUCCESS, "set string failed\n");
492     sz = sizeof buffer;
493     r = MsiFormatRecord(0, hrec, buffer, &sz);
494     ok( r == ERROR_SUCCESS, "format failed\n");
495     ok( sz == 7, "size wrong\n");
496     ok( 0 == strcmp(buffer,"boo hoo"), "wrong output\n");
497
498     /* now put something in the first field */
499     r = MsiRecordSetString(hrec, 0, "[1] [2]");
500     r = MsiRecordSetString(hrec, 1, "boo");
501     r = MsiRecordSetString(hrec, 2, "hoo");
502     ok( r == ERROR_SUCCESS, "set string failed\n");
503     sz = sizeof buffer;
504     r = MsiFormatRecord(0, hrec, buffer, &sz);
505     ok( r == ERROR_SUCCESS, "format failed\n");
506     ok( sz == 7, "size wrong\n");
507     ok( 0 == strcmp(buffer,"boo hoo"), "wrong output\n");
508
509
510     /* empty string */
511     r = MsiRecordSetString(hrec, 0, "");
512     sz = sizeof buffer;
513     r = MsiFormatRecord(0, hrec, buffer, &sz);
514     ok( r == ERROR_SUCCESS, "format failed\n");
515     ok( sz == 30, "size wrong %li\n",sz);
516     ok( 0 == strcmp(buffer,"1: boo 2: hoo 3:  4:  5:  6:  "), 
517                     "wrong output(%s)\n",buffer);
518
519     /* play games with recursive lookups */
520     r = MsiRecordSetString(hrec, 0, "[[1]] [2]");
521     r = MsiRecordSetString(hrec, 1, "2");
522     r = MsiRecordSetString(hrec, 2, "hey");
523     ok( r == ERROR_SUCCESS, "set string failed\n");
524     sz = sizeof buffer;
525     r = MsiFormatRecord(0, hrec, buffer, &sz);
526     ok( r == ERROR_SUCCESS, "format failed\n");
527     ok( sz == 7, "size wrong,(%li)\n",sz);
528     ok( 0 == strcmp(buffer,"hey hey"), "wrong output (%s)\n",buffer);
529
530     r = MsiRecordSetString(hrec, 0, "[[1]] [2]");
531     r = MsiRecordSetString(hrec, 1, "[2]");
532     r = MsiRecordSetString(hrec, 2, "hey");
533     ok( r == ERROR_SUCCESS, "set string failed\n");
534     sz = sizeof buffer;
535     r = MsiFormatRecord(0, hrec, buffer, &sz);
536     ok( r == ERROR_SUCCESS, "format failed\n");
537     ok( sz == 9, "size wrong,(%li)\n",sz);
538     ok( 0 == strcmp(buffer,"[[2]] hey"), "wrong output (%s)\n",buffer);
539
540     r = MsiRecordSetString(hrec, 0, "[[[3]]] [2]");
541     r = MsiRecordSetString(hrec, 1, "2");
542     r = MsiRecordSetString(hrec, 2, "hey");
543     r = MsiRecordSetString(hrec, 3, "1");
544     ok( r == ERROR_SUCCESS, "set string failed\n");
545     sz = sizeof buffer;
546     r = MsiFormatRecord(0, hrec, buffer, &sz);
547     ok( r == ERROR_SUCCESS, "format failed\n");
548     ok( sz == 7, "size wrong,(%li)\n",sz);
549     ok( 0 == strcmp(buffer,"hey hey"), "wrong output (%s)\n",buffer);
550
551     r = MsiCloseHandle(hrec);
552     ok(r==ERROR_SUCCESS, "Unable to close record\n");
553     hrec = MsiCreateRecord(12);
554     ok( hrec, "failed to create record\n");
555
556     r = MsiRecordSetString(hrec, 0, "[[3][1]] [2]");
557     r = MsiRecordSetString(hrec, 1, "2");
558     r = MsiRecordSetString(hrec, 2, "hey");
559     r = MsiRecordSetString(hrec, 3, "1");
560     r = MsiRecordSetString(hrec, 12, "big");
561     ok( r == ERROR_SUCCESS, "set string failed\n");
562     sz = sizeof buffer;
563     r = MsiFormatRecord(0, hrec, buffer, &sz);
564     ok( r == ERROR_SUCCESS, "format failed\n");
565     ok( sz == 7, "size wrong,(%li)\n",sz);
566     ok( 0 == strcmp(buffer,"big hey"), "wrong output (%s)\n",buffer);
567
568     r = MsiRecordSetString(hrec, 0, "[[3][4][1]] [2]");
569     r = MsiRecordSetString(hrec, 1, "2");
570     r = MsiRecordSetString(hrec, 2, "hey");
571     r = MsiRecordSetString(hrec, 3, "1");
572     r = MsiRecordSetString(hrec, 4, NULL);
573     r = MsiRecordSetString(hrec, 12, "big");
574     ok( r == ERROR_SUCCESS, "set string failed\n");
575     sz = sizeof buffer;
576     r = MsiFormatRecord(0, hrec, buffer, &sz);
577     ok( r == ERROR_SUCCESS, "format failed\n");
578     ok( sz == 7, "size wrong,(%li)\n",sz);
579     ok( 0 == strcmp(buffer,"big hey"), "wrong output (%s)\n",buffer);
580
581     r = MsiRecordSetString(hrec, 0, "[[3][[4]][1]] [2]");
582     r = MsiRecordSetString(hrec, 1, "2");
583     r = MsiRecordSetString(hrec, 2, "hey");
584     r = MsiRecordSetString(hrec, 3, "1");
585     r = MsiRecordSetString(hrec, 4, NULL);
586     r = MsiRecordSetString(hrec, 12, "big");
587     ok( r == ERROR_SUCCESS, "set string failed\n");
588     sz = sizeof buffer;
589     r = MsiFormatRecord(0, hrec, buffer, &sz);
590     ok( r == ERROR_SUCCESS, "format failed\n");
591     ok( sz == 10, "size wrong,(%li)\n",sz);
592     ok( 0 == strcmp(buffer,"[1[]2] hey"), "wrong output (%s)\n",buffer);
593
594     /* incorrect  formats */
595     r = MsiRecordSetString(hrec, 0, "[[[3][[4]][1]] [2]");
596     r = MsiRecordSetString(hrec, 1, "2");
597     r = MsiRecordSetString(hrec, 2, "hey");
598     r = MsiRecordSetString(hrec, 3, "1");
599     r = MsiRecordSetString(hrec, 4, NULL);
600     r = MsiRecordSetString(hrec, 12, "big");
601     ok( r == ERROR_SUCCESS, "set string failed\n");
602     sz = sizeof buffer;
603     r = MsiFormatRecord(0, hrec, buffer, &sz);
604     ok( r == ERROR_SUCCESS, "format failed\n");
605     ok( sz == 18, "size wrong,(%li)\n",sz);
606     ok( 0 == strcmp(buffer,"[[[3][[4]][1]] [2]"), "wrong output (%s)\n",buffer);
607
608     r = MsiRecordSetString(hrec, 0, "[[3][[4]][1]] [2]]");
609     r = MsiRecordSetString(hrec, 1, "2");
610     r = MsiRecordSetString(hrec, 2, "hey");
611     r = MsiRecordSetString(hrec, 3, "1");
612     r = MsiRecordSetString(hrec, 4, NULL);
613     r = MsiRecordSetString(hrec, 12, "big");
614     ok( r == ERROR_SUCCESS, "set string failed\n");
615     sz = sizeof buffer;
616     r = MsiFormatRecord(0, hrec, buffer, &sz);
617     ok( r == ERROR_SUCCESS, "format failed\n");
618     ok( sz == 11, "size wrong,(%li)\n",sz);
619     ok( 0 == strcmp(buffer,"[1[]2] hey]"), "wrong output (%s)\n",buffer);
620
621
622     /* play games with {} */
623
624     r = MsiRecordSetString(hrec, 0, "{[3][1]} [2]");
625     r = MsiRecordSetString(hrec, 1, "2");
626     r = MsiRecordSetString(hrec, 2, "hey");
627     r = MsiRecordSetString(hrec, 3, "1");
628     r = MsiRecordSetString(hrec, 4, NULL);
629     r = MsiRecordSetString(hrec, 12, "big");
630     ok( r == ERROR_SUCCESS, "set string failed\n");
631     sz = sizeof buffer;
632     r = MsiFormatRecord(0, hrec, buffer, &sz);
633     ok( r == ERROR_SUCCESS, "format failed\n");
634     ok( sz == 6, "size wrong,(%li)\n",sz);
635     ok( 0 == strcmp(buffer,"12 hey"), "wrong output (%s)\n",buffer);
636
637     r = MsiRecordSetString(hrec, 0, "[{[3][1]}] [2]");
638     r = MsiRecordSetString(hrec, 1, "2");
639     r = MsiRecordSetString(hrec, 2, "hey");
640     r = MsiRecordSetString(hrec, 3, "1");
641     r = MsiRecordSetString(hrec, 4, NULL);
642     r = MsiRecordSetString(hrec, 12, "big");
643     ok( r == ERROR_SUCCESS, "set string failed\n");
644     sz = sizeof buffer;
645     r = MsiFormatRecord(0, hrec, buffer, &sz);
646     ok( r == ERROR_SUCCESS, "format failed\n");
647     ok( sz == 8, "size wrong,(%li)\n",sz);
648     ok( 0 == strcmp(buffer,"[12] hey"), "wrong output (%s)\n",buffer);
649
650
651     r = MsiRecordSetString(hrec, 0, "{test} [2]");
652     r = MsiRecordSetString(hrec, 1, "2");
653     r = MsiRecordSetString(hrec, 2, "hey");
654     r = MsiRecordSetString(hrec, 3, "1");
655     r = MsiRecordSetString(hrec, 4, NULL);
656     r = MsiRecordSetString(hrec, 12, "big");
657     ok( r == ERROR_SUCCESS, "set string failed\n");
658     sz = sizeof buffer;
659     r = MsiFormatRecord(0, hrec, buffer, &sz);
660     ok( r == ERROR_SUCCESS, "format failed\n");
661     ok( sz == 10, "size wrong,(%li)\n",sz);
662     ok( 0 == strcmp(buffer,"{test} hey"), "wrong output (%s)\n",buffer);
663
664     r = MsiRecordSetString(hrec, 0, "{[test]} [2]");
665     r = MsiRecordSetString(hrec, 1, "2");
666     r = MsiRecordSetString(hrec, 2, "hey");
667     r = MsiRecordSetString(hrec, 3, "1");
668     r = MsiRecordSetString(hrec, 4, NULL);
669     r = MsiRecordSetString(hrec, 12, "big");
670     ok( r == ERROR_SUCCESS, "set string failed\n");
671     sz = sizeof buffer;
672     r = MsiFormatRecord(0, hrec, buffer, &sz);
673     ok( r == ERROR_SUCCESS, "format failed\n");
674     ok( sz == 12, "size wrong,(%li)\n",sz);
675     ok( 0 == strcmp(buffer,"{[test]} hey"), "wrong output (%s)\n",buffer);
676
677     r = MsiRecordSetString(hrec, 0, "{[1][2][3][4]} [2]");
678     r = MsiRecordSetString(hrec, 1, "2");
679     r = MsiRecordSetString(hrec, 2, "hey");
680     r = MsiRecordSetString(hrec, 3, "1");
681     r = MsiRecordSetString(hrec, 4, NULL);
682     r = MsiRecordSetString(hrec, 12, "big");
683     ok( r == ERROR_SUCCESS, "set string failed\n");
684     sz = sizeof buffer;
685     r = MsiFormatRecord(0, hrec, buffer, &sz);
686     ok( r == ERROR_SUCCESS, "format failed\n");
687     ok( sz == 4, "size wrong,(%li)\n",sz);
688     ok( 0 == strcmp(buffer," hey"), "wrong output (%s)\n",buffer);
689
690     r = MsiRecordSetString(hrec, 0, "{[1][2][3][dummy]} [2]");
691     r = MsiRecordSetString(hrec, 1, "2");
692     r = MsiRecordSetString(hrec, 2, "hey");
693     r = MsiRecordSetString(hrec, 3, "1");
694     r = MsiRecordSetString(hrec, 4, NULL);
695     r = MsiRecordSetString(hrec, 12, "big");
696     ok( r == ERROR_SUCCESS, "set string failed\n");
697     sz = sizeof buffer;
698     r = MsiFormatRecord(0, hrec, buffer, &sz);
699     ok( r == ERROR_SUCCESS, "format failed\n");
700     ok( sz == 18, "size wrong,(%li)\n",sz);
701     ok( 0 == strcmp(buffer,"{2hey1[dummy]} hey"), "wrong output (%s)\n",buffer);
702
703     r = MsiRecordSetString(hrec, 0, "{[1][2][3][4][dummy]} [2]");
704     r = MsiRecordSetString(hrec, 1, "2");
705     r = MsiRecordSetString(hrec, 2, "hey");
706     r = MsiRecordSetString(hrec, 3, "1");
707     r = MsiRecordSetString(hrec, 4, NULL);
708     r = MsiRecordSetString(hrec, 12, "big");
709     ok( r == ERROR_SUCCESS, "set string failed\n");
710     sz = sizeof buffer;
711     r = MsiFormatRecord(0, hrec, buffer, &sz);
712     ok( r == ERROR_SUCCESS, "format failed\n");
713     ok( sz == 18, "size wrong,(%li)\n",sz);
714     ok( 0 == strcmp(buffer,"{2hey1[dummy]} hey"), "wrong output (%s)\n",buffer);
715
716     r = MsiRecordSetString(hrec, 0, "{{[1][2]}[3][4][dummy]}");
717     r = MsiRecordSetString(hrec, 1, "2");
718     r = MsiRecordSetString(hrec, 2, "hey");
719     r = MsiRecordSetString(hrec, 3, "1");
720     r = MsiRecordSetString(hrec, 4, NULL);
721     r = MsiRecordSetString(hrec, 12, "big");
722     ok( r == ERROR_SUCCESS, "set string failed\n");
723     sz = sizeof buffer;
724     r = MsiFormatRecord(0, hrec, buffer, &sz);
725     ok( r == ERROR_SUCCESS, "format failed\n");
726
727     todo_wine{
728     ok( sz == 16, "size wrong,(%li)\n",sz);
729     ok( 0 == strcmp(buffer,"{{2hey}1[dummy]}"), "wrong output (%s)\n",buffer);
730     }
731
732     r = MsiRecordSetString(hrec, 0, "{{[1][2]}[3]{[4][dummy]}}");
733     r = MsiRecordSetString(hrec, 1, "2");
734     r = MsiRecordSetString(hrec, 2, "hey");
735     r = MsiRecordSetString(hrec, 3, "1");
736     r = MsiRecordSetString(hrec, 4, NULL);
737     r = MsiRecordSetString(hrec, 12, "big");
738     ok( r == ERROR_SUCCESS, "set string failed\n");
739     sz = sizeof buffer;
740     r = MsiFormatRecord(0, hrec, buffer, &sz);
741     ok( r == ERROR_SUCCESS, "format failed\n");
742     todo_wine{
743     ok( sz == 0, "size wrong,(%li)\n",sz);
744     ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
745     }
746
747     r = MsiRecordSetString(hrec, 0, "{{[1][2]}[3]} {[1][2]}");
748     r = MsiRecordSetString(hrec, 1, "1");
749     r = MsiRecordSetString(hrec, 2, "2");
750     r = MsiRecordSetString(hrec, 3, "3");
751     r = MsiRecordSetString(hrec, 4, NULL);
752     r = MsiRecordSetString(hrec, 12, "big");
753     ok( r == ERROR_SUCCESS, "set string failed\n");
754     sz = sizeof buffer;
755     r = MsiFormatRecord(0, hrec, buffer, &sz);
756     ok( r == ERROR_SUCCESS, "format failed\n");
757     todo_wine{
758     ok( sz == 12, "size wrong,(%li)\n",sz);
759     ok( 0 == strcmp(buffer,"{{12}3} {12}"), "wrong output (%s)\n",buffer);
760     }
761
762     r = MsiRecordSetString(hrec, 0, "{[1][2]} {{[1][2]}[3]} {[1][2]}");
763     r = MsiRecordSetString(hrec, 1, "1");
764     r = MsiRecordSetString(hrec, 2, "2");
765     r = MsiRecordSetString(hrec, 3, "3");
766     r = MsiRecordSetString(hrec, 4, NULL);
767     r = MsiRecordSetString(hrec, 12, "big");
768     ok( r == ERROR_SUCCESS, "set string failed\n");
769     sz = sizeof buffer;
770     r = MsiFormatRecord(0, hrec, buffer, &sz);
771     ok( r == ERROR_SUCCESS, "format failed\n");
772     todo_wine{
773     ok( sz == 15, "size wrong,(%li)\n",sz);
774     ok( 0 == strcmp(buffer,"12 {{12}3} {12}"), "wrong output (%s)\n",buffer);
775     }
776
777     r = MsiRecordSetString(hrec, 0, "{[4]}{[1][2]} {{[1][2]}[3]} {[1][2]}");
778     r = MsiRecordSetString(hrec, 1, "1");
779     r = MsiRecordSetString(hrec, 2, "2");
780     r = MsiRecordSetString(hrec, 3, "3");
781     r = MsiRecordSetString(hrec, 4, NULL);
782     r = MsiRecordSetString(hrec, 12, "big");
783     ok( r == ERROR_SUCCESS, "set string failed\n");
784     sz = sizeof buffer;
785     r = MsiFormatRecord(0, hrec, buffer, &sz);
786     ok( r == ERROR_SUCCESS, "format failed\n");
787     todo_wine{
788     ok( sz == 15, "size wrong,(%li)\n",sz);
789     ok( 0 == strcmp(buffer,"12 {{12}3} {12}"), "wrong output (%s)\n",buffer);
790     }
791
792
793     r = MsiRecordSetString(hrec, 0, "{blah} {[4]}{[1][2]} {{[1][2]}[3]} {[1][2]}");
794     r = MsiRecordSetString(hrec, 1, "1");
795     r = MsiRecordSetString(hrec, 2, "2");
796     r = MsiRecordSetString(hrec, 3, "3");
797     r = MsiRecordSetString(hrec, 4, NULL);
798     r = MsiRecordSetString(hrec, 12, "big");
799     ok( r == ERROR_SUCCESS, "set string failed\n");
800     sz = sizeof buffer;
801     r = MsiFormatRecord(0, hrec, buffer, &sz);
802     ok( r == ERROR_SUCCESS, "format failed\n");
803     todo_wine{
804     ok( sz == 22, "size wrong,(%li)\n",sz);
805     ok( 0 == strcmp(buffer,"{blah} 12 {{12}3} {12}"), "wrong output (%s)\n",buffer);
806     }
807
808     r = MsiRecordSetString(hrec, 0, "{{[1]}[2]} {[4]}{[1][2]}");
809     r = MsiRecordSetString(hrec, 1, "1");
810     r = MsiRecordSetString(hrec, 2, "2");
811     r = MsiRecordSetString(hrec, 3, "3");
812     r = MsiRecordSetString(hrec, 4, NULL);
813     r = MsiRecordSetString(hrec, 12, "big");
814     ok( r == ERROR_SUCCESS, "set string failed\n");
815     sz = sizeof buffer;
816     r = MsiFormatRecord(0, hrec, buffer, &sz);
817     ok( r == ERROR_SUCCESS, "format failed\n");
818     todo_wine{
819     ok( sz == 13, "size wrong,(%li)\n",sz);
820     ok( 0 == strcmp(buffer,"{{1}2} {}{12}"), "wrong output (%s)\n",buffer);
821     }
822
823     r = MsiRecordSetString(hrec, 0, "{{[1]}} {[4]}{[1][2]}");
824     r = MsiRecordSetString(hrec, 1, "1");
825     r = MsiRecordSetString(hrec, 2, "2");
826     r = MsiRecordSetString(hrec, 3, "3");
827     r = MsiRecordSetString(hrec, 4, NULL);
828     r = MsiRecordSetString(hrec, 12, "big");
829     ok( r == ERROR_SUCCESS, "set string failed\n");
830     sz = sizeof buffer;
831     r = MsiFormatRecord(0, hrec, buffer, &sz);
832     ok( r == ERROR_SUCCESS, "format failed\n");
833     todo_wine{
834     ok( sz == 3, "size wrong,(%li)\n",sz);
835     ok( 0 == strcmp(buffer," 12"), "wrong output (%s)\n",buffer);
836     }
837
838     r = MsiRecordSetString(hrec, 0, "{{{[1]}} {[4]}{[1][2]}");
839     r = MsiRecordSetString(hrec, 1, "1");
840     r = MsiRecordSetString(hrec, 2, "2");
841     r = MsiRecordSetString(hrec, 3, "3");
842     r = MsiRecordSetString(hrec, 4, NULL);
843     r = MsiRecordSetString(hrec, 12, "big");
844     ok( r == ERROR_SUCCESS, "set string failed\n");
845     sz = sizeof buffer;
846     r = MsiFormatRecord(0, hrec, buffer, &sz);
847     ok( r == ERROR_SUCCESS, "format failed\n");
848     todo_wine{
849     ok( sz == 3, "size wrong,(%li)\n",sz);
850     ok( 0 == strcmp(buffer," 12"), "wrong output (%s)\n",buffer);
851     }
852     
853     /* now put play games with escaping */
854     r = MsiRecordSetString(hrec, 0, "[1] [2] [\\3asdf]");
855     r = MsiRecordSetString(hrec, 1, "boo");
856     r = MsiRecordSetString(hrec, 2, "hoo");
857     ok( r == ERROR_SUCCESS, "set string failed\n");
858     sz = sizeof buffer;
859     r = MsiFormatRecord(0, hrec, buffer, &sz);
860     ok( r == ERROR_SUCCESS, "format failed\n");
861     ok( sz == 16, "size wrong\n");
862     ok( 0 == strcmp(buffer,"boo hoo [\\3asdf]"), "wrong output\n");
863
864     /* now put play games with escaping */
865     r = MsiRecordSetString(hrec, 0, "[1] [2] [\\x]");
866     r = MsiRecordSetString(hrec, 1, "boo");
867     r = MsiRecordSetString(hrec, 2, "hoo");
868     ok( r == ERROR_SUCCESS, "set string failed\n");
869     sz = sizeof buffer;
870     r = MsiFormatRecord(0, hrec, buffer, &sz);
871     ok( r == ERROR_SUCCESS, "format failed\n");
872     ok( sz == 12, "size wrong\n");
873     ok( 0 == strcmp(buffer,"boo hoo [\\x]"), "wrong output\n");
874
875     MsiRecordSetString(hrec, 0, "[\\x]");
876     sz = sizeof buffer;
877     r = MsiFormatRecord(0, hrec, buffer, &sz);
878     ok( r == ERROR_SUCCESS, "format failed\n");
879     ok( sz == 4, "size wrong: %ld\n", sz);
880     ok( 0 == strcmp(buffer,"[\\x]"), "wrong output: %s\n", buffer);
881
882     MsiRecordSetString(hrec, 0, "{\\x}");
883     sz = sizeof buffer;
884     r = MsiFormatRecord(0, hrec, buffer, &sz);
885     ok( r == ERROR_SUCCESS, "format failed\n");
886     ok( sz == 4, "size wrong: %ld\n", sz);
887     ok( 0 == strcmp(buffer,"{\\x}"), "wrong output: %s\n", buffer);
888
889     MsiRecordSetString(hrec, 0, "[abc\\x]");
890     sz = sizeof buffer;
891     r = MsiFormatRecord(0, hrec, buffer, &sz);
892     ok( r == ERROR_SUCCESS, "format failed\n");
893     ok( sz == 7, "size wrong: %ld\n", sz);
894     ok( 0 == strcmp(buffer,"[abc\\x]"), "wrong output: %s\n", buffer);
895
896     MsiRecordSetString(hrec, 0, "[\\[]Bracket Text[\\]]");
897     sz = sizeof buffer;
898     r = MsiFormatRecord(0, hrec, buffer, &sz);
899     ok( r == ERROR_SUCCESS, "format failed\n");
900     ok( sz == 20, "size wrong: %ld\n", sz);
901     ok( 0 == strcmp(buffer,"[\\[]Bracket Text[\\]]"), "wrong output: %s\n", buffer);
902
903     /* now try other formats without a package */
904     r = MsiRecordSetString(hrec, 0, "[1] [2] [property]");
905     r = MsiRecordSetString(hrec, 1, "boo");
906     r = MsiRecordSetString(hrec, 2, "hoo");
907     ok( r == ERROR_SUCCESS, "set string failed\n");
908     sz = sizeof buffer;
909     r = MsiFormatRecord(0, hrec, buffer, &sz);
910     ok( r == ERROR_SUCCESS, "format failed\n");
911     ok( sz == 18, "size wrong\n");
912     ok( 0 == strcmp(buffer,"boo hoo [property]"), "wrong output\n");
913
914     r = MsiRecordSetString(hrec, 0, "[1] [~] [2]");
915     r = MsiRecordSetString(hrec, 1, "boo");
916     r = MsiRecordSetString(hrec, 2, "hoo");
917     ok( r == ERROR_SUCCESS, "set string failed\n");
918     sz = sizeof buffer;
919     r = MsiFormatRecord(0, hrec, buffer, &sz);
920     ok( r == ERROR_SUCCESS, "format failed\n");
921     ok( sz == 11, "size wrong\n");
922     ok( 0 == strcmp(buffer,"boo [~] hoo"), "wrong output (%s)\n",buffer);
923
924     r = MsiRecordSetString(hrec, 0, "[1]");
925     r = MsiRecordSetInteger(hrec, 1, 123456);
926     ok( r == ERROR_SUCCESS, "set integer failed\n");
927     sz = sizeof buffer;
928     r = MsiFormatRecord(0, hrec, buffer, &sz);
929     ok( r == ERROR_SUCCESS, "format failed\n");
930     todo_wine{
931     ok( sz == 6, "size wrong\n");
932     ok( 0 == strcmp(buffer,"123456"), "wrong output (%s)\n",buffer);
933     }
934
935     r = MsiRecordSetString(hrec, 0, "[~]");
936     sz = sizeof buffer;
937     r = MsiFormatRecord(0, hrec, buffer, &sz);
938     ok( sz == 3, "size wrong\n");
939     ok( 0 == strcmp(buffer,"[~]"), "wrong output\n");
940     ok( r == ERROR_SUCCESS, "format failed\n");
941
942     r = MsiRecordSetString(hrec, 0, "[]");
943     sz = sizeof buffer;
944     r = MsiFormatRecord(0, hrec, buffer, &sz);
945     ok( sz == 2, "size wrong\n");
946     ok( 0 == strcmp(buffer,"[]"), "wrong output\n");
947     ok( r == ERROR_SUCCESS, "format failed\n");
948
949     /* MsiFormatRecord doesn't seem to handle a negative too well */
950     r = MsiRecordSetString(hrec, 0, "[-1]");
951     sz = sizeof buffer;
952     r = MsiFormatRecord(0, hrec, buffer, &sz);
953     ok( sz == 4, "size wrong\n");
954     ok( 0 == strcmp(buffer,"[-1]"), "wrong output\n");
955     ok( r == ERROR_SUCCESS, "format failed\n");
956
957     r = MsiRecordSetString(hrec, 0, "{[]}");
958     sz = sizeof buffer;
959     r = MsiFormatRecord(0, hrec, buffer, &sz);
960     ok( sz == 4, "size wrong\n");
961     ok( 0 == strcmp(buffer,"{[]}"), "wrong output\n");
962     ok( r == ERROR_SUCCESS, "format failed\n");
963
964     r = MsiRecordSetString(hrec, 0, "[0]");
965     sz = sizeof buffer;
966     r = MsiFormatRecord(0, hrec, buffer, &sz);
967     ok( sz == 3, "size wrong\n");
968     ok( 0 == strcmp(buffer,"[0]"), "wrong output\n");
969     ok( r == ERROR_SUCCESS, "format failed\n");
970
971     r = MsiRecordSetString(hrec, 0, "[100]");
972     sz = sizeof buffer;
973     r = MsiFormatRecord(0, hrec, buffer, &sz);
974     ok( sz == 0, "size wrong\n");
975     ok( 0 == strcmp(buffer,""), "wrong output\n");
976     ok( r == ERROR_SUCCESS, "format failed\n");
977
978     r = MsiRecordSetString(hrec, 0, "{[1] [2]}");
979     r = MsiRecordSetString(hrec, 1, "boo");
980     r = MsiRecordSetString(hrec, 2, "hoo");
981     sz = sizeof buffer;
982     r = MsiFormatRecord(0, hrec, buffer, &sz);
983     ok( sz == 7, "size wrong\n");
984     ok( 0 == strcmp(buffer,"boo hoo"), "wrong output\n");
985     ok( r == ERROR_SUCCESS, "format failed\n");
986
987     r = MsiRecordSetString(hrec, 0, "{}");
988     sz = sizeof buffer;
989     r = MsiFormatRecord(0, hrec, buffer, &sz);
990     ok( sz == 0, "size wrong\n");
991     ok( 0 == strcmp(buffer,""), "wrong output\n");
992     ok( r == ERROR_SUCCESS, "format failed\n");
993
994     r = MsiRecordSetString(hrec, 0, "{foo}");
995     sz = sizeof buffer;
996     r = MsiFormatRecord(0, hrec, buffer, &sz);
997     ok( sz == 5, "size wrong\n");
998     ok( 0 == strcmp(buffer,"{foo}"), "wrong output\n");
999     ok( r == ERROR_SUCCESS, "format failed\n");
1000
1001     r = MsiRecordSetString(hrec, 0, "{boo [1]}");
1002     r = MsiRecordSetString(hrec, 1, "hoo");
1003     sz = sizeof buffer;
1004     r = MsiFormatRecord(0, hrec, buffer, &sz);
1005     ok( sz == 7, "size wrong\n");
1006     ok( 0 == strcmp(buffer,"boo hoo"), "wrong output\n");
1007     ok( r == ERROR_SUCCESS, "format failed\n");
1008
1009     todo_wine {
1010     r = MsiRecordSetString(hrec, 0, "{{[1]}}");
1011     r = MsiRecordSetString(hrec, 1, "hoo");
1012     sz = sizeof buffer;
1013     r = MsiFormatRecord(0, hrec, buffer, &sz);
1014     ok( sz == 0, "size wrong\n");
1015     ok( 0 == strcmp(buffer,""), "wrong output\n");
1016     }
1017     ok( r == ERROR_SUCCESS, "format failed\n");
1018
1019     r = MsiRecordSetString(hrec, 0, "{ {[1]}}");
1020     r = MsiRecordSetString(hrec, 1, "hoo");
1021     sz = sizeof buffer;
1022     r = MsiFormatRecord(0, hrec, buffer, &sz);
1023     ok( 0 == strcmp(buffer," {hoo}"), "wrong output\n");
1024     ok( sz == 6, "size wrong\n");
1025     ok( r == ERROR_SUCCESS, "format failed\n");
1026
1027     todo_wine {
1028     r = MsiRecordSetString(hrec, 0, "{{[1]} }");
1029     r = MsiRecordSetString(hrec, 1, "hoo");
1030     sz = sizeof buffer;
1031     r = MsiFormatRecord(0, hrec, buffer, &sz);
1032     ok( sz == 8, "size wrong\n");
1033     ok( 0 == strcmp(buffer,"{{hoo} }"), "wrong output\n");
1034     }
1035     ok( r == ERROR_SUCCESS, "format failed\n");
1036
1037     todo_wine {
1038     r = MsiRecordSetString(hrec, 0, "{{ [1]}}");
1039     r = MsiRecordSetString(hrec, 1, "hoo");
1040     sz = sizeof buffer;
1041     r = MsiFormatRecord(0, hrec, buffer, &sz);
1042     ok( sz == 0, "size wrong\n");
1043     ok( 0 == strcmp(buffer,""), "wrong output\n");
1044     }
1045     ok( r == ERROR_SUCCESS, "format failed\n");
1046
1047     todo_wine {
1048     r = MsiRecordSetString(hrec, 0, "{{[1] }}");
1049     r = MsiRecordSetString(hrec, 1, "hoo");
1050     sz = sizeof buffer;
1051     r = MsiFormatRecord(0, hrec, buffer, &sz);
1052     ok( sz == 0, "size wrong\n");
1053     ok( 0 == strcmp(buffer,""), "wrong output\n");
1054     }
1055     ok( r == ERROR_SUCCESS, "format failed\n");
1056
1057     todo_wine {
1058     r = MsiRecordSetString(hrec, 0, "{{a}{b}{c }{ d}{any text}}");
1059     sz = sizeof buffer;
1060     r = MsiFormatRecord(0, hrec, buffer, &sz);
1061     ok( sz == 0, "size wrong\n");
1062     ok( 0 == strcmp(buffer,""), "wrong output\n");
1063     }
1064     ok( r == ERROR_SUCCESS, "format failed\n");
1065
1066     r = MsiRecordSetString(hrec, 0, "{{a} }");
1067     sz = sizeof buffer;
1068     r = MsiFormatRecord(0, hrec, buffer, &sz);
1069     ok( sz == 6, "size wrong\n");
1070     ok( 0 == strcmp(buffer,"{{a} }"), "wrong output\n");
1071     ok( r == ERROR_SUCCESS, "format failed\n");
1072
1073     todo_wine {
1074     r = MsiRecordSetString(hrec, 0, "{{a} {b}}");
1075     sz = sizeof buffer;
1076     r = MsiFormatRecord(0, hrec, buffer, &sz);
1077     ok( sz == 0, "size wrong\n");
1078     ok( 0 == strcmp(buffer,""), "wrong output\n");
1079     }
1080     ok( r == ERROR_SUCCESS, "format failed\n");
1081
1082     todo_wine {
1083     r = MsiRecordSetString(hrec, 0, "{{a} b}}");
1084     sz = sizeof buffer;
1085     r = MsiFormatRecord(0, hrec, buffer, &sz);
1086     ok( sz == 0, "size wrong\n");
1087     ok( 0 == strcmp(buffer,""), "wrong output\n");
1088     }
1089     ok( r == ERROR_SUCCESS, "format failed\n");
1090
1091     todo_wine {
1092     r = MsiRecordSetString(hrec, 0, "{{a b}}");
1093     sz = sizeof buffer;
1094     r = MsiFormatRecord(0, hrec, buffer, &sz);
1095     ok( sz == 0, "size wrong\n");
1096     ok( 0 == strcmp(buffer,""), "wrong output\n");
1097     }
1098     ok( r == ERROR_SUCCESS, "format failed\n");
1099
1100     r = MsiRecordSetString(hrec, 0, "{ }");
1101     sz = sizeof buffer;
1102     r = MsiFormatRecord(0, hrec, buffer, &sz);
1103     ok( sz == 3, "size wrong\n");
1104     ok( 0 == strcmp(buffer,"{ }"), "wrong output\n");
1105     ok( r == ERROR_SUCCESS, "format failed\n");
1106
1107     todo_wine {
1108     r = MsiRecordSetString(hrec, 0, " {{a}}}");
1109     sz = sizeof buffer;
1110     r = MsiFormatRecord(0, hrec, buffer, &sz);
1111     ok( sz == 2, "size wrong\n");
1112     ok( 0 == strcmp(buffer," }"), "wrong output\n");
1113     }
1114     ok( r == ERROR_SUCCESS, "format failed\n");
1115
1116     todo_wine {
1117     r = MsiRecordSetString(hrec, 0, "{{ almost {{ any }} text }}");
1118     sz = sizeof buffer;
1119     r = MsiFormatRecord(0, hrec, buffer, &sz);
1120     ok( sz == 8, "size wrong\n");
1121     ok( 0 == strcmp(buffer," text }}"), "wrong output\n");
1122     }
1123     ok( r == ERROR_SUCCESS, "format failed\n");
1124
1125     todo_wine {
1126     r = MsiRecordSetString(hrec, 0, "{{ } { hidden ][ [ }}");
1127     sz = sizeof buffer;
1128     r = MsiFormatRecord(0, hrec, buffer, &sz);
1129     ok( sz == 0, "size wrong\n");
1130     ok( 0 == strcmp(buffer,""), "wrong output\n");
1131     }
1132     ok( r == ERROR_SUCCESS, "format failed\n");
1133
1134     r = MsiRecordSetString(hrec, 0, "[ 1]");
1135     r = MsiRecordSetString(hrec, 1, "hoo");
1136     sz = sizeof buffer;
1137     r = MsiFormatRecord(0, hrec, buffer, &sz);
1138     ok( sz == 4, "size wrong\n");
1139     ok( 0 == strcmp(buffer,"[ 1]"), "wrong output\n");
1140     ok( r == ERROR_SUCCESS, "format failed\n");
1141
1142     r = MsiRecordSetString(hrec, 0, "[01]");
1143     r = MsiRecordSetString(hrec, 1, "hoo");
1144     sz = sizeof buffer;
1145     r = MsiFormatRecord(0, hrec, buffer, &sz);
1146     ok( sz == 3, "size wrong\n");
1147     ok( 0 == strcmp(buffer,"hoo"), "wrong output\n");
1148     ok( r == ERROR_SUCCESS, "format failed\n");
1149
1150     todo_wine {
1151     r = MsiRecordSetString(hrec, 0, "{{test}} [01");
1152     r = MsiRecordSetString(hrec, 1, "hoo");
1153     sz = sizeof buffer;
1154     r = MsiFormatRecord(0, hrec, buffer, &sz);
1155     ok( sz == 4, "size wrong\n");
1156     ok( 0 == strcmp(buffer," [01"), "wrong output\n");
1157     }
1158     ok( r == ERROR_SUCCESS, "format failed\n");
1159
1160     r = MsiRecordSetString(hrec, 0, "[\\[]");
1161     r = MsiRecordSetString(hrec, 1, "hoo");
1162     sz = sizeof buffer;
1163     r = MsiFormatRecord(0, hrec, buffer, &sz);
1164     ok( sz == 4, "size wrong\n");
1165     ok( 0 == strcmp(buffer,"[\\[]"), "wrong output\n");
1166     ok( r == ERROR_SUCCESS, "format failed\n");
1167
1168     r = MsiRecordSetString(hrec, 0, "[foo]");
1169     r = MsiRecordSetString(hrec, 1, "hoo");
1170     sz = sizeof buffer;
1171     r = MsiFormatRecord(0, hrec, buffer, &sz);
1172     ok( sz == 5, "size wrong\n");
1173     ok( 0 == strcmp(buffer,"[foo]"), "wrong output\n");
1174     ok( r == ERROR_SUCCESS, "format failed\n");
1175
1176     r = MsiRecordSetString(hrec, 0, "[01.]");
1177     r = MsiRecordSetString(hrec, 1, "hoo");
1178     sz = sizeof buffer;
1179     r = MsiFormatRecord(0, hrec, buffer, &sz);
1180     ok( sz == 5, "size wrong\n");
1181     ok( 0 == strcmp(buffer,"[01.]"), "wrong output\n");
1182     ok( r == ERROR_SUCCESS, "format failed\n");
1183
1184     SetEnvironmentVariable("FOO", "BAR");
1185     r = MsiRecordSetString(hrec, 0, "[%FOO]");
1186     sz = sizeof buffer;
1187     r = MsiFormatRecord(0, hrec, buffer, &sz);
1188     ok( sz == 6, "size wrong\n");
1189     ok( 0 == strcmp(buffer,"[%FOO]"), "wrong output\n");
1190     ok( r == ERROR_SUCCESS, "format failed\n");
1191
1192     todo_wine {
1193     r = MsiRecordSetString(hrec, 0, "{{[1]}");
1194     r = MsiRecordSetString(hrec, 1, "hoo");
1195     sz = sizeof buffer;
1196     r = MsiFormatRecord(0, hrec, buffer, &sz);
1197     ok( sz == 6, "size wrong\n");
1198     ok( 0 == strcmp(buffer,"{{hoo}"), "wrong output\n");
1199     }
1200     ok( r == ERROR_SUCCESS, "format failed\n");
1201
1202     todo_wine {
1203     r = MsiRecordSetString(hrec, 0, "{{ {[1]}");
1204     r = MsiRecordSetString(hrec, 1, "hoo");
1205     sz = sizeof buffer;
1206     r = MsiFormatRecord(0, hrec, buffer, &sz);
1207     ok( sz == 8, "size wrong\n");
1208     ok( 0 == strcmp(buffer,"{{ {hoo}"), "wrong output\n");
1209     }
1210     ok( r == ERROR_SUCCESS, "format failed\n");
1211
1212     todo_wine {
1213     r = MsiRecordSetString(hrec, 0, "{{ {[1]}");
1214     r = MsiRecordSetString(hrec, 1, "hoo");
1215     sz = sizeof buffer;
1216     r = MsiFormatRecord(0, hrec, buffer, &sz);
1217     ok( sz == 8, "size wrong\n");
1218     ok( 0 == strcmp(buffer,"{{ {hoo}"), "wrong output\n");
1219     }
1220     ok( r == ERROR_SUCCESS, "format failed\n");
1221
1222     todo_wine {
1223     r = MsiRecordSetString(hrec, 0, "{{ {{[1]}");
1224     r = MsiRecordSetString(hrec, 1, "hoo");
1225     sz = sizeof buffer;
1226     r = MsiFormatRecord(0, hrec, buffer, &sz);
1227     ok( sz == 9, "size wrong\n");
1228     ok( 0 == strcmp(buffer,"{{ {{hoo}"), "wrong output\n");
1229     }
1230     ok( r == ERROR_SUCCESS, "format failed\n");
1231
1232     r = MsiRecordSetString(hrec, 0, "[1]}");
1233     r = MsiRecordSetString(hrec, 1, "hoo");
1234     sz = sizeof buffer;
1235     r = MsiFormatRecord(0, hrec, buffer, &sz);
1236     ok( sz == 4, "size wrong\n");
1237     ok( 0 == strcmp(buffer,"hoo}"), "wrong output\n");
1238     ok( r == ERROR_SUCCESS, "format failed\n");
1239
1240     r = MsiRecordSetString(hrec, 0, "{{ {{a}");
1241     sz = sizeof buffer;
1242     r = MsiFormatRecord(0, hrec, buffer, &sz);
1243     ok( sz == 7, "size wrong\n");
1244     ok( 0 == strcmp(buffer,"{{ {{a}"), "wrong output\n");
1245     ok( r == ERROR_SUCCESS, "format failed\n");
1246
1247     r = MsiRecordSetString(hrec, 0, "{{ {{a}");
1248     sz = sizeof buffer;
1249     r = MsiFormatRecord(0, hrec, buffer, &sz);
1250     ok( sz == 7, "size wrong\n");
1251     ok( 0 == strcmp(buffer,"{{ {{a}"), "wrong output\n");
1252     ok( r == ERROR_SUCCESS, "format failed\n");
1253
1254     r = MsiRecordSetString(hrec, 0, "0{1{2{3{4[1]5}6}7}8}9");
1255     r = MsiRecordSetString(hrec, 1, "hoo");
1256     sz = sizeof buffer;
1257     r = MsiFormatRecord(0, hrec, buffer, &sz);
1258     ok( sz == 19, "size wrong\n");
1259     ok( 0 == strcmp(buffer,"01{2{3{4hoo56}7}8}9"), "wrong output\n");
1260     ok( r == ERROR_SUCCESS, "format failed\n");
1261
1262     r = MsiRecordSetString(hrec, 0, "0{1{2[1]3}4");
1263     r = MsiRecordSetString(hrec, 1, "hoo");
1264     sz = sizeof buffer;
1265     r = MsiFormatRecord(0, hrec, buffer, &sz);
1266     ok( sz == 9, "size wrong\n");
1267     ok( 0 == strcmp(buffer,"01{2hoo34"), "wrong output\n");
1268     ok( r == ERROR_SUCCESS, "format failed\n");
1269
1270     r = MsiRecordSetString(hrec, 0, "0{1{2[1]3}4");
1271     r = MsiRecordSetString(hrec, 1, "hoo");
1272     sz = sizeof buffer;
1273     r = MsiFormatRecord(0, hrec, buffer, &sz);
1274     ok( sz == 9, "size wrong\n");
1275     ok( 0 == strcmp(buffer,"01{2hoo34"), "wrong output\n");
1276     ok( r == ERROR_SUCCESS, "format failed\n");
1277
1278     r = MsiRecordSetString(hrec, 0, "{[1.} [1]");
1279     r = MsiRecordSetString(hrec, 1, "hoo");
1280     sz = sizeof buffer;
1281     r = MsiFormatRecord(0, hrec, buffer, &sz);
1282     ok( sz == 9, "size wrong\n");
1283     ok( 0 == strcmp(buffer,"{[1.} hoo"), "wrong output\n");
1284     ok( r == ERROR_SUCCESS, "format failed\n");
1285
1286     r = MsiRecordSetString(hrec, 0, "{[{[1]}]}");
1287     r = MsiRecordSetString(hrec, 1, "2");
1288     r = MsiRecordSetString(hrec, 2, "foo");
1289     sz = sizeof buffer;
1290     r = MsiFormatRecord(0, hrec, buffer, &sz);
1291     ok( sz == 9, "size wrong\n");
1292     ok( 0 == strcmp(buffer,"{[{[1]}]}"), "wrong output\n");
1293     ok( r == ERROR_SUCCESS, "format failed\n");
1294
1295     r = MsiRecordSetString(hrec, 0, "{[1][}");
1296     r = MsiRecordSetString(hrec, 1, "2");
1297     r = MsiRecordSetString(hrec, 2, "foo");
1298     sz = sizeof buffer;
1299     r = MsiFormatRecord(0, hrec, buffer, &sz);
1300     ok( sz == 2, "size wrong\n");
1301     ok( 0 == strcmp(buffer,"2["), "wrong output\n");
1302     ok( r == ERROR_SUCCESS, "format failed\n");
1303
1304     r = MsiRecordSetString(hrec, 0, "[1]");
1305     r = MsiRecordSetString(hrec, 1, "[2]");
1306     r = MsiRecordSetString(hrec, 2, "foo");
1307     sz = sizeof buffer;
1308     r = MsiFormatRecord(0, hrec, buffer, &sz);
1309     ok( sz == 3, "size wrong\n");
1310     ok( 0 == strcmp(buffer,"[2]"), "wrong output\n");
1311     ok( r == ERROR_SUCCESS, "format failed\n");
1312
1313     todo_wine {
1314     r = MsiRecordSetString(hrec, 0, "[{{boo}}1]");
1315     r = MsiRecordSetString(hrec, 1, "hoo");
1316     sz = sizeof buffer;
1317     r = MsiFormatRecord(0, hrec, buffer, &sz);
1318     ok( sz == 3, "size wrong\n");
1319     ok( 0 == strcmp(buffer,"[1]"), "wrong output\n");
1320     }
1321     ok( r == ERROR_SUCCESS, "format failed\n");
1322
1323     todo_wine {
1324     r = MsiRecordSetString(hrec, 0, "[{{boo}}1]");
1325     r = MsiRecordSetString(hrec, 0, "[1{{boo}}]");
1326     r = MsiRecordSetString(hrec, 1, "hoo");
1327     sz = sizeof buffer;
1328     r = MsiFormatRecord(0, hrec, buffer, &sz);
1329     ok( sz == 3, "size wrong\n");
1330     ok( 0 == strcmp(buffer,"[1]"), "wrong output\n");
1331     }
1332     ok( r == ERROR_SUCCESS, "format failed\n");
1333
1334     r = MsiRecordSetString(hrec, 0, "{[1]{{boo} }}");
1335     r = MsiRecordSetString(hrec, 1, "hoo");
1336     sz = sizeof buffer;
1337     r = MsiFormatRecord(0, hrec, buffer, &sz);
1338     ok( sz == 11, "size wrong\n");
1339     ok( 0 == strcmp(buffer,"hoo{{boo }}"), "wrong output\n");
1340     ok( r == ERROR_SUCCESS, "format failed\n");
1341
1342     r = MsiRecordSetString(hrec, 0, "{[1{{boo}}]}");
1343     r = MsiRecordSetString(hrec, 1, "hoo");
1344     sz = sizeof buffer;
1345     r = MsiFormatRecord(0, hrec, buffer, &sz);
1346     ok( sz == 12, "size wrong: got %lu, expected 12\n", sz);
1347     ok( 0 == strcmp(buffer,"{[1{{boo}}]}"), "wrong output: got %s, expected [1]\n", buffer);
1348     ok( r == ERROR_SUCCESS, "format failed\n");
1349
1350     todo_wine {
1351     r = MsiRecordSetString(hrec, 0, "{{[1]}");
1352     r = MsiRecordSetString(hrec, 1, "hoo");
1353     sz = sizeof buffer;
1354     r = MsiFormatRecord(0, hrec, buffer, &sz);
1355     ok( sz == 6, "size wrong: got %lu, expected 3\n", sz);
1356     ok( 0 == strcmp(buffer,"{{hoo}"), "wrong output: got %s, expected [1]\n", buffer);
1357     }
1358     ok( r == ERROR_SUCCESS, "format failed\n");
1359
1360     r = MsiRecordSetString(hrec, 0, "{[1{{bo}o}}]}");
1361     r = MsiRecordSetString(hrec, 1, "hoo");
1362     sz = sizeof buffer;
1363     r = MsiFormatRecord(0, hrec, buffer, &sz);
1364     ok( sz == 13, "size wrong\n");
1365     ok( 0 == strcmp(buffer,"{[1{{bo}o}}]}"), "wrong output %s\n",buffer);
1366     ok( r == ERROR_SUCCESS, "format failed\n");
1367
1368     r = MsiRecordSetString(hrec, 0, "{[1{{b{o}o}}]}");
1369     sz = sizeof buffer;
1370     r = MsiFormatRecord(0, hrec, buffer, &sz);
1371     ok( sz == 14, "size wrong\n");
1372     ok( 0 == strcmp(buffer,"{[1{{b{o}o}}]}"), "wrong output %s\n",buffer);
1373     ok( r == ERROR_SUCCESS, "format failed\n");
1374
1375     r = MsiRecordSetString(hrec, 0, "{ {[1]}");
1376     r = MsiRecordSetString(hrec, 1, "hoo");
1377     sz = sizeof buffer;
1378     r = MsiFormatRecord(0, hrec, buffer, &sz);
1379     ok( sz == 5, "size wrong\n");
1380     ok( 0 == strcmp(buffer," {hoo"), "wrong output %s\n",buffer);
1381     ok( r == ERROR_SUCCESS, "format failed\n");
1382
1383     /* {} inside a substitution does strange things... */
1384     r = MsiRecordSetString(hrec, 0, "[[1]{}]");
1385     r = MsiRecordSetString(hrec, 1, "2");
1386     sz = sizeof buffer;
1387     r = MsiFormatRecord(0, hrec, buffer, &sz);
1388     ok( sz == 5, "size wrong\n");
1389     ok( 0 == strcmp(buffer,"[[1]]"), "wrong output %s\n",buffer);
1390     ok( r == ERROR_SUCCESS, "format failed\n");
1391
1392     r = MsiRecordSetString(hrec, 0, "[[1]{}[1]]");
1393     r = MsiRecordSetString(hrec, 1, "2");
1394     sz = sizeof buffer;
1395     r = MsiFormatRecord(0, hrec, buffer, &sz);
1396     ok( sz == 6, "size wrong\n");
1397     ok( 0 == strcmp(buffer,"[[1]2]"), "wrong output %s\n",buffer);
1398     ok( r == ERROR_SUCCESS, "format failed\n");
1399
1400     r = MsiRecordSetString(hrec, 0, "[a[1]b[1]c{}d[1]e]");
1401     r = MsiRecordSetString(hrec, 1, "2");
1402     sz = sizeof buffer;
1403     r = MsiFormatRecord(0, hrec, buffer, &sz);
1404     ok( sz == 14, "size wrong\n");
1405     ok( 0 == strcmp(buffer,"[a[1]b[1]cd2e]"), "wrong output %s\n",buffer);
1406     ok( r == ERROR_SUCCESS, "format failed\n");
1407
1408     r = MsiRecordSetString(hrec, 0, "[a[1]b");
1409     r = MsiRecordSetString(hrec, 1, "2");
1410     sz = sizeof buffer;
1411     r = MsiFormatRecord(0, hrec, buffer, &sz);
1412     ok( sz == 6, "size wrong\n");
1413     ok( 0 == strcmp(buffer,"[a[1]b"), "wrong output %s\n",buffer);
1414     ok( r == ERROR_SUCCESS, "format failed\n");
1415
1416     r = MsiRecordSetString(hrec, 0, "a[1]b]");
1417     r = MsiRecordSetString(hrec, 1, "2");
1418     sz = sizeof buffer;
1419     r = MsiFormatRecord(0, hrec, buffer, &sz);
1420     ok( sz == 4, "size wrong\n");
1421     ok( 0 == strcmp(buffer,"a2b]"), "wrong output %s\n",buffer);
1422     ok( r == ERROR_SUCCESS, "format failed\n");
1423
1424     r = MsiRecordSetString(hrec, 0, "]a[1]b");
1425     r = MsiRecordSetString(hrec, 1, "2");
1426     sz = sizeof buffer;
1427     r = MsiFormatRecord(0, hrec, buffer, &sz);
1428     ok( sz == 4, "size wrong\n");
1429     ok( 0 == strcmp(buffer,"]a2b"), "wrong output %s\n",buffer);
1430     ok( r == ERROR_SUCCESS, "format failed\n");
1431
1432     r = MsiRecordSetString(hrec, 0, "]a[1]b");
1433     r = MsiRecordSetString(hrec, 1, "2");
1434     sz = sizeof buffer;
1435     r = MsiFormatRecord(0, hrec, buffer, &sz);
1436     ok( sz == 4, "size wrong\n");
1437     ok( 0 == strcmp(buffer,"]a2b"), "wrong output %s\n",buffer);
1438     ok( r == ERROR_SUCCESS, "format failed\n");
1439
1440     r = MsiRecordSetString(hrec, 0, "\\[1]");
1441     r = MsiRecordSetString(hrec, 1, "2");
1442     sz = sizeof buffer;
1443     r = MsiFormatRecord(0, hrec, buffer, &sz);
1444     ok( sz == 2, "size wrong\n");
1445     ok( 0 == strcmp(buffer,"\\2"), "wrong output %s\n",buffer);
1446     ok( r == ERROR_SUCCESS, "format failed\n");
1447
1448     r = MsiRecordSetString(hrec, 0, "\\{[1]}");
1449     r = MsiRecordSetString(hrec, 1, "2");
1450     sz = sizeof buffer;
1451     r = MsiFormatRecord(0, hrec, buffer, &sz);
1452     ok( sz == 2, "size wrong\n");
1453     ok( 0 == strcmp(buffer,"\\2"), "wrong output %s\n",buffer);
1454     ok( r == ERROR_SUCCESS, "format failed\n");
1455
1456     r = MsiRecordSetString(hrec, 0, "a{b[1]c}d");
1457     r = MsiRecordSetString(hrec, 1, NULL);
1458     sz = sizeof buffer;
1459     r = MsiFormatRecord(0, hrec, buffer, &sz);
1460     ok( sz == 2, "size wrong\n");
1461     ok( 0 == strcmp(buffer,"ad"), "wrong output %s\n",buffer);
1462     ok( r == ERROR_SUCCESS, "format failed\n");
1463
1464     r = MsiRecordSetString(hrec, 0, "{a[0]b}");
1465     r = MsiRecordSetString(hrec, 1, "foo");
1466     sz = sizeof buffer;
1467     r = MsiFormatRecord(0, hrec, buffer, &sz);
1468     ok( sz == 9, "size wrong\n");
1469     ok( 0 == strcmp(buffer,"a{a[0]b}b"), "wrong output %s\n",buffer);
1470     ok( r == ERROR_SUCCESS, "format failed\n");
1471
1472     r = MsiRecordSetString(hrec, 0, "[foo]");
1473     sz = sizeof buffer;
1474     r = MsiFormatRecord(0, hrec, buffer, &sz);
1475     ok( sz == 5, "size wrong\n");
1476     ok( 0 == strcmp(buffer,"[foo]"), "wrong output %s\n",buffer);
1477     ok( r == ERROR_SUCCESS, "format failed\n");
1478
1479     r = MsiRecordSetString(hrec, 0, "{[1][-1][1]}");
1480     r = MsiRecordSetString(hrec, 1, "foo");
1481     sz = sizeof buffer;
1482     r = MsiFormatRecord(0, hrec, buffer, &sz);
1483     ok( sz == 12, "size wrong\n");
1484     ok( 0 == strcmp(buffer,"{foo[-1]foo}"), "wrong output %s\n",buffer);
1485     ok( r == ERROR_SUCCESS, "format failed\n");
1486
1487     /* nested braces */
1488     sz = sizeof buffer;
1489     MsiRecordSetString(hrec, 0, "{abcd}");
1490     r = MsiFormatRecord(0, hrec, buffer, &sz);
1491     ok( r == ERROR_SUCCESS, "format failed\n");
1492     ok( sz == 6, "size wrong(%li)\n",sz);
1493     ok( 0 == strcmp(buffer,"{abcd}"), "wrong output (%s)\n",buffer);
1494
1495     sz = sizeof buffer;
1496     MsiRecordSetString(hrec, 0, "{a[one]bc[two]de[one]f}");
1497     r = MsiFormatRecord(0, hrec, buffer, &sz);
1498     ok( r == ERROR_SUCCESS, "format failed\n");
1499     ok( sz == 23, "size wrong(%li)\n",sz);
1500     ok( 0 == strcmp(buffer,"{a[one]bc[two]de[one]f}"), "wrong output (%s)\n",buffer);
1501
1502     sz = sizeof buffer;
1503     MsiRecordSetString(hrec, 0, "{a[one]bc[bad]de[two]f}");
1504     r = MsiFormatRecord(0, hrec, buffer, &sz);
1505     ok( r == ERROR_SUCCESS, "format failed\n");
1506     ok( sz == 23, "size wrong(%li)\n",sz);
1507     ok( 0 == strcmp(buffer,"{a[one]bc[bad]de[two]f}"), "wrong output (%s)\n",buffer);
1508
1509     sz = sizeof buffer;
1510     MsiRecordSetString(hrec, 0, "{[bad]}");
1511     r = MsiFormatRecord(0, hrec, buffer, &sz);
1512     ok( r == ERROR_SUCCESS, "format failed\n");
1513     ok( sz == 7, "size wrong(%li)\n",sz);
1514     ok( 0 == strcmp(buffer,"{[bad]}"), "wrong output (%s)\n",buffer);
1515
1516     sz = sizeof buffer;
1517     MsiRecordSetString(hrec, 0, "{abc{d[one]ef}"); /* missing final brace */
1518     r = MsiFormatRecord(0, hrec, buffer, &sz);
1519     ok( r == ERROR_SUCCESS, "format failed\n");
1520     ok( sz == 14, "size wrong(%li)\n",sz);
1521     ok( 0 == strcmp(buffer,"{abc{d[one]ef}"), "wrong output (%s)\n",buffer);
1522
1523     sz = sizeof buffer;
1524     MsiRecordSetString(hrec, 0, "{abc{d[one]ef}}");
1525     r = MsiFormatRecord(0, hrec, buffer, &sz);
1526     ok( r == ERROR_SUCCESS, "format failed\n");
1527     ok( sz == 15, "size wrong(%li)\n",sz);
1528     ok( 0 == strcmp(buffer,"{abc{d[one]ef}}"), "wrong output (%s)\n",buffer);
1529
1530     sz = sizeof buffer;
1531     MsiRecordSetString(hrec, 0, "{abc}{{def}hi{j[one]k}}");
1532     r = MsiFormatRecord(0, hrec, buffer, &sz);
1533     ok( r == ERROR_SUCCESS, "format failed\n");
1534     todo_wine
1535     {
1536         ok( sz == 5, "size wrong(%li)\n",sz);
1537         ok( 0 == strcmp(buffer,"{abc}"), "wrong output (%s)\n",buffer);
1538     }
1539
1540     sz = sizeof buffer;
1541     MsiRecordSetString(hrec, 0, "{{def}hi{j[one]k}}");
1542     r = MsiFormatRecord(0, hrec, buffer, &sz);
1543     ok( r == ERROR_SUCCESS, "format failed\n");
1544     todo_wine
1545     {
1546         ok( sz == 0, "size wrong(%li)\n",sz);
1547         ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
1548     }
1549
1550     sz = sizeof buffer;
1551     MsiRecordSetString(hrec, 0, "{{def}hi{jk}}");
1552     r = MsiFormatRecord(0, hrec, buffer, &sz);
1553     ok( r == ERROR_SUCCESS, "format failed\n");
1554     todo_wine
1555     {
1556         ok( sz == 0, "size wrong(%li)\n",sz);
1557         ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
1558     }
1559
1560     sz = sizeof buffer;
1561     MsiRecordSetString(hrec, 0, "{{{def}}hi{jk}}");
1562     r = MsiFormatRecord(0, hrec, buffer, &sz);
1563     ok( r == ERROR_SUCCESS, "format failed\n");
1564     todo_wine
1565     {
1566         ok( sz == 7, "size wrong(%li)\n",sz);
1567         ok( 0 == strcmp(buffer,"hi{jk}}"), "wrong output (%s)\n",buffer);
1568     }
1569
1570     sz = sizeof buffer;
1571     MsiRecordSetString(hrec, 0, "{{def}hi{{jk}}}");
1572     r = MsiFormatRecord(0, hrec, buffer, &sz);
1573     ok( r == ERROR_SUCCESS, "format failed\n");
1574     todo_wine
1575     {
1576         ok( sz == 1, "size wrong(%li)\n",sz);
1577         ok( 0 == strcmp(buffer,"}"), "wrong output (%s)\n",buffer);
1578     }
1579
1580     sz = sizeof buffer;
1581     MsiRecordSetString(hrec, 0, "{{def}{jk}}");
1582     r = MsiFormatRecord(0, hrec, buffer, &sz);
1583     ok( r == ERROR_SUCCESS, "format failed\n");
1584     todo_wine
1585     {
1586         ok( sz == 0, "size wrong(%li)\n",sz);
1587         ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
1588     }
1589
1590     sz = sizeof buffer;
1591     MsiRecordSetString(hrec, 0, "{{def}}");
1592     r = MsiFormatRecord(0, hrec, buffer, &sz);
1593     ok( r == ERROR_SUCCESS, "format failed\n");
1594     todo_wine
1595     {
1596         ok( sz == 0, "size wrong(%li)\n",sz);
1597         ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
1598     }
1599
1600     sz = sizeof buffer;
1601     MsiRecordSetString(hrec, 0, "{a{b}c}");
1602     r = MsiFormatRecord(0, hrec, buffer, &sz);
1603     ok( r == ERROR_SUCCESS, "format failed\n");
1604     ok( sz == 7, "size wrong(%li)\n",sz);
1605     ok( 0 == strcmp(buffer,"{a{b}c}"), "wrong output (%s)\n",buffer);
1606
1607     sz = sizeof buffer;
1608     MsiRecordSetString(hrec, 0, "{a{b}}");
1609     r = MsiFormatRecord(0, hrec, buffer, &sz);
1610     ok( r == ERROR_SUCCESS, "format failed\n");
1611     ok( sz == 6, "size wrong(%li)\n",sz);
1612     ok( 0 == strcmp(buffer,"{a{b}}"), "wrong output (%s)\n",buffer);
1613
1614     sz = sizeof buffer;
1615     MsiRecordSetString(hrec, 0, "{{b}c}");
1616     r = MsiFormatRecord(0, hrec, buffer, &sz);
1617     ok( r == ERROR_SUCCESS, "format failed\n");
1618     ok( sz == 6, "size wrong(%li)\n",sz);
1619     ok( 0 == strcmp(buffer,"{{b}c}"), "wrong output (%s)\n",buffer);
1620
1621     sz = sizeof buffer;
1622     MsiRecordSetString(hrec, 0, "{{{{}}}}");
1623     r = MsiFormatRecord(0, hrec, buffer, &sz);
1624     ok( r == ERROR_SUCCESS, "format failed\n");
1625     todo_wine
1626     {
1627         ok( sz == 2, "size wrong(%li)\n",sz);
1628         ok( 0 == strcmp(buffer,"}}"), "wrong output (%s)\n",buffer);
1629     }
1630
1631     MsiCloseHandle( hrec );
1632 }
1633
1634 static void test_formatrecord_package(void)
1635 {
1636     static const CHAR filename[] = "winetest.msi";
1637     char buffer[100];
1638     MSIHANDLE hrec;
1639     MSIHANDLE package;
1640     UINT r;
1641     DWORD sz=100;
1642
1643     package = helper_createpackage( filename );
1644     ok(package!=0, "Unable to create package\n");
1645
1646     hrec = MsiCreateRecord(12);
1647     ok( hrec, "failed to create record\n");
1648
1649     r = MsiFormatRecord(package, 0, NULL, NULL );
1650     ok( r == ERROR_INVALID_HANDLE, "wrong error\n");
1651
1652     r = MsiFormatRecord(package, hrec, NULL, NULL );
1653     ok( r == ERROR_SUCCESS, "format failed\n");
1654
1655     r = MsiRecordSetString(hrec,0,NULL);
1656     r = MsiRecordSetString(hrec,1,NULL);
1657     r = MsiRecordSetString(hrec,2,NULL);
1658     r = MsiRecordSetString(hrec,3,NULL);
1659     r = MsiRecordSetString(hrec,4,NULL);
1660     r = MsiRecordSetString(hrec,5,NULL);
1661     r = MsiRecordSetString(hrec,6,NULL);
1662     r = MsiRecordSetString(hrec,7,NULL);
1663     r = MsiRecordSetString(hrec,8,NULL);
1664     r = MsiRecordSetString(hrec,9,NULL);
1665     r = MsiRecordSetString(hrec,10,NULL);
1666     r = MsiRecordSetString(hrec,11,NULL);
1667     r = MsiRecordSetString(hrec,12,NULL);
1668     ok( r == ERROR_SUCCESS, "set string failed\n");
1669
1670     sz = sizeof buffer;
1671     r = MsiFormatRecord(package, hrec, buffer, &sz);
1672     ok( r == ERROR_SUCCESS, "format failed with empty buffer (%i)\n",r);
1673     ok( sz == 51, "size wrong (%li)\n",sz);
1674     ok( 0 == strcmp(buffer,"1:  2:  3:  4:  5:  6:  7:  8:  9:  10:  11:  12:  "), "wrong output(%s)\n",buffer);
1675
1676     r = MsiSetProperty(package, "prop", "val");
1677     ok( r == ERROR_SUCCESS, "failed to set propertY: %d\n", r);
1678
1679     r = MsiRecordSetString(hrec, 0, NULL);
1680     r = MsiRecordSetString(hrec, 1, "[2]");
1681     r = MsiRecordSetString(hrec, 2, "stuff");
1682     r = MsiRecordSetString(hrec, 3, "prop");
1683     r = MsiRecordSetString(hrec, 4, "[prop]");
1684     r = MsiRecordSetString(hrec, 5, "[noprop]");
1685     sz = sizeof buffer;
1686     r = MsiFormatRecord(package, hrec, buffer, &sz);
1687     ok( r == ERROR_SUCCESS, "format failed with empty buffer (%i)\n",r);
1688     todo_wine
1689     {
1690         ok( sz == 66, "size wrong (%li)\n",sz);
1691         ok( 0 == strcmp(buffer,"1: [2] 2: stuff 3: prop 4: val 5:  6:  7:  8:  9:  10:  11:  12:  "), "wrong output(%s)\n",buffer);
1692     }
1693
1694     /* now put play games with escaping */
1695     r = MsiRecordSetString(hrec, 0, "[1] [2] [\\3asdf]");
1696     r = MsiRecordSetString(hrec, 1, "boo");
1697     r = MsiRecordSetString(hrec, 2, "hoo");
1698     ok( r == ERROR_SUCCESS, "set string failed\n");
1699     sz = sizeof buffer;
1700     r = MsiFormatRecord(package, hrec, buffer, &sz);
1701     ok( r == ERROR_SUCCESS, "format failed\n");
1702     ok( sz == 9, "size wrong(%li)\n",sz);
1703     ok( 0 == strcmp(buffer,"boo hoo 3"), "wrong output (%s)\n",buffer);
1704
1705     r = MsiRecordSetString(hrec, 0, "[1] [2] [\\x]");
1706     r = MsiRecordSetString(hrec, 1, "boo");
1707     r = MsiRecordSetString(hrec, 2, "hoo");
1708     ok( r == ERROR_SUCCESS, "set string failed\n");
1709     sz = sizeof buffer;
1710     r = MsiFormatRecord(package, hrec, buffer, &sz);
1711     ok( r == ERROR_SUCCESS, "format failed\n");
1712     ok( sz == 9, "size wrong(%li)\n",sz);
1713     ok( 0 == strcmp(buffer,"boo hoo x"), "wrong output (%s)\n",buffer);
1714
1715     MsiRecordSetString(hrec, 0, "[\\x]");
1716     sz = sizeof buffer;
1717     r = MsiFormatRecord(package, hrec, buffer, &sz);
1718     ok( r == ERROR_SUCCESS, "format failed\n");
1719     ok( sz == 1, "size wrong: %ld\n", sz);
1720     ok( 0 == strcmp(buffer,"x"), "wrong output: %s\n", buffer);
1721
1722     MsiRecordSetString(hrec, 0, "{\\x}");
1723     sz = sizeof buffer;
1724     r = MsiFormatRecord(package, hrec, buffer, &sz);
1725     ok( r == ERROR_SUCCESS, "format failed\n");
1726     ok( sz == 4, "size wrong: %ld\n", sz);
1727     ok( 0 == strcmp(buffer,"{\\x}"), "wrong output: %s\n", buffer);
1728
1729     MsiRecordSetString(hrec, 0, "[abc\\x]");
1730     sz = sizeof buffer;
1731     r = MsiFormatRecord(package, hrec, buffer, &sz);
1732     ok( r == ERROR_SUCCESS, "format failed\n");
1733     ok( sz == 0, "size wrong: %ld\n", sz);
1734     ok( 0 == strcmp(buffer,""), "wrong output: %s\n", buffer);
1735
1736     MsiRecordSetString(hrec, 0, "[abc\\xdef]");
1737     sz = sizeof buffer;
1738     r = MsiFormatRecord(package, hrec, buffer, &sz);
1739     ok( r == ERROR_SUCCESS, "format failed\n");
1740     ok( sz == 0, "size wrong: %ld\n", sz);
1741     ok( 0 == strcmp(buffer,""), "wrong output: %s\n", buffer);
1742
1743     MsiRecordSetString(hrec, 0, "[\\[]Bracket Text[\\]]");
1744     sz = sizeof buffer;
1745     r = MsiFormatRecord(package, hrec, buffer, &sz);
1746     ok( r == ERROR_SUCCESS, "format failed\n");
1747     ok( sz == 14, "size wrong: %ld\n", sz);
1748     ok( 0 == strcmp(buffer,"[Bracket Text]"), "wrong output: %s\n", buffer);
1749
1750     /* null characters */
1751     r = MsiRecordSetString(hrec, 0, "[1] [~] [2]");
1752     r = MsiRecordSetString(hrec, 1, "boo");
1753     r = MsiRecordSetString(hrec, 2, "hoo");
1754     ok( r == ERROR_SUCCESS, "set string failed\n");
1755     sz = sizeof buffer;
1756     r = MsiFormatRecord(package, hrec, buffer, &sz);
1757     ok( r == ERROR_SUCCESS, "format failed\n");
1758     ok( sz == 9, "size wrong\n");
1759     ok( 0 == strcmp(buffer,"boo "), "wrong output\n");
1760
1761     /* properties */
1762     r = MsiSetProperty(package,"dummy","Bork");
1763     ok( r == ERROR_SUCCESS, "set property failed\n");
1764     r = MsiRecordSetString(hrec, 0, "[1] [dummy] [2]");
1765     r = MsiRecordSetString(hrec, 1, "boo");
1766     r = MsiRecordSetString(hrec, 2, "hoo");
1767     ok( r == ERROR_SUCCESS, "set string failed\n");
1768     sz = sizeof buffer;
1769     r = MsiFormatRecord(package, hrec, buffer, &sz);
1770     ok( r == ERROR_SUCCESS, "format failed\n");
1771     ok( sz == 12, "size wrong\n");
1772     ok( 0 == strcmp(buffer,"boo Bork hoo"), "wrong output\n");
1773
1774     r = MsiRecordSetString(hrec, 0, "[1] [invalid] [2]");
1775     r = MsiRecordSetString(hrec, 1, "boo");
1776     r = MsiRecordSetString(hrec, 2, "hoo");
1777     ok( r == ERROR_SUCCESS, "set string failed\n");
1778     sz = sizeof buffer;
1779     r = MsiFormatRecord(package, hrec, buffer, &sz);
1780     ok( r == ERROR_SUCCESS, "format failed\n");
1781     ok( sz == 8, "size wrong\n");
1782     ok( 0 == strcmp(buffer,"boo  hoo"), "wrong output\n");
1783
1784
1785     /* nesting tests */
1786     r = MsiSetProperty(package,"dummya","foo");
1787     r = MsiSetProperty(package,"dummyb","baa");
1788     r = MsiSetProperty(package,"adummyc","whoa");
1789     ok( r == ERROR_SUCCESS, "set property failed\n");
1790     r = MsiRecordSetString(hrec, 0, "[dummy[1]] [dummy[2]] [[1]dummy[3]]");
1791     r = MsiRecordSetString(hrec, 1, "a");
1792     r = MsiRecordSetString(hrec, 2, "b");
1793     r = MsiRecordSetString(hrec, 3, "c");
1794     ok( r == ERROR_SUCCESS, "set string failed\n");
1795     sz = sizeof buffer;
1796     r = MsiFormatRecord(package, hrec, buffer, &sz);
1797     ok( r == ERROR_SUCCESS, "format failed\n");
1798     ok( sz == 12, "size wrong(%li)\n",sz);
1799     ok( 0 == strcmp(buffer,"foo baa whoa"), "wrong output (%s)\n",buffer);
1800
1801
1802     r = MsiSetProperty(package,"dummya","1");
1803     r = MsiSetProperty(package,"dummyb","[2]");
1804     ok( r == ERROR_SUCCESS, "set property failed\n");
1805     r = MsiRecordSetString(hrec, 0, "[dummya] [[dummya]] [dummyb]");
1806     r = MsiRecordSetString(hrec, 1, "aaa");
1807     r = MsiRecordSetString(hrec, 2, "bbb");
1808     r = MsiRecordSetString(hrec, 3, "ccc");
1809     ok( r == ERROR_SUCCESS, "set string failed\n");
1810     sz = sizeof buffer;
1811     r = MsiFormatRecord(package, hrec, buffer, &sz);
1812     ok( r == ERROR_SUCCESS, "format failed\n");
1813     ok( sz == 9, "size wrong(%li)\n",sz);
1814     ok( 0 == strcmp(buffer,"1 [1] [2]"), "wrong output (%s)\n",buffer);
1815
1816     r = MsiSetProperty(package,"dummya","1");
1817     r = MsiSetProperty(package,"dummyb","a");
1818     r = MsiSetProperty(package,"dummyc","\\blath");
1819     r = MsiSetProperty(package,"dummyd","[\\blath]");
1820     ok( r == ERROR_SUCCESS, "set property failed\n");
1821     r = MsiRecordSetString(hrec, 0, "[dummyc] [[dummyc]] [dummy[dummyb]]");
1822     r = MsiRecordSetString(hrec, 1, "aaa");
1823     r = MsiRecordSetString(hrec, 2, "bbb");
1824     r = MsiRecordSetString(hrec, 3, "ccc");
1825     ok( r == ERROR_SUCCESS, "set string failed\n");
1826     sz = sizeof buffer;
1827     r = MsiFormatRecord(package, hrec, buffer, &sz);
1828     ok( r == ERROR_SUCCESS, "format failed\n");
1829     ok( sz == 10, "size wrong(%li)\n",sz);
1830     ok( 0 == strcmp(buffer,"\\blath b 1"), "wrong output (%s)\n",buffer);
1831
1832     r = MsiRecordSetString(hrec, 0, "[1] [2] [[\\3asdf]]");
1833     r = MsiRecordSetString(hrec, 1, "boo");
1834     r = MsiRecordSetString(hrec, 2, "hoo");
1835     r = MsiRecordSetString(hrec, 3, "yeah");
1836     ok( r == ERROR_SUCCESS, "set string failed\n");
1837     sz = sizeof buffer;
1838     r = MsiFormatRecord(package, hrec, buffer, &sz);
1839     ok( r == ERROR_SUCCESS, "format failed\n");
1840     ok( sz == 11, "size wrong(%li)\n",sz);
1841     ok( 0 == strcmp(buffer,"boo hoo [3]"), "wrong output (%s)\n",buffer);
1842
1843     r = MsiRecordSetString(hrec, 0, "[1] [2] [[3]]");
1844     r = MsiRecordSetString(hrec, 1, "boo");
1845     r = MsiRecordSetString(hrec, 2, "hoo");
1846     r = MsiRecordSetString(hrec, 3, "\\help");
1847     ok( r == ERROR_SUCCESS, "set string failed\n");
1848     sz = sizeof buffer;
1849     r = MsiFormatRecord(package, hrec, buffer, &sz);
1850     ok( r == ERROR_SUCCESS, "format failed\n");
1851     ok( sz == 9, "size wrong(%li)\n",sz);
1852     ok( 0 == strcmp(buffer,"boo hoo h"), "wrong output (%s)\n",buffer);
1853
1854     /* nested properties */
1855     MsiSetProperty(package, "PropA", "surprise");
1856     MsiSetProperty(package, "PropB", "[PropA]");
1857     MsiSetProperty(package, "PropC", "[PropB]");
1858     sz = sizeof buffer;
1859     MsiRecordSetString(hrec, 0, "[PropC]");
1860     r = MsiFormatRecord(package, hrec, buffer, &sz);
1861     ok( r == ERROR_SUCCESS, "format failed\n");
1862     ok( sz == 7, "size wrong(%li)\n",sz);
1863     ok( 0 == strcmp(buffer,"[PropB]"), "wrong output (%s)\n",buffer);
1864
1865     MsiSetProperty(package, "PropA", "surprise");
1866     MsiSetProperty(package, "PropB", "PropA");
1867     MsiSetProperty(package, "PropC", "PropB");
1868     sz = sizeof buffer;
1869     MsiRecordSetString(hrec, 0, "[PropC]");
1870     r = MsiFormatRecord(package, hrec, buffer, &sz);
1871     ok( r == ERROR_SUCCESS, "format failed\n");
1872     ok( sz == 5, "size wrong(%li)\n",sz);
1873     ok( 0 == strcmp(buffer,"PropB"), "wrong output (%s)\n",buffer);
1874
1875     MsiSetProperty(package, "PropA", "surprise");
1876     MsiSetProperty(package, "PropB", "[PropA]");
1877     MsiSetProperty(package, "PropC", "[PropB]");
1878     sz = sizeof buffer;
1879     MsiRecordSetString(hrec, 0, "[[PropC]]");
1880     r = MsiFormatRecord(package, hrec, buffer, &sz);
1881     ok( r == ERROR_SUCCESS, "format failed\n");
1882     ok( sz == 0, "size wrong(%li)\n",sz);
1883     ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
1884
1885     MsiSetProperty(package, "PropA", "surprise");
1886     MsiSetProperty(package, "PropB", "[PropA]");
1887     MsiSetProperty(package, "PropC", "PropB");
1888     sz = sizeof buffer;
1889     MsiRecordSetString(hrec, 0, "[[PropC]]");
1890     r = MsiFormatRecord(package, hrec, buffer, &sz);
1891     ok( r == ERROR_SUCCESS, "format failed\n");
1892     ok( sz == 7, "size wrong(%li)\n",sz);
1893     ok( 0 == strcmp(buffer,"[PropA]"), "wrong output (%s)\n",buffer);
1894
1895     MsiSetProperty(package, "PropA", "surprise");
1896     MsiSetProperty(package, "PropB", "PropA");
1897     MsiSetProperty(package, "PropC", "PropB");
1898     sz = sizeof buffer;
1899     MsiRecordSetString(hrec, 0, "[[PropC]]");
1900     r = MsiFormatRecord(package, hrec, buffer, &sz);
1901     ok( r == ERROR_SUCCESS, "format failed\n");
1902     ok( sz == 5, "size wrong(%li)\n",sz);
1903     ok( 0 == strcmp(buffer,"PropA"), "wrong output (%s)\n",buffer);
1904
1905     MsiSetProperty(package, "PropA", "surprise");
1906     MsiSetProperty(package, "PropB", "PropA");
1907     MsiSetProperty(package, "PropC", "PropB");
1908     sz = sizeof buffer;
1909     MsiRecordSetString(hrec, 0, "[[[PropC]]]");
1910     r = MsiFormatRecord(package, hrec, buffer, &sz);
1911     ok( r == ERROR_SUCCESS, "format failed\n");
1912     ok( sz == 8, "size wrong(%li)\n",sz);
1913     ok( 0 == strcmp(buffer,"surprise"), "wrong output (%s)\n",buffer);
1914
1915     /* properties inside braces */
1916     sz = sizeof buffer;
1917     MsiRecordSetString(hrec, 0, "{abcd}");
1918     r = MsiFormatRecord(package, hrec, buffer, &sz);
1919     ok( r == ERROR_SUCCESS, "format failed\n");
1920     ok( sz == 6, "size wrong(%li)\n",sz);
1921     ok( 0 == strcmp(buffer,"{abcd}"), "wrong output (%s)\n",buffer);
1922
1923     MsiSetProperty(package, "one", "mercury");
1924     MsiSetProperty(package, "two", "venus");
1925     sz = sizeof buffer;
1926     MsiRecordSetString(hrec, 0, "{a[one]bc[two]de[one]f}");
1927     r = MsiFormatRecord(package, hrec, buffer, &sz);
1928     ok( r == ERROR_SUCCESS, "format failed\n");
1929     ok( sz == 25, "size wrong(%li)\n",sz);
1930     ok( 0 == strcmp(buffer,"amercurybcvenusdemercuryf"), "wrong output (%s)\n",buffer);
1931
1932     MsiSetProperty(package, "one", "mercury");
1933     MsiSetProperty(package, "two", "venus");
1934     MsiSetProperty(package, "bad", "");
1935     sz = sizeof buffer;
1936     MsiRecordSetString(hrec, 0, "{a[one]bc[bad]de[two]f}");
1937     r = MsiFormatRecord(package, hrec, buffer, &sz);
1938     ok( r == ERROR_SUCCESS, "format failed\n");
1939     todo_wine
1940     {
1941         ok( sz == 0, "size wrong(%li)\n",sz);
1942         ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
1943     }
1944
1945     MsiSetProperty(package, "bad", "");
1946     sz = sizeof buffer;
1947     MsiRecordSetString(hrec, 0, "{[bad]}");
1948     r = MsiFormatRecord(package, hrec, buffer, &sz);
1949     ok( r == ERROR_SUCCESS, "format failed\n");
1950     ok( sz == 0, "size wrong(%li)\n",sz);
1951     ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
1952
1953     MsiSetProperty(package, "one", "mercury");
1954     sz = sizeof buffer;
1955     MsiRecordSetString(hrec, 0, "{abc{d[one]ef}"); /* missing final brace */
1956     r = MsiFormatRecord(package, hrec, buffer, &sz);
1957     ok( r == ERROR_SUCCESS, "format failed\n");
1958     ok( sz == 14, "size wrong(%li)\n",sz);
1959     ok( 0 == strcmp(buffer,"abc{dmercuryef"), "wrong output (%s)\n",buffer);
1960
1961     MsiSetProperty(package, "one", "mercury");
1962     sz = sizeof buffer;
1963     MsiRecordSetString(hrec, 0, "{abc{d[one]ef}}");
1964     r = MsiFormatRecord(package, hrec, buffer, &sz);
1965     ok( r == ERROR_SUCCESS, "format failed\n");
1966     ok( sz == 15, "size wrong(%li)\n",sz);
1967     ok( 0 == strcmp(buffer,"abc{dmercuryef}"), "wrong output (%s)\n",buffer);
1968
1969     MsiSetProperty(package, "one", "mercury");
1970     sz = sizeof buffer;
1971     MsiRecordSetString(hrec, 0, "{abc}{{def}hi{j[one]k}}");
1972     r = MsiFormatRecord(package, hrec, buffer, &sz);
1973     ok( r == ERROR_SUCCESS, "format failed\n");
1974     todo_wine
1975     {
1976         ok( sz == 5, "size wrong(%li)\n",sz);
1977         ok( 0 == strcmp(buffer,"{abc}"), "wrong output (%s)\n",buffer);
1978     }
1979
1980     MsiSetProperty(package, "one", "mercury");
1981     sz = sizeof buffer;
1982     MsiRecordSetString(hrec, 0, "{{def}hi{j[one]k}}");
1983     r = MsiFormatRecord(package, hrec, buffer, &sz);
1984     ok( r == ERROR_SUCCESS, "format failed\n");
1985     todo_wine
1986     {
1987         ok( sz == 0, "size wrong(%li)\n",sz);
1988         ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
1989     }
1990
1991     MsiCloseHandle(hrec);
1992
1993     r = MsiCloseHandle(package);
1994     ok(r==ERROR_SUCCESS, "Unable to close package\n");
1995
1996     DeleteFile( filename );
1997 }
1998
1999 static void test_formatrecord_tables(void)
2000 {
2001     MSIHANDLE hdb, hpkg, hrec;
2002     CHAR buf[MAX_PATH];
2003     CHAR curr_dir[MAX_PATH];
2004     CHAR expected[MAX_PATH];
2005     DWORD size;
2006     UINT r;
2007
2008     GetCurrentDirectory( MAX_PATH, curr_dir );
2009
2010     hdb = create_package_db();
2011     ok ( hdb, "failed to create package database\n");
2012
2013     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
2014     ok( r == ERROR_SUCCESS, "cannot add directory: %d\n", r);
2015
2016     r = add_directory_entry( hdb, "'ReallyLongDir', 'TARGETDIR', "
2017                              "'I am a really long directory'" );
2018     ok( r == ERROR_SUCCESS, "cannot add directory: %d\n", r);
2019
2020     r = create_feature_table( hdb );
2021     ok( r == ERROR_SUCCESS, "cannot create Feature table: %d\n", r);
2022
2023     r = add_feature_entry( hdb, "'occipitofrontalis', '', '', '', 2, 1, '', 0" );
2024     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2025
2026     r = create_component_table( hdb );
2027     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r);
2028
2029     r = add_component_entry( hdb, "'frontal', '', 'TARGETDIR', 0, '', 'frontal_file'" );
2030     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r);
2031
2032     r = add_component_entry( hdb, "'parietal', '', 'TARGETDIR', 1, '', 'parietal_file'" );
2033     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r);
2034
2035     r = add_component_entry( hdb, "'temporal', '', 'ReallyLongDir', 0, '', 'temporal_file'" );
2036     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r);
2037
2038     r = create_feature_components_table( hdb );
2039     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r);
2040
2041     r = add_feature_components_entry( hdb, "'occipitofrontalis', 'frontal'" );
2042     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r);
2043
2044     r = add_feature_components_entry( hdb, "'occipitofrontalis', 'parietal'" );
2045     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r);
2046
2047     r = add_feature_components_entry( hdb, "'occipitofrontalis', 'temporal'" );
2048     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r);
2049
2050     r = create_file_table( hdb );
2051     ok( r == ERROR_SUCCESS, "cannot create File table: %d\n", r);
2052
2053     r = add_file_entry( hdb, "'frontal_file', 'frontal', 'frontal.txt', 0, '', '1033', 8192, 1" );
2054     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
2055
2056     r = add_file_entry( hdb, "'parietal_file', 'parietal', 'parietal.txt', 0, '', '1033', 8192, 1" );
2057     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
2058
2059     r = add_file_entry( hdb, "'temporal_file', 'temporal', 'temporal.txt', 0, '', '1033', 8192, 1" );
2060     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
2061
2062     r = create_custom_action_table( hdb );
2063     ok( r == ERROR_SUCCESS, "cannot create CustomAction table: %d\n", r);
2064
2065     r = add_custom_action_entry( hdb, "'MyCustom', 51, 'prop', '[!temporal_file]'" );
2066     ok( r == ERROR_SUCCESS, "cannt add custom action: %d\n", r);
2067
2068     r = add_custom_action_entry( hdb, "'EscapeIt1', 51, 'prop', '[\\[]Bracket Text[\\]]'" );
2069     ok( r == ERROR_SUCCESS, "cannt add custom action: %d\n", r);
2070
2071     r = add_custom_action_entry( hdb, "'EscapeIt2', 51, 'prop', '[\\xabcd]'" );
2072     ok( r == ERROR_SUCCESS, "cannt add custom action: %d\n", r);
2073
2074     r = add_custom_action_entry( hdb, "'EscapeIt3', 51, 'prop', '[abcd\\xefgh]'" );
2075     ok( r == ERROR_SUCCESS, "cannt add custom action: %d\n", r);
2076
2077     hpkg = package_from_db( hdb );
2078     ok( hpkg, "failed to create package\n");
2079
2080     MsiCloseHandle( hdb );
2081
2082     r = MsiSetPropertyA( hpkg, "imaprop", "ringer" );
2083     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2084
2085     hrec = MsiCreateRecord( 1 );
2086
2087     /* property doesn't exist */
2088     size = MAX_PATH;
2089     /*MsiRecordSetString( hrec, 0, "[1]" ); */
2090     MsiRecordSetString( hrec, 1, "[idontexist]" );
2091     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2092     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2093     ok( !lstrcmp( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2094
2095     /* property exists */
2096     size = MAX_PATH;
2097     MsiRecordSetString( hrec, 1, "[imaprop]" );
2098     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2099     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2100     ok( !lstrcmp( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2101
2102     /* environment variable doesn't exist */
2103     size = MAX_PATH;
2104     MsiRecordSetString( hrec, 1, "[%idontexist]" );
2105     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2106     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2107     ok( !lstrcmp( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2108
2109     /* environment variable exists */
2110     size = MAX_PATH;
2111     SetEnvironmentVariable( "crazyvar", "crazyval" );
2112     MsiRecordSetString( hrec, 1, "[%crazyvar]" );
2113     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2114     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2115     ok( !lstrcmp( buf, "1: crazyval " ), "Expected '1: crazyval ', got %s\n", buf );
2116
2117     /* file key before CostInitialize */
2118     size = MAX_PATH;
2119     MsiRecordSetString( hrec, 1, "[#frontal_file]" );
2120     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2121     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2122     ok( !lstrcmp( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2123
2124     r = MsiDoAction(hpkg, "CostInitialize");
2125     ok( r == ERROR_SUCCESS, "CostInitialize failed: %d\n", r);
2126
2127     r = MsiDoAction(hpkg, "FileCost");
2128     ok( r == ERROR_SUCCESS, "FileCost failed: %d\n", r);
2129
2130     r = MsiDoAction(hpkg, "CostFinalize");
2131     ok( r == ERROR_SUCCESS, "CostFinalize failed: %d\n", r);
2132
2133     /* frontal full file key */
2134     size = MAX_PATH;
2135     MsiRecordSetString( hrec, 1, "[#frontal_file]" );
2136     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2137     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2138     ok( !lstrcmp( buf, "1: C:\\frontal.txt " ), "Expected '1: C:\\frontal.txt ', got %s\n", buf);
2139
2140     /* frontal short file key */
2141     size = MAX_PATH;
2142     MsiRecordSetString( hrec, 1, "[!frontal_file]" );
2143     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2144     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2145     ok( !lstrcmp( buf, "1: C:\\frontal.txt " ), "Expected '1: C:\\frontal.txt ', got %s\n", buf);
2146
2147     /* temporal full file key */
2148     size = MAX_PATH;
2149     MsiRecordSetString( hrec, 1, "[#temporal_file]" );
2150     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2151     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2152     ok( !lstrcmp( buf, "1: C:\\I am a really long directory\\temporal.txt " ),
2153         "Expected '1: C:\\I am a really long directory\\temporal.txt ', got %s\n", buf);
2154
2155     /* temporal short file key */
2156     size = MAX_PATH;
2157     MsiRecordSetString( hrec, 1, "[!temporal_file]" );
2158     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2159     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2160     ok( !lstrcmp( buf, "1: C:\\I am a really long directory\\temporal.txt " ),
2161         "Expected '1: C:\\I am a really long directory\\temporal.txt ', got %s\n", buf);
2162
2163     /* custom action 51, files don't exist */
2164     r = MsiDoAction( hpkg, "MyCustom" );
2165     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2166
2167     size = MAX_PATH;
2168     r = MsiGetProperty( hpkg, "prop", buf, &size );
2169     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2170     ok( !lstrcmp( buf, "C:\\I am a really long directory\\temporal.txt" ),
2171         "Expected 'C:\\I am a really long directory\\temporal.txt', got %s\n", buf);
2172
2173     CreateDirectory( "C:\\I am a really long directory", NULL );
2174     create_test_file( "C:\\I am a really long directory\\temporal.txt" );
2175
2176     /* custom action 51, files exist */
2177     r = MsiDoAction( hpkg, "MyCustom" );
2178     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2179
2180     size = MAX_PATH;
2181     r = MsiGetProperty( hpkg, "prop", buf, &size );
2182     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2183     todo_wine
2184     {
2185         ok( !lstrcmp( buf, "C:\\I am a really long directory\\temporal.txt" ),
2186             "Expected 'C:\\I am a really long directory\\temporal.txt', got %s\n", buf);
2187     }
2188
2189     /* custom action 51, escaped text 1 */
2190     r = MsiDoAction( hpkg, "EscapeIt1" );
2191     ok( r == ERROR_SUCCESS, "EscapeIt failed: %d\n", r);
2192
2193     size = MAX_PATH;
2194     r = MsiGetProperty( hpkg, "prop", buf, &size );
2195     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2196     ok( !lstrcmp( buf, "[Bracket Text]" ), "Expected '[Bracket Text]', got %s\n", buf);
2197
2198     /* custom action 51, escaped text 2 */
2199     r = MsiDoAction( hpkg, "EscapeIt2" );
2200     ok( r == ERROR_SUCCESS, "EscapeIt failed: %d\n", r);
2201
2202     size = MAX_PATH;
2203     r = MsiGetProperty( hpkg, "prop", buf, &size );
2204     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2205     ok( !lstrcmp( buf, "x" ), "Expected 'x', got %s\n", buf);
2206
2207     /* custom action 51, escaped text 3 */
2208     r = MsiDoAction( hpkg, "EscapeIt3" );
2209     ok( r == ERROR_SUCCESS, "EscapeIt failed: %d\n", r);
2210
2211     size = MAX_PATH;
2212     r = MsiGetProperty( hpkg, "prop", buf, &size );
2213     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2214     ok( !lstrcmp( buf, "" ), "Expected '', got %s\n", buf);
2215
2216     /* component with INSTALLSTATE_LOCAL */
2217     size = MAX_PATH;
2218     MsiRecordSetString( hrec, 1, "[$temporal]" );
2219     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2220     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2221     ok( !lstrcmp( buf, "1: C:\\I am a really long directory\\ " ),
2222         "Expected '1: C:\\I am a really long directory\\ ', got %s\n", buf);
2223
2224     r = MsiSetComponentState( hpkg, "temporal", INSTALLSTATE_SOURCE );
2225     ok( r == ERROR_SUCCESS, "failed to set install state: %d\n", r);
2226
2227     /* component with INSTALLSTATE_SOURCE */
2228     lstrcpy( expected, "1: " );
2229     lstrcat( expected, curr_dir );
2230     lstrcat( expected, "\\ " );
2231     size = MAX_PATH;
2232     MsiRecordSetString( hrec, 1, "[$parietal]" );
2233     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2234     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2235     todo_wine
2236     {
2237         ok( !lstrcmp( buf, expected ), "Expected '%s', got %s\n", expected, buf);
2238     }
2239
2240     DeleteFile( "C:\\I am a really long directory\\temporal.txt" );
2241     RemoveDirectory( "C:\\I am a really long directory" );
2242
2243     MsiCloseHandle( hrec );
2244     MsiCloseHandle( hpkg );
2245     DeleteFile( msifile );
2246 }
2247
2248 static void test_processmessage(void)
2249 {
2250     static const CHAR filename[] = "winetest.msi";
2251     MSIHANDLE hrec;
2252     MSIHANDLE package;
2253     int r;
2254
2255     package = helper_createpackage( filename );
2256     ok(package!=0, "Unable to create package\n");
2257
2258     hrec = MsiCreateRecord(3);
2259     ok( hrec, "failed to create record\n");
2260
2261     r = MsiRecordSetString(hrec, 1, "");
2262     ok( r == ERROR_SUCCESS, "set string failed\n");
2263
2264     r = MsiProcessMessage(package, INSTALLMESSAGE_ACTIONSTART, hrec);
2265     ok( r == IDOK, "expected IDOK, got %i\n", r);
2266
2267     MsiCloseHandle(hrec);
2268     MsiCloseHandle(package);
2269
2270     DeleteFile(filename);
2271 }
2272
2273 START_TEST(format)
2274 {
2275     test_createpackage();
2276     test_formatrecord();
2277     test_formatrecord_package();
2278     test_formatrecord_tables();
2279     test_processmessage();
2280 }