msi: Add tests for MsiGetComponentPath.
[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",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(0);
392     ok( hrec, "failed to create record\n");
393
394     /* format an empty record on a record with no parameters */
395     sz = sizeof(buffer);
396     r = MsiFormatRecordA(0, hrec, buffer, &sz );
397     ok( r == ERROR_SUCCESS, "format failed\n");
398     ok( sz == 0, "size wrong\n");
399
400     MsiCloseHandle( hrec );
401
402     hrec = MsiCreateRecord(4);
403     ok( hrec, "failed to create record\n");
404
405     /* format an empty record */
406     r = MsiFormatRecord(0, hrec, NULL, NULL );
407     ok( r == ERROR_SUCCESS, "format failed\n");
408     buffer[0] = 'x';
409     buffer[1] = 0;
410     sz=0;
411     r = MsiFormatRecord(0, hrec, buffer+1, &sz);
412     ok( r == ERROR_MORE_DATA && buffer[0] == 'x', "format failed measuring with buffer\n");
413     ok( sz == 16, "size wrong\n");
414     sz=100;
415     r = MsiFormatRecord(0, hrec, buffer, &sz);
416     ok( r == ERROR_SUCCESS, "format failed with empty buffer\n");
417     ok( sz == 16, "size wrong\n");
418     ok( 0 == strcmp(buffer,"1:  2:  3:  4:  "), "wrong output\n");
419
420     r = MsiCloseHandle(hrec);
421     ok(r==ERROR_SUCCESS, "Unable to close record\n");
422
423     hrec = MsiCreateRecord(6);
424     ok( hrec, "failed to create record\n");
425
426     sz = 100;
427     buffer[0] = 'x';
428     buffer[1] = 0;
429     r = MsiFormatRecord(0, hrec, buffer, &sz);
430     ok( r == ERROR_SUCCESS, "format failed with empty buffer\n");
431     ok( sz == 24, "size wrong\n");
432     ok( 0 == strcmp(buffer,"1:  2:  3:  4:  5:  6:  "), "wrong output\n");
433
434
435     /* format a format string with everything else empty */
436     r = MsiRecordSetString(hrec, 0, "%1");
437     ok( r == ERROR_SUCCESS, "set string failed\n");
438     r = MsiFormatRecord(0, hrec, NULL, NULL );
439     ok( r == ERROR_SUCCESS, "format failed\n");
440     r = MsiFormatRecord(0, hrec, buffer, NULL);
441     ok( r == ERROR_INVALID_PARAMETER, "wrong error\n");
442
443     sz = 123;
444     r = MsiFormatRecord(0, hrec, NULL, &sz);
445     ok( r == ERROR_SUCCESS, "format failed with empty buffer\n");
446     ok( sz == 2, "size wrong (%i)\n",sz);
447     sz = sizeof buffer;
448     buffer[0] = 'x';
449     buffer[1] = 0;
450     r = MsiFormatRecord(0, hrec, buffer, &sz);
451     ok( r == ERROR_SUCCESS, "format failed with empty buffer\n");
452     ok( sz == 2, "size wrong\n");
453     ok( 0 == strcmp(buffer,"%1"), "wrong output\n");
454
455     /* make the buffer too small */
456     sz = 0;
457     buffer[0] = 'x';
458     buffer[1] = 0;
459     r = MsiFormatRecord(0, hrec, buffer, &sz);
460     ok( r == ERROR_MORE_DATA, "format failed with empty buffer\n");
461     ok( sz == 2, "size wrong\n");
462     ok( 0 == strcmp(buffer,"x"), "wrong output\n");
463
464     /* make the buffer a little bit bigger */
465     sz = 1;
466     buffer[0] = 'x';
467     buffer[1] = 0;
468     r = MsiFormatRecord(0, hrec, buffer, &sz);
469     ok( r == ERROR_MORE_DATA, "format failed with empty buffer\n");
470     ok( sz == 2, "size wrong\n");
471     ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
472
473     /* and again */
474     sz = 2;
475     buffer[0] = 'x';
476     buffer[1] = 0;
477     r = MsiFormatRecord(0, hrec, buffer, &sz);
478     ok( r == ERROR_MORE_DATA, "format failed with empty buffer\n");
479     ok( sz == 2, "size wrong\n");
480     ok( 0 == strcmp(buffer,"%"), "wrong output\n");
481
482     /* and again */
483     sz = 3;
484     buffer[0] = 'x';
485     buffer[1] = 0;
486     r = MsiFormatRecord(0, hrec, buffer, &sz);
487     ok( r == ERROR_SUCCESS, "format failed with empty buffer\n");
488     ok( sz == 2, "size wrong\n");
489     ok( 0 == strcmp(buffer,"%1"), "wrong output\n");
490
491     /* now try a real format string */
492     r = MsiRecordSetString(hrec, 0, "[1]");
493     ok( r == ERROR_SUCCESS, "set string failed\n");
494     sz = sizeof buffer;
495     r = MsiFormatRecord(0, hrec, buffer, &sz);
496     ok( r == ERROR_SUCCESS, "format failed\n");
497     ok( sz == 0, "size wrong\n");
498     ok( 0 == strcmp(buffer,""), "wrong output\n");
499
500     /* now put something in the first field */
501     r = MsiRecordSetString(hrec, 1, "boo 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     /* now put something in the first field */
510     r = MsiRecordSetString(hrec, 0, "[1] [2]");
511     r = MsiRecordSetString(hrec, 1, "boo");
512     r = MsiRecordSetString(hrec, 2, "hoo");
513     ok( r == ERROR_SUCCESS, "set string failed\n");
514     sz = sizeof buffer;
515     r = MsiFormatRecord(0, hrec, buffer, &sz);
516     ok( r == ERROR_SUCCESS, "format failed\n");
517     ok( sz == 7, "size wrong\n");
518     ok( 0 == strcmp(buffer,"boo hoo"), "wrong output\n");
519
520
521     /* empty string */
522     r = MsiRecordSetString(hrec, 0, "");
523     sz = sizeof buffer;
524     r = MsiFormatRecord(0, hrec, buffer, &sz);
525     ok( r == ERROR_SUCCESS, "format failed\n");
526     ok( sz == 30, "size wrong %i\n",sz);
527     ok( 0 == strcmp(buffer,"1: boo 2: hoo 3:  4:  5:  6:  "), 
528                     "wrong output(%s)\n",buffer);
529
530     /* play games with recursive lookups */
531     r = MsiRecordSetString(hrec, 0, "[[1]] [2]");
532     r = MsiRecordSetString(hrec, 1, "2");
533     r = MsiRecordSetString(hrec, 2, "hey");
534     ok( r == ERROR_SUCCESS, "set string failed\n");
535     sz = sizeof buffer;
536     r = MsiFormatRecord(0, hrec, buffer, &sz);
537     ok( r == ERROR_SUCCESS, "format failed\n");
538     ok( sz == 7, "size wrong,(%i)\n",sz);
539     ok( 0 == strcmp(buffer,"hey hey"), "wrong output (%s)\n",buffer);
540
541     r = MsiRecordSetString(hrec, 0, "[[1]] [2]");
542     r = MsiRecordSetString(hrec, 1, "[2]");
543     r = MsiRecordSetString(hrec, 2, "hey");
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 == 9, "size wrong,(%i)\n",sz);
549     ok( 0 == strcmp(buffer,"[[2]] hey"), "wrong output (%s)\n",buffer);
550
551     r = MsiRecordSetString(hrec, 0, "[[[3]]] [2]");
552     r = MsiRecordSetString(hrec, 1, "2");
553     r = MsiRecordSetString(hrec, 2, "hey");
554     r = MsiRecordSetString(hrec, 3, "1");
555     ok( r == ERROR_SUCCESS, "set string failed\n");
556     sz = sizeof buffer;
557     r = MsiFormatRecord(0, hrec, buffer, &sz);
558     ok( r == ERROR_SUCCESS, "format failed\n");
559     ok( sz == 7, "size wrong,(%i)\n",sz);
560     ok( 0 == strcmp(buffer,"hey hey"), "wrong output (%s)\n",buffer);
561
562     r = MsiCloseHandle(hrec);
563     ok(r==ERROR_SUCCESS, "Unable to close record\n");
564     hrec = MsiCreateRecord(12);
565     ok( hrec, "failed to create record\n");
566
567     r = MsiRecordSetString(hrec, 0, "[[3][1]] [2]");
568     r = MsiRecordSetString(hrec, 1, "2");
569     r = MsiRecordSetString(hrec, 2, "hey");
570     r = MsiRecordSetString(hrec, 3, "1");
571     r = MsiRecordSetString(hrec, 12, "big");
572     ok( r == ERROR_SUCCESS, "set string failed\n");
573     sz = sizeof buffer;
574     r = MsiFormatRecord(0, hrec, buffer, &sz);
575     ok( r == ERROR_SUCCESS, "format failed\n");
576     ok( sz == 7, "size wrong,(%i)\n",sz);
577     ok( 0 == strcmp(buffer,"big hey"), "wrong output (%s)\n",buffer);
578
579     r = MsiRecordSetString(hrec, 0, "[[3][4][1]] [2]");
580     r = MsiRecordSetString(hrec, 1, "2");
581     r = MsiRecordSetString(hrec, 2, "hey");
582     r = MsiRecordSetString(hrec, 3, "1");
583     r = MsiRecordSetString(hrec, 4, NULL);
584     r = MsiRecordSetString(hrec, 12, "big");
585     ok( r == ERROR_SUCCESS, "set string failed\n");
586     sz = sizeof buffer;
587     r = MsiFormatRecord(0, hrec, buffer, &sz);
588     ok( r == ERROR_SUCCESS, "format failed\n");
589     ok( sz == 7, "size wrong,(%i)\n",sz);
590     ok( 0 == strcmp(buffer,"big hey"), "wrong output (%s)\n",buffer);
591
592     r = MsiRecordSetString(hrec, 0, "[[3][[4]][1]] [2]");
593     r = MsiRecordSetString(hrec, 1, "2");
594     r = MsiRecordSetString(hrec, 2, "hey");
595     r = MsiRecordSetString(hrec, 3, "1");
596     r = MsiRecordSetString(hrec, 4, NULL);
597     r = MsiRecordSetString(hrec, 12, "big");
598     ok( r == ERROR_SUCCESS, "set string failed\n");
599     sz = sizeof buffer;
600     r = MsiFormatRecord(0, hrec, buffer, &sz);
601     ok( r == ERROR_SUCCESS, "format failed\n");
602     ok( sz == 10, "size wrong,(%i)\n",sz);
603     ok( 0 == strcmp(buffer,"[1[]2] hey"), "wrong output (%s)\n",buffer);
604
605     /* incorrect  formats */
606     r = MsiRecordSetString(hrec, 0, "[[[3][[4]][1]] [2]");
607     r = MsiRecordSetString(hrec, 1, "2");
608     r = MsiRecordSetString(hrec, 2, "hey");
609     r = MsiRecordSetString(hrec, 3, "1");
610     r = MsiRecordSetString(hrec, 4, NULL);
611     r = MsiRecordSetString(hrec, 12, "big");
612     ok( r == ERROR_SUCCESS, "set string failed\n");
613     sz = sizeof buffer;
614     r = MsiFormatRecord(0, hrec, buffer, &sz);
615     ok( r == ERROR_SUCCESS, "format failed\n");
616     ok( sz == 18, "size wrong,(%i)\n",sz);
617     ok( 0 == strcmp(buffer,"[[[3][[4]][1]] [2]"), "wrong output (%s)\n",buffer);
618
619     r = MsiRecordSetString(hrec, 0, "[[3][[4]][1]] [2]]");
620     r = MsiRecordSetString(hrec, 1, "2");
621     r = MsiRecordSetString(hrec, 2, "hey");
622     r = MsiRecordSetString(hrec, 3, "1");
623     r = MsiRecordSetString(hrec, 4, NULL);
624     r = MsiRecordSetString(hrec, 12, "big");
625     ok( r == ERROR_SUCCESS, "set string failed\n");
626     sz = sizeof buffer;
627     r = MsiFormatRecord(0, hrec, buffer, &sz);
628     ok( r == ERROR_SUCCESS, "format failed\n");
629     ok( sz == 11, "size wrong,(%i)\n",sz);
630     ok( 0 == strcmp(buffer,"[1[]2] hey]"), "wrong output (%s)\n",buffer);
631
632
633     /* play games with {} */
634
635     r = MsiRecordSetString(hrec, 0, "{[3][1]} [2]");
636     r = MsiRecordSetString(hrec, 1, "2");
637     r = MsiRecordSetString(hrec, 2, "hey");
638     r = MsiRecordSetString(hrec, 3, "1");
639     r = MsiRecordSetString(hrec, 4, NULL);
640     r = MsiRecordSetString(hrec, 12, "big");
641     ok( r == ERROR_SUCCESS, "set string failed\n");
642     sz = sizeof buffer;
643     r = MsiFormatRecord(0, hrec, buffer, &sz);
644     ok( r == ERROR_SUCCESS, "format failed\n");
645     ok( sz == 6, "size wrong,(%i)\n",sz);
646     ok( 0 == strcmp(buffer,"12 hey"), "wrong output (%s)\n",buffer);
647
648     r = MsiRecordSetString(hrec, 0, "[{[3][1]}] [2]");
649     r = MsiRecordSetString(hrec, 1, "2");
650     r = MsiRecordSetString(hrec, 2, "hey");
651     r = MsiRecordSetString(hrec, 3, "1");
652     r = MsiRecordSetString(hrec, 4, NULL);
653     r = MsiRecordSetString(hrec, 12, "big");
654     ok( r == ERROR_SUCCESS, "set string failed\n");
655     sz = sizeof buffer;
656     r = MsiFormatRecord(0, hrec, buffer, &sz);
657     ok( r == ERROR_SUCCESS, "format failed\n");
658     ok( sz == 8, "size wrong,(%i)\n",sz);
659     ok( 0 == strcmp(buffer,"[12] hey"), "wrong output (%s)\n",buffer);
660
661
662     r = MsiRecordSetString(hrec, 0, "{test} [2]");
663     r = MsiRecordSetString(hrec, 1, "2");
664     r = MsiRecordSetString(hrec, 2, "hey");
665     r = MsiRecordSetString(hrec, 3, "1");
666     r = MsiRecordSetString(hrec, 4, NULL);
667     r = MsiRecordSetString(hrec, 12, "big");
668     ok( r == ERROR_SUCCESS, "set string failed\n");
669     sz = sizeof buffer;
670     r = MsiFormatRecord(0, hrec, buffer, &sz);
671     ok( r == ERROR_SUCCESS, "format failed\n");
672     ok( sz == 10, "size wrong,(%i)\n",sz);
673     ok( 0 == strcmp(buffer,"{test} hey"), "wrong output (%s)\n",buffer);
674
675     r = MsiRecordSetString(hrec, 0, "{[test]} [2]");
676     r = MsiRecordSetString(hrec, 1, "2");
677     r = MsiRecordSetString(hrec, 2, "hey");
678     r = MsiRecordSetString(hrec, 3, "1");
679     r = MsiRecordSetString(hrec, 4, NULL);
680     r = MsiRecordSetString(hrec, 12, "big");
681     ok( r == ERROR_SUCCESS, "set string failed\n");
682     sz = sizeof buffer;
683     r = MsiFormatRecord(0, hrec, buffer, &sz);
684     ok( r == ERROR_SUCCESS, "format failed\n");
685     ok( sz == 12, "size wrong,(%i)\n",sz);
686     ok( 0 == strcmp(buffer,"{[test]} hey"), "wrong output (%s)\n",buffer);
687
688     r = MsiRecordSetString(hrec, 0, "{[1][2][3][4]} [2]");
689     r = MsiRecordSetString(hrec, 1, "2");
690     r = MsiRecordSetString(hrec, 2, "hey");
691     r = MsiRecordSetString(hrec, 3, "1");
692     r = MsiRecordSetString(hrec, 4, NULL);
693     r = MsiRecordSetString(hrec, 12, "big");
694     ok( r == ERROR_SUCCESS, "set string failed\n");
695     sz = sizeof buffer;
696     r = MsiFormatRecord(0, hrec, buffer, &sz);
697     ok( r == ERROR_SUCCESS, "format failed\n");
698     ok( sz == 4, "size wrong,(%i)\n",sz);
699     ok( 0 == strcmp(buffer," hey"), "wrong output (%s)\n",buffer);
700
701     r = MsiRecordSetString(hrec, 0, "{[1][2][3][dummy]} [2]");
702     r = MsiRecordSetString(hrec, 1, "2");
703     r = MsiRecordSetString(hrec, 2, "hey");
704     r = MsiRecordSetString(hrec, 3, "1");
705     r = MsiRecordSetString(hrec, 4, NULL);
706     r = MsiRecordSetString(hrec, 12, "big");
707     ok( r == ERROR_SUCCESS, "set string failed\n");
708     sz = sizeof buffer;
709     r = MsiFormatRecord(0, hrec, buffer, &sz);
710     ok( r == ERROR_SUCCESS, "format failed\n");
711     ok( sz == 18, "size wrong,(%i)\n",sz);
712     ok( 0 == strcmp(buffer,"{2hey1[dummy]} hey"), "wrong output (%s)\n",buffer);
713
714     r = MsiRecordSetString(hrec, 0, "{[1][2][3][4][dummy]} [2]");
715     r = MsiRecordSetString(hrec, 1, "2");
716     r = MsiRecordSetString(hrec, 2, "hey");
717     r = MsiRecordSetString(hrec, 3, "1");
718     r = MsiRecordSetString(hrec, 4, NULL);
719     r = MsiRecordSetString(hrec, 12, "big");
720     ok( r == ERROR_SUCCESS, "set string failed\n");
721     sz = sizeof buffer;
722     r = MsiFormatRecord(0, hrec, buffer, &sz);
723     ok( r == ERROR_SUCCESS, "format failed\n");
724     ok( sz == 18, "size wrong,(%i)\n",sz);
725     ok( 0 == strcmp(buffer,"{2hey1[dummy]} hey"), "wrong output (%s)\n",buffer);
726
727     r = MsiRecordSetString(hrec, 0, "{{[1][2]}[3][4][dummy]}");
728     r = MsiRecordSetString(hrec, 1, "2");
729     r = MsiRecordSetString(hrec, 2, "hey");
730     r = MsiRecordSetString(hrec, 3, "1");
731     r = MsiRecordSetString(hrec, 4, NULL);
732     r = MsiRecordSetString(hrec, 12, "big");
733     ok( r == ERROR_SUCCESS, "set string failed\n");
734     sz = sizeof buffer;
735     r = MsiFormatRecord(0, hrec, buffer, &sz);
736     ok( r == ERROR_SUCCESS, "format failed\n");
737
738     todo_wine{
739     ok( sz == 16, "size wrong,(%i)\n",sz);
740     ok( 0 == strcmp(buffer,"{{2hey}1[dummy]}"), "wrong output (%s)\n",buffer);
741     }
742
743     r = MsiRecordSetString(hrec, 0, "{{[1][2]}[3]{[4][dummy]}}");
744     r = MsiRecordSetString(hrec, 1, "2");
745     r = MsiRecordSetString(hrec, 2, "hey");
746     r = MsiRecordSetString(hrec, 3, "1");
747     r = MsiRecordSetString(hrec, 4, NULL);
748     r = MsiRecordSetString(hrec, 12, "big");
749     ok( r == ERROR_SUCCESS, "set string failed\n");
750     sz = sizeof buffer;
751     r = MsiFormatRecord(0, hrec, buffer, &sz);
752     ok( r == ERROR_SUCCESS, "format failed\n");
753     todo_wine{
754     ok( sz == 0, "size wrong,(%i)\n",sz);
755     ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
756     }
757
758     r = MsiRecordSetString(hrec, 0, "{{[1][2]}[3]} {[1][2]}");
759     r = MsiRecordSetString(hrec, 1, "1");
760     r = MsiRecordSetString(hrec, 2, "2");
761     r = MsiRecordSetString(hrec, 3, "3");
762     r = MsiRecordSetString(hrec, 4, NULL);
763     r = MsiRecordSetString(hrec, 12, "big");
764     ok( r == ERROR_SUCCESS, "set string failed\n");
765     sz = sizeof buffer;
766     r = MsiFormatRecord(0, hrec, buffer, &sz);
767     ok( r == ERROR_SUCCESS, "format failed\n");
768     todo_wine{
769     ok( sz == 12, "size wrong,(%i)\n",sz);
770     ok( 0 == strcmp(buffer,"{{12}3} {12}"), "wrong output (%s)\n",buffer);
771     }
772
773     r = MsiRecordSetString(hrec, 0, "{[1][2]} {{[1][2]}[3]} {[1][2]}");
774     r = MsiRecordSetString(hrec, 1, "1");
775     r = MsiRecordSetString(hrec, 2, "2");
776     r = MsiRecordSetString(hrec, 3, "3");
777     r = MsiRecordSetString(hrec, 4, NULL);
778     r = MsiRecordSetString(hrec, 12, "big");
779     ok( r == ERROR_SUCCESS, "set string failed\n");
780     sz = sizeof buffer;
781     r = MsiFormatRecord(0, hrec, buffer, &sz);
782     ok( r == ERROR_SUCCESS, "format failed\n");
783     todo_wine{
784     ok( sz == 15, "size wrong,(%i)\n",sz);
785     ok( 0 == strcmp(buffer,"12 {{12}3} {12}"), "wrong output (%s)\n",buffer);
786     }
787
788     r = MsiRecordSetString(hrec, 0, "{[4]}{[1][2]} {{[1][2]}[3]} {[1][2]}");
789     r = MsiRecordSetString(hrec, 1, "1");
790     r = MsiRecordSetString(hrec, 2, "2");
791     r = MsiRecordSetString(hrec, 3, "3");
792     r = MsiRecordSetString(hrec, 4, NULL);
793     r = MsiRecordSetString(hrec, 12, "big");
794     ok( r == ERROR_SUCCESS, "set string failed\n");
795     sz = sizeof buffer;
796     r = MsiFormatRecord(0, hrec, buffer, &sz);
797     ok( r == ERROR_SUCCESS, "format failed\n");
798     todo_wine{
799     ok( sz == 15, "size wrong,(%i)\n",sz);
800     ok( 0 == strcmp(buffer,"12 {{12}3} {12}"), "wrong output (%s)\n",buffer);
801     }
802
803
804     r = MsiRecordSetString(hrec, 0, "{blah} {[4]}{[1][2]} {{[1][2]}[3]} {[1][2]}");
805     r = MsiRecordSetString(hrec, 1, "1");
806     r = MsiRecordSetString(hrec, 2, "2");
807     r = MsiRecordSetString(hrec, 3, "3");
808     r = MsiRecordSetString(hrec, 4, NULL);
809     r = MsiRecordSetString(hrec, 12, "big");
810     ok( r == ERROR_SUCCESS, "set string failed\n");
811     sz = sizeof buffer;
812     r = MsiFormatRecord(0, hrec, buffer, &sz);
813     ok( r == ERROR_SUCCESS, "format failed\n");
814     todo_wine{
815     ok( sz == 22, "size wrong,(%i)\n",sz);
816     ok( 0 == strcmp(buffer,"{blah} 12 {{12}3} {12}"), "wrong output (%s)\n",buffer);
817     }
818
819     r = MsiRecordSetString(hrec, 0, "{{[1]}[2]} {[4]}{[1][2]}");
820     r = MsiRecordSetString(hrec, 1, "1");
821     r = MsiRecordSetString(hrec, 2, "2");
822     r = MsiRecordSetString(hrec, 3, "3");
823     r = MsiRecordSetString(hrec, 4, NULL);
824     r = MsiRecordSetString(hrec, 12, "big");
825     ok( r == ERROR_SUCCESS, "set string failed\n");
826     sz = sizeof buffer;
827     r = MsiFormatRecord(0, hrec, buffer, &sz);
828     ok( r == ERROR_SUCCESS, "format failed\n");
829     todo_wine{
830     ok( sz == 13, "size wrong,(%i)\n",sz);
831     ok( 0 == strcmp(buffer,"{{1}2} {}{12}"), "wrong output (%s)\n",buffer);
832     }
833
834     r = MsiRecordSetString(hrec, 0, "{{[1]}} {[4]}{[1][2]}");
835     r = MsiRecordSetString(hrec, 1, "1");
836     r = MsiRecordSetString(hrec, 2, "2");
837     r = MsiRecordSetString(hrec, 3, "3");
838     r = MsiRecordSetString(hrec, 4, NULL);
839     r = MsiRecordSetString(hrec, 12, "big");
840     ok( r == ERROR_SUCCESS, "set string failed\n");
841     sz = sizeof buffer;
842     r = MsiFormatRecord(0, hrec, buffer, &sz);
843     ok( r == ERROR_SUCCESS, "format failed\n");
844     todo_wine{
845     ok( sz == 3, "size wrong,(%i)\n",sz);
846     ok( 0 == strcmp(buffer," 12"), "wrong output (%s)\n",buffer);
847     }
848
849     r = MsiRecordSetString(hrec, 0, "{{{[1]}} {[4]}{[1][2]}");
850     r = MsiRecordSetString(hrec, 1, "1");
851     r = MsiRecordSetString(hrec, 2, "2");
852     r = MsiRecordSetString(hrec, 3, "3");
853     r = MsiRecordSetString(hrec, 4, NULL);
854     r = MsiRecordSetString(hrec, 12, "big");
855     ok( r == ERROR_SUCCESS, "set string failed\n");
856     sz = sizeof buffer;
857     r = MsiFormatRecord(0, hrec, buffer, &sz);
858     ok( r == ERROR_SUCCESS, "format failed\n");
859     todo_wine{
860     ok( sz == 3, "size wrong,(%i)\n",sz);
861     ok( 0 == strcmp(buffer," 12"), "wrong output (%s)\n",buffer);
862     }
863     
864     /* now put play games with escaping */
865     r = MsiRecordSetString(hrec, 0, "[1] [2] [\\3asdf]");
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 == 16, "size wrong\n");
873     ok( 0 == strcmp(buffer,"boo hoo [\\3asdf]"), "wrong output\n");
874
875     /* now put play games with escaping */
876     r = MsiRecordSetString(hrec, 0, "[1] [2] [\\x]");
877     r = MsiRecordSetString(hrec, 1, "boo");
878     r = MsiRecordSetString(hrec, 2, "hoo");
879     ok( r == ERROR_SUCCESS, "set string failed\n");
880     sz = sizeof buffer;
881     r = MsiFormatRecord(0, hrec, buffer, &sz);
882     ok( r == ERROR_SUCCESS, "format failed\n");
883     ok( sz == 12, "size wrong\n");
884     ok( 0 == strcmp(buffer,"boo hoo [\\x]"), "wrong output\n");
885
886     MsiRecordSetString(hrec, 0, "[\\x]");
887     sz = sizeof buffer;
888     r = MsiFormatRecord(0, hrec, buffer, &sz);
889     ok( r == ERROR_SUCCESS, "format failed\n");
890     ok( sz == 4, "size wrong: %d\n", sz);
891     ok( 0 == strcmp(buffer,"[\\x]"), "wrong output: %s\n", buffer);
892
893     MsiRecordSetString(hrec, 0, "{\\x}");
894     sz = sizeof buffer;
895     r = MsiFormatRecord(0, hrec, buffer, &sz);
896     ok( r == ERROR_SUCCESS, "format failed\n");
897     ok( sz == 4, "size wrong: %d\n", sz);
898     ok( 0 == strcmp(buffer,"{\\x}"), "wrong output: %s\n", buffer);
899
900     MsiRecordSetString(hrec, 0, "[abc\\x]");
901     sz = sizeof buffer;
902     r = MsiFormatRecord(0, hrec, buffer, &sz);
903     ok( r == ERROR_SUCCESS, "format failed\n");
904     ok( sz == 7, "size wrong: %d\n", sz);
905     ok( 0 == strcmp(buffer,"[abc\\x]"), "wrong output: %s\n", buffer);
906
907     MsiRecordSetString(hrec, 0, "[\\[]Bracket Text[\\]]");
908     sz = sizeof buffer;
909     r = MsiFormatRecord(0, hrec, buffer, &sz);
910     ok( r == ERROR_SUCCESS, "format failed\n");
911     ok( sz == 20, "size wrong: %d\n", sz);
912     ok( 0 == strcmp(buffer,"[\\[]Bracket Text[\\]]"), "wrong output: %s\n", buffer);
913
914     /* now try other formats without a package */
915     r = MsiRecordSetString(hrec, 0, "[1] [2] [property]");
916     r = MsiRecordSetString(hrec, 1, "boo");
917     r = MsiRecordSetString(hrec, 2, "hoo");
918     ok( r == ERROR_SUCCESS, "set string failed\n");
919     sz = sizeof buffer;
920     r = MsiFormatRecord(0, hrec, buffer, &sz);
921     ok( r == ERROR_SUCCESS, "format failed\n");
922     ok( sz == 18, "size wrong\n");
923     ok( 0 == strcmp(buffer,"boo hoo [property]"), "wrong output\n");
924
925     r = MsiRecordSetString(hrec, 0, "[1] [~] [2]");
926     r = MsiRecordSetString(hrec, 1, "boo");
927     r = MsiRecordSetString(hrec, 2, "hoo");
928     ok( r == ERROR_SUCCESS, "set string failed\n");
929     sz = sizeof buffer;
930     r = MsiFormatRecord(0, hrec, buffer, &sz);
931     ok( r == ERROR_SUCCESS, "format failed\n");
932     ok( sz == 11, "size wrong\n");
933     ok( 0 == strcmp(buffer,"boo [~] hoo"), "wrong output (%s)\n",buffer);
934
935     r = MsiRecordSetString(hrec, 0, "[1]");
936     r = MsiRecordSetInteger(hrec, 1, 123456);
937     ok( r == ERROR_SUCCESS, "set integer failed\n");
938     sz = sizeof buffer;
939     r = MsiFormatRecord(0, hrec, buffer, &sz);
940     ok( r == ERROR_SUCCESS, "format failed\n");
941     ok( sz == 6, "size wrong\n");
942     ok( 0 == strcmp(buffer,"123456"), "wrong output (%s)\n",buffer);
943
944     r = MsiRecordSetString(hrec, 0, "[~]");
945     sz = sizeof buffer;
946     r = MsiFormatRecord(0, hrec, buffer, &sz);
947     ok( sz == 3, "size wrong\n");
948     ok( 0 == strcmp(buffer,"[~]"), "wrong output\n");
949     ok( r == ERROR_SUCCESS, "format failed\n");
950
951     r = MsiRecordSetString(hrec, 0, "[]");
952     sz = sizeof buffer;
953     r = MsiFormatRecord(0, hrec, buffer, &sz);
954     ok( sz == 2, "size wrong\n");
955     ok( 0 == strcmp(buffer,"[]"), "wrong output\n");
956     ok( r == ERROR_SUCCESS, "format failed\n");
957
958     /* MsiFormatRecord doesn't seem to handle a negative too well */
959     r = MsiRecordSetString(hrec, 0, "[-1]");
960     sz = sizeof buffer;
961     r = MsiFormatRecord(0, hrec, buffer, &sz);
962     ok( sz == 4, "size wrong\n");
963     ok( 0 == strcmp(buffer,"[-1]"), "wrong output\n");
964     ok( r == ERROR_SUCCESS, "format failed\n");
965
966     r = MsiRecordSetString(hrec, 0, "{[]}");
967     sz = sizeof buffer;
968     r = MsiFormatRecord(0, hrec, buffer, &sz);
969     ok( sz == 4, "size wrong\n");
970     ok( 0 == strcmp(buffer,"{[]}"), "wrong output\n");
971     ok( r == ERROR_SUCCESS, "format failed\n");
972
973     r = MsiRecordSetString(hrec, 0, "[0]");
974     sz = sizeof buffer;
975     r = MsiFormatRecord(0, hrec, buffer, &sz);
976     ok( sz == 3, "size wrong\n");
977     ok( 0 == strcmp(buffer,"[0]"), "wrong output\n");
978     ok( r == ERROR_SUCCESS, "format failed\n");
979
980     r = MsiRecordSetString(hrec, 0, "[100]");
981     sz = sizeof buffer;
982     r = MsiFormatRecord(0, hrec, buffer, &sz);
983     ok( sz == 0, "size wrong\n");
984     ok( 0 == strcmp(buffer,""), "wrong output\n");
985     ok( r == ERROR_SUCCESS, "format failed\n");
986
987     r = MsiRecordSetString(hrec, 0, "{[1] [2]}");
988     r = MsiRecordSetString(hrec, 1, "boo");
989     r = MsiRecordSetString(hrec, 2, "hoo");
990     sz = sizeof buffer;
991     r = MsiFormatRecord(0, hrec, buffer, &sz);
992     ok( sz == 7, "size wrong\n");
993     ok( 0 == strcmp(buffer,"boo hoo"), "wrong output\n");
994     ok( r == ERROR_SUCCESS, "format failed\n");
995
996     r = MsiRecordSetString(hrec, 0, "{}");
997     sz = sizeof buffer;
998     r = MsiFormatRecord(0, hrec, buffer, &sz);
999     ok( sz == 0, "size wrong\n");
1000     ok( 0 == strcmp(buffer,""), "wrong output\n");
1001     ok( r == ERROR_SUCCESS, "format failed\n");
1002
1003     r = MsiRecordSetString(hrec, 0, "{foo}");
1004     sz = sizeof buffer;
1005     r = MsiFormatRecord(0, hrec, buffer, &sz);
1006     ok( sz == 5, "size wrong\n");
1007     ok( 0 == strcmp(buffer,"{foo}"), "wrong output\n");
1008     ok( r == ERROR_SUCCESS, "format failed\n");
1009
1010     r = MsiRecordSetString(hrec, 0, "{boo [1]}");
1011     r = MsiRecordSetString(hrec, 1, "hoo");
1012     sz = sizeof buffer;
1013     r = MsiFormatRecord(0, hrec, buffer, &sz);
1014     ok( sz == 7, "size wrong\n");
1015     ok( 0 == strcmp(buffer,"boo hoo"), "wrong output\n");
1016     ok( r == ERROR_SUCCESS, "format failed\n");
1017
1018     todo_wine {
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( sz == 0, "size wrong\n");
1024     ok( 0 == strcmp(buffer,""), "wrong output\n");
1025     }
1026     ok( r == ERROR_SUCCESS, "format failed\n");
1027
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( 0 == strcmp(buffer," {hoo}"), "wrong output\n");
1033     ok( sz == 6, "size wrong\n");
1034     ok( r == ERROR_SUCCESS, "format failed\n");
1035
1036     todo_wine {
1037     r = MsiRecordSetString(hrec, 0, "{{[1]} }");
1038     r = MsiRecordSetString(hrec, 1, "hoo");
1039     sz = sizeof buffer;
1040     r = MsiFormatRecord(0, hrec, buffer, &sz);
1041     ok( sz == 8, "size wrong\n");
1042     ok( 0 == strcmp(buffer,"{{hoo} }"), "wrong output\n");
1043     }
1044     ok( r == ERROR_SUCCESS, "format failed\n");
1045
1046     todo_wine {
1047     r = MsiRecordSetString(hrec, 0, "{{ [1]}}");
1048     r = MsiRecordSetString(hrec, 1, "hoo");
1049     sz = sizeof buffer;
1050     r = MsiFormatRecord(0, hrec, buffer, &sz);
1051     ok( sz == 0, "size wrong\n");
1052     ok( 0 == strcmp(buffer,""), "wrong output\n");
1053     }
1054     ok( r == ERROR_SUCCESS, "format failed\n");
1055
1056     todo_wine {
1057     r = MsiRecordSetString(hrec, 0, "{{[1] }}");
1058     r = MsiRecordSetString(hrec, 1, "hoo");
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     todo_wine {
1067     r = MsiRecordSetString(hrec, 0, "{{a}{b}{c }{ d}{any text}}");
1068     sz = sizeof buffer;
1069     r = MsiFormatRecord(0, hrec, buffer, &sz);
1070     ok( sz == 0, "size wrong\n");
1071     ok( 0 == strcmp(buffer,""), "wrong output\n");
1072     }
1073     ok( r == ERROR_SUCCESS, "format failed\n");
1074
1075     r = MsiRecordSetString(hrec, 0, "{{a} }");
1076     sz = sizeof buffer;
1077     r = MsiFormatRecord(0, hrec, buffer, &sz);
1078     ok( sz == 6, "size wrong\n");
1079     ok( 0 == strcmp(buffer,"{{a} }"), "wrong output\n");
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     todo_wine {
1101     r = MsiRecordSetString(hrec, 0, "{{a b}}");
1102     sz = sizeof buffer;
1103     r = MsiFormatRecord(0, hrec, buffer, &sz);
1104     ok( sz == 0, "size wrong\n");
1105     ok( 0 == strcmp(buffer,""), "wrong output\n");
1106     }
1107     ok( r == ERROR_SUCCESS, "format failed\n");
1108
1109     r = MsiRecordSetString(hrec, 0, "{ }");
1110     sz = sizeof buffer;
1111     r = MsiFormatRecord(0, hrec, buffer, &sz);
1112     ok( sz == 3, "size wrong\n");
1113     ok( 0 == strcmp(buffer,"{ }"), "wrong output\n");
1114     ok( r == ERROR_SUCCESS, "format failed\n");
1115
1116     todo_wine {
1117     r = MsiRecordSetString(hrec, 0, " {{a}}}");
1118     sz = sizeof buffer;
1119     r = MsiFormatRecord(0, hrec, buffer, &sz);
1120     ok( sz == 2, "size wrong\n");
1121     ok( 0 == strcmp(buffer," }"), "wrong output\n");
1122     }
1123     ok( r == ERROR_SUCCESS, "format failed\n");
1124
1125     todo_wine {
1126     r = MsiRecordSetString(hrec, 0, "{{ almost {{ any }} text }}");
1127     sz = sizeof buffer;
1128     r = MsiFormatRecord(0, hrec, buffer, &sz);
1129     ok( sz == 8, "size wrong\n");
1130     ok( 0 == strcmp(buffer," text }}"), "wrong output\n");
1131     }
1132     ok( r == ERROR_SUCCESS, "format failed\n");
1133
1134     todo_wine {
1135     r = MsiRecordSetString(hrec, 0, "{{ } { hidden ][ [ }}");
1136     sz = sizeof buffer;
1137     r = MsiFormatRecord(0, hrec, buffer, &sz);
1138     ok( sz == 0, "size wrong\n");
1139     ok( 0 == strcmp(buffer,""), "wrong output\n");
1140     }
1141     ok( r == ERROR_SUCCESS, "format failed\n");
1142
1143     r = MsiRecordSetString(hrec, 0, "[ 1]");
1144     r = MsiRecordSetString(hrec, 1, "hoo");
1145     sz = sizeof buffer;
1146     r = MsiFormatRecord(0, hrec, buffer, &sz);
1147     ok( sz == 4, "size wrong\n");
1148     ok( 0 == strcmp(buffer,"[ 1]"), "wrong output\n");
1149     ok( r == ERROR_SUCCESS, "format failed\n");
1150
1151     r = MsiRecordSetString(hrec, 0, "[01]");
1152     r = MsiRecordSetString(hrec, 1, "hoo");
1153     sz = sizeof buffer;
1154     r = MsiFormatRecord(0, hrec, buffer, &sz);
1155     ok( sz == 3, "size wrong\n");
1156     ok( 0 == strcmp(buffer,"hoo"), "wrong output\n");
1157     ok( r == ERROR_SUCCESS, "format failed\n");
1158
1159     todo_wine {
1160     r = MsiRecordSetString(hrec, 0, "{{test}} [01");
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," [01"), "wrong output\n");
1166     }
1167     ok( r == ERROR_SUCCESS, "format failed\n");
1168
1169     r = MsiRecordSetString(hrec, 0, "[\\[]");
1170     r = MsiRecordSetString(hrec, 1, "hoo");
1171     sz = sizeof buffer;
1172     r = MsiFormatRecord(0, hrec, buffer, &sz);
1173     ok( sz == 4, "size wrong\n");
1174     ok( 0 == strcmp(buffer,"[\\[]"), "wrong output\n");
1175     ok( r == ERROR_SUCCESS, "format failed\n");
1176
1177     r = MsiRecordSetString(hrec, 0, "[foo]");
1178     r = MsiRecordSetString(hrec, 1, "hoo");
1179     sz = sizeof buffer;
1180     r = MsiFormatRecord(0, hrec, buffer, &sz);
1181     ok( sz == 5, "size wrong\n");
1182     ok( 0 == strcmp(buffer,"[foo]"), "wrong output\n");
1183     ok( r == ERROR_SUCCESS, "format failed\n");
1184
1185     r = MsiRecordSetString(hrec, 0, "[01.]");
1186     r = MsiRecordSetString(hrec, 1, "hoo");
1187     sz = sizeof buffer;
1188     r = MsiFormatRecord(0, hrec, buffer, &sz);
1189     ok( sz == 5, "size wrong\n");
1190     ok( 0 == strcmp(buffer,"[01.]"), "wrong output\n");
1191     ok( r == ERROR_SUCCESS, "format failed\n");
1192
1193     SetEnvironmentVariable("FOO", "BAR");
1194     r = MsiRecordSetString(hrec, 0, "[%FOO]");
1195     sz = sizeof buffer;
1196     r = MsiFormatRecord(0, hrec, buffer, &sz);
1197     ok( sz == 6, "size wrong\n");
1198     ok( 0 == strcmp(buffer,"[%FOO]"), "wrong output\n");
1199     ok( r == ERROR_SUCCESS, "format failed\n");
1200
1201     todo_wine {
1202     r = MsiRecordSetString(hrec, 0, "{{[1]}");
1203     r = MsiRecordSetString(hrec, 1, "hoo");
1204     sz = sizeof buffer;
1205     r = MsiFormatRecord(0, hrec, buffer, &sz);
1206     ok( sz == 6, "size wrong\n");
1207     ok( 0 == strcmp(buffer,"{{hoo}"), "wrong output\n");
1208     }
1209     ok( r == ERROR_SUCCESS, "format failed\n");
1210
1211     todo_wine {
1212     r = MsiRecordSetString(hrec, 0, "{{ {[1]}");
1213     r = MsiRecordSetString(hrec, 1, "hoo");
1214     sz = sizeof buffer;
1215     r = MsiFormatRecord(0, hrec, buffer, &sz);
1216     ok( sz == 8, "size wrong\n");
1217     ok( 0 == strcmp(buffer,"{{ {hoo}"), "wrong output\n");
1218     }
1219     ok( r == ERROR_SUCCESS, "format failed\n");
1220
1221     todo_wine {
1222     r = MsiRecordSetString(hrec, 0, "{{ {[1]}");
1223     r = MsiRecordSetString(hrec, 1, "hoo");
1224     sz = sizeof buffer;
1225     r = MsiFormatRecord(0, hrec, buffer, &sz);
1226     ok( sz == 8, "size wrong\n");
1227     ok( 0 == strcmp(buffer,"{{ {hoo}"), "wrong output\n");
1228     }
1229     ok( r == ERROR_SUCCESS, "format failed\n");
1230
1231     todo_wine {
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 == 9, "size wrong\n");
1237     ok( 0 == strcmp(buffer,"{{ {{hoo}"), "wrong output\n");
1238     }
1239     ok( r == ERROR_SUCCESS, "format failed\n");
1240
1241     r = MsiRecordSetString(hrec, 0, "[1]}");
1242     r = MsiRecordSetString(hrec, 1, "hoo");
1243     sz = sizeof buffer;
1244     r = MsiFormatRecord(0, hrec, buffer, &sz);
1245     ok( sz == 4, "size wrong\n");
1246     ok( 0 == strcmp(buffer,"hoo}"), "wrong output\n");
1247     ok( r == ERROR_SUCCESS, "format failed\n");
1248
1249     r = MsiRecordSetString(hrec, 0, "{{ {{a}");
1250     sz = sizeof buffer;
1251     r = MsiFormatRecord(0, hrec, buffer, &sz);
1252     ok( sz == 7, "size wrong\n");
1253     ok( 0 == strcmp(buffer,"{{ {{a}"), "wrong output\n");
1254     ok( r == ERROR_SUCCESS, "format failed\n");
1255
1256     r = MsiRecordSetString(hrec, 0, "{{ {{a}");
1257     sz = sizeof buffer;
1258     r = MsiFormatRecord(0, hrec, buffer, &sz);
1259     ok( sz == 7, "size wrong\n");
1260     ok( 0 == strcmp(buffer,"{{ {{a}"), "wrong output\n");
1261     ok( r == ERROR_SUCCESS, "format failed\n");
1262
1263     r = MsiRecordSetString(hrec, 0, "0{1{2{3{4[1]5}6}7}8}9");
1264     r = MsiRecordSetString(hrec, 1, "hoo");
1265     sz = sizeof buffer;
1266     r = MsiFormatRecord(0, hrec, buffer, &sz);
1267     ok( sz == 19, "size wrong\n");
1268     ok( 0 == strcmp(buffer,"01{2{3{4hoo56}7}8}9"), "wrong output\n");
1269     ok( r == ERROR_SUCCESS, "format failed\n");
1270
1271     r = MsiRecordSetString(hrec, 0, "0{1{2[1]3}4");
1272     r = MsiRecordSetString(hrec, 1, "hoo");
1273     sz = sizeof buffer;
1274     r = MsiFormatRecord(0, hrec, buffer, &sz);
1275     ok( sz == 9, "size wrong\n");
1276     ok( 0 == strcmp(buffer,"01{2hoo34"), "wrong output\n");
1277     ok( r == ERROR_SUCCESS, "format failed\n");
1278
1279     r = MsiRecordSetString(hrec, 0, "0{1{2[1]3}4");
1280     r = MsiRecordSetString(hrec, 1, "hoo");
1281     sz = sizeof buffer;
1282     r = MsiFormatRecord(0, hrec, buffer, &sz);
1283     ok( sz == 9, "size wrong\n");
1284     ok( 0 == strcmp(buffer,"01{2hoo34"), "wrong output\n");
1285     ok( r == ERROR_SUCCESS, "format failed\n");
1286
1287     r = MsiRecordSetString(hrec, 0, "{[1.} [1]");
1288     r = MsiRecordSetString(hrec, 1, "hoo");
1289     sz = sizeof buffer;
1290     r = MsiFormatRecord(0, hrec, buffer, &sz);
1291     ok( sz == 9, "size wrong\n");
1292     ok( 0 == strcmp(buffer,"{[1.} hoo"), "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 == 9, "size wrong\n");
1301     ok( 0 == strcmp(buffer,"{[{[1]}]}"), "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 == 2, "size wrong\n");
1310     ok( 0 == strcmp(buffer,"2["), "wrong output\n");
1311     ok( r == ERROR_SUCCESS, "format failed\n");
1312
1313     r = MsiRecordSetString(hrec, 0, "[1]");
1314     r = MsiRecordSetString(hrec, 1, "[2]");
1315     r = MsiRecordSetString(hrec, 2, "foo");
1316     sz = sizeof buffer;
1317     r = MsiFormatRecord(0, hrec, buffer, &sz);
1318     ok( sz == 3, "size wrong\n");
1319     ok( 0 == strcmp(buffer,"[2]"), "wrong output\n");
1320     ok( r == ERROR_SUCCESS, "format failed\n");
1321
1322     todo_wine {
1323     r = MsiRecordSetString(hrec, 0, "[{{boo}}1]");
1324     r = MsiRecordSetString(hrec, 1, "hoo");
1325     sz = sizeof buffer;
1326     r = MsiFormatRecord(0, hrec, buffer, &sz);
1327     ok( sz == 3, "size wrong\n");
1328     ok( 0 == strcmp(buffer,"[1]"), "wrong output\n");
1329     }
1330     ok( r == ERROR_SUCCESS, "format failed\n");
1331
1332     todo_wine {
1333     r = MsiRecordSetString(hrec, 0, "[{{boo}}1]");
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 == 3, "size wrong\n");
1339     ok( 0 == strcmp(buffer,"[1]"), "wrong output\n");
1340     }
1341     ok( r == ERROR_SUCCESS, "format failed\n");
1342
1343     r = MsiRecordSetString(hrec, 0, "{[1]{{boo} }}");
1344     r = MsiRecordSetString(hrec, 1, "hoo");
1345     sz = sizeof buffer;
1346     r = MsiFormatRecord(0, hrec, buffer, &sz);
1347     ok( sz == 11, "size wrong\n");
1348     ok( 0 == strcmp(buffer,"hoo{{boo }}"), "wrong output\n");
1349     ok( r == ERROR_SUCCESS, "format failed\n");
1350
1351     r = MsiRecordSetString(hrec, 0, "{[1{{boo}}]}");
1352     r = MsiRecordSetString(hrec, 1, "hoo");
1353     sz = sizeof buffer;
1354     r = MsiFormatRecord(0, hrec, buffer, &sz);
1355     ok( sz == 12, "size wrong: got %u, expected 12\n", sz);
1356     ok( 0 == strcmp(buffer,"{[1{{boo}}]}"), "wrong output: got %s, expected [1]\n", buffer);
1357     ok( r == ERROR_SUCCESS, "format failed\n");
1358
1359     todo_wine {
1360     r = MsiRecordSetString(hrec, 0, "{{[1]}");
1361     r = MsiRecordSetString(hrec, 1, "hoo");
1362     sz = sizeof buffer;
1363     r = MsiFormatRecord(0, hrec, buffer, &sz);
1364     ok( sz == 6, "size wrong: got %u, expected 3\n", sz);
1365     ok( 0 == strcmp(buffer,"{{hoo}"), "wrong output: got %s, expected [1]\n", buffer);
1366     }
1367     ok( r == ERROR_SUCCESS, "format failed\n");
1368
1369     r = MsiRecordSetString(hrec, 0, "{[1{{bo}o}}]}");
1370     r = MsiRecordSetString(hrec, 1, "hoo");
1371     sz = sizeof buffer;
1372     r = MsiFormatRecord(0, hrec, buffer, &sz);
1373     ok( sz == 13, "size wrong\n");
1374     ok( 0 == strcmp(buffer,"{[1{{bo}o}}]}"), "wrong output %s\n",buffer);
1375     ok( r == ERROR_SUCCESS, "format failed\n");
1376
1377     r = MsiRecordSetString(hrec, 0, "{[1{{b{o}o}}]}");
1378     sz = sizeof buffer;
1379     r = MsiFormatRecord(0, hrec, buffer, &sz);
1380     ok( sz == 14, "size wrong\n");
1381     ok( 0 == strcmp(buffer,"{[1{{b{o}o}}]}"), "wrong output %s\n",buffer);
1382     ok( r == ERROR_SUCCESS, "format failed\n");
1383
1384     r = MsiRecordSetString(hrec, 0, "{ {[1]}");
1385     r = MsiRecordSetString(hrec, 1, "hoo");
1386     sz = sizeof buffer;
1387     r = MsiFormatRecord(0, hrec, buffer, &sz);
1388     ok( sz == 5, "size wrong\n");
1389     ok( 0 == strcmp(buffer," {hoo"), "wrong output %s\n",buffer);
1390     ok( r == ERROR_SUCCESS, "format failed\n");
1391
1392     /* {} inside a substitution does strange things... */
1393     r = MsiRecordSetString(hrec, 0, "[[1]{}]");
1394     r = MsiRecordSetString(hrec, 1, "2");
1395     sz = sizeof buffer;
1396     r = MsiFormatRecord(0, hrec, buffer, &sz);
1397     ok( sz == 5, "size wrong\n");
1398     ok( 0 == strcmp(buffer,"[[1]]"), "wrong output %s\n",buffer);
1399     ok( r == ERROR_SUCCESS, "format failed\n");
1400
1401     r = MsiRecordSetString(hrec, 0, "[[1]{}[1]]");
1402     r = MsiRecordSetString(hrec, 1, "2");
1403     sz = sizeof buffer;
1404     r = MsiFormatRecord(0, hrec, buffer, &sz);
1405     ok( sz == 6, "size wrong\n");
1406     ok( 0 == strcmp(buffer,"[[1]2]"), "wrong output %s\n",buffer);
1407     ok( r == ERROR_SUCCESS, "format failed\n");
1408
1409     r = MsiRecordSetString(hrec, 0, "[a[1]b[1]c{}d[1]e]");
1410     r = MsiRecordSetString(hrec, 1, "2");
1411     sz = sizeof buffer;
1412     r = MsiFormatRecord(0, hrec, buffer, &sz);
1413     ok( sz == 14, "size wrong\n");
1414     ok( 0 == strcmp(buffer,"[a[1]b[1]cd2e]"), "wrong output %s\n",buffer);
1415     ok( r == ERROR_SUCCESS, "format failed\n");
1416
1417     r = MsiRecordSetString(hrec, 0, "[a[1]b");
1418     r = MsiRecordSetString(hrec, 1, "2");
1419     sz = sizeof buffer;
1420     r = MsiFormatRecord(0, hrec, buffer, &sz);
1421     ok( sz == 6, "size wrong\n");
1422     ok( 0 == strcmp(buffer,"[a[1]b"), "wrong output %s\n",buffer);
1423     ok( r == ERROR_SUCCESS, "format failed\n");
1424
1425     r = MsiRecordSetString(hrec, 0, "a[1]b]");
1426     r = MsiRecordSetString(hrec, 1, "2");
1427     sz = sizeof buffer;
1428     r = MsiFormatRecord(0, hrec, buffer, &sz);
1429     ok( sz == 4, "size wrong\n");
1430     ok( 0 == strcmp(buffer,"a2b]"), "wrong output %s\n",buffer);
1431     ok( r == ERROR_SUCCESS, "format failed\n");
1432
1433     r = MsiRecordSetString(hrec, 0, "]a[1]b");
1434     r = MsiRecordSetString(hrec, 1, "2");
1435     sz = sizeof buffer;
1436     r = MsiFormatRecord(0, hrec, buffer, &sz);
1437     ok( sz == 4, "size wrong\n");
1438     ok( 0 == strcmp(buffer,"]a2b"), "wrong output %s\n",buffer);
1439     ok( r == ERROR_SUCCESS, "format failed\n");
1440
1441     r = MsiRecordSetString(hrec, 0, "]a[1]b");
1442     r = MsiRecordSetString(hrec, 1, "2");
1443     sz = sizeof buffer;
1444     r = MsiFormatRecord(0, hrec, buffer, &sz);
1445     ok( sz == 4, "size wrong\n");
1446     ok( 0 == strcmp(buffer,"]a2b"), "wrong output %s\n",buffer);
1447     ok( r == ERROR_SUCCESS, "format failed\n");
1448
1449     r = MsiRecordSetString(hrec, 0, "\\[1]");
1450     r = MsiRecordSetString(hrec, 1, "2");
1451     sz = sizeof buffer;
1452     r = MsiFormatRecord(0, hrec, buffer, &sz);
1453     ok( sz == 2, "size wrong\n");
1454     ok( 0 == strcmp(buffer,"\\2"), "wrong output %s\n",buffer);
1455     ok( r == ERROR_SUCCESS, "format failed\n");
1456
1457     r = MsiRecordSetString(hrec, 0, "\\{[1]}");
1458     r = MsiRecordSetString(hrec, 1, "2");
1459     sz = sizeof buffer;
1460     r = MsiFormatRecord(0, hrec, buffer, &sz);
1461     ok( sz == 2, "size wrong\n");
1462     ok( 0 == strcmp(buffer,"\\2"), "wrong output %s\n",buffer);
1463     ok( r == ERROR_SUCCESS, "format failed\n");
1464
1465     r = MsiRecordSetString(hrec, 0, "a{b[1]c}d");
1466     r = MsiRecordSetString(hrec, 1, NULL);
1467     sz = sizeof buffer;
1468     r = MsiFormatRecord(0, hrec, buffer, &sz);
1469     ok( sz == 2, "size wrong\n");
1470     ok( 0 == strcmp(buffer,"ad"), "wrong output %s\n",buffer);
1471     ok( r == ERROR_SUCCESS, "format failed\n");
1472
1473     r = MsiRecordSetString(hrec, 0, "{a[0]b}");
1474     r = MsiRecordSetString(hrec, 1, "foo");
1475     sz = sizeof buffer;
1476     r = MsiFormatRecord(0, hrec, buffer, &sz);
1477     ok( sz == 9, "size wrong\n");
1478     ok( 0 == strcmp(buffer,"a{a[0]b}b"), "wrong output %s\n",buffer);
1479     ok( r == ERROR_SUCCESS, "format failed\n");
1480
1481     r = MsiRecordSetString(hrec, 0, "[foo]");
1482     sz = sizeof buffer;
1483     r = MsiFormatRecord(0, hrec, buffer, &sz);
1484     ok( sz == 5, "size wrong\n");
1485     ok( 0 == strcmp(buffer,"[foo]"), "wrong output %s\n",buffer);
1486     ok( r == ERROR_SUCCESS, "format failed\n");
1487
1488     r = MsiRecordSetString(hrec, 0, "{[1][-1][1]}");
1489     r = MsiRecordSetString(hrec, 1, "foo");
1490     sz = sizeof buffer;
1491     r = MsiFormatRecord(0, hrec, buffer, &sz);
1492     ok( sz == 12, "size wrong\n");
1493     ok( 0 == strcmp(buffer,"{foo[-1]foo}"), "wrong output %s\n",buffer);
1494     ok( r == ERROR_SUCCESS, "format failed\n");
1495
1496     /* nested braces */
1497     sz = sizeof buffer;
1498     MsiRecordSetString(hrec, 0, "{abcd}");
1499     r = MsiFormatRecord(0, hrec, buffer, &sz);
1500     ok( r == ERROR_SUCCESS, "format failed\n");
1501     ok( sz == 6, "size wrong(%i)\n",sz);
1502     ok( 0 == strcmp(buffer,"{abcd}"), "wrong output (%s)\n",buffer);
1503
1504     sz = sizeof buffer;
1505     MsiRecordSetString(hrec, 0, "{a[one]bc[two]de[one]f}");
1506     r = MsiFormatRecord(0, hrec, buffer, &sz);
1507     ok( r == ERROR_SUCCESS, "format failed\n");
1508     ok( sz == 23, "size wrong(%i)\n",sz);
1509     ok( 0 == strcmp(buffer,"{a[one]bc[two]de[one]f}"), "wrong output (%s)\n",buffer);
1510
1511     sz = sizeof buffer;
1512     MsiRecordSetString(hrec, 0, "{a[one]bc[bad]de[two]f}");
1513     r = MsiFormatRecord(0, hrec, buffer, &sz);
1514     ok( r == ERROR_SUCCESS, "format failed\n");
1515     ok( sz == 23, "size wrong(%i)\n",sz);
1516     ok( 0 == strcmp(buffer,"{a[one]bc[bad]de[two]f}"), "wrong output (%s)\n",buffer);
1517
1518     sz = sizeof buffer;
1519     MsiRecordSetString(hrec, 0, "{[bad]}");
1520     r = MsiFormatRecord(0, hrec, buffer, &sz);
1521     ok( r == ERROR_SUCCESS, "format failed\n");
1522     ok( sz == 7, "size wrong(%i)\n",sz);
1523     ok( 0 == strcmp(buffer,"{[bad]}"), "wrong output (%s)\n",buffer);
1524
1525     sz = sizeof buffer;
1526     MsiRecordSetString(hrec, 0, "{abc{d[one]ef}"); /* missing final brace */
1527     r = MsiFormatRecord(0, hrec, buffer, &sz);
1528     ok( r == ERROR_SUCCESS, "format failed\n");
1529     ok( sz == 14, "size wrong(%i)\n",sz);
1530     ok( 0 == strcmp(buffer,"{abc{d[one]ef}"), "wrong output (%s)\n",buffer);
1531
1532     sz = sizeof buffer;
1533     MsiRecordSetString(hrec, 0, "{abc{d[one]ef}}");
1534     r = MsiFormatRecord(0, hrec, buffer, &sz);
1535     ok( r == ERROR_SUCCESS, "format failed\n");
1536     ok( sz == 15, "size wrong(%i)\n",sz);
1537     ok( 0 == strcmp(buffer,"{abc{d[one]ef}}"), "wrong output (%s)\n",buffer);
1538
1539     sz = sizeof buffer;
1540     MsiRecordSetString(hrec, 0, "{abc}{{def}hi{j[one]k}}");
1541     r = MsiFormatRecord(0, hrec, buffer, &sz);
1542     ok( r == ERROR_SUCCESS, "format failed\n");
1543     todo_wine
1544     {
1545         ok( sz == 5, "size wrong(%i)\n",sz);
1546         ok( 0 == strcmp(buffer,"{abc}"), "wrong output (%s)\n",buffer);
1547     }
1548
1549     sz = sizeof buffer;
1550     MsiRecordSetString(hrec, 0, "{{def}hi{j[one]k}}");
1551     r = MsiFormatRecord(0, hrec, buffer, &sz);
1552     ok( r == ERROR_SUCCESS, "format failed\n");
1553     todo_wine
1554     {
1555         ok( sz == 0, "size wrong(%i)\n",sz);
1556         ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
1557     }
1558
1559     sz = sizeof buffer;
1560     MsiRecordSetString(hrec, 0, "{{def}hi{jk}}");
1561     r = MsiFormatRecord(0, hrec, buffer, &sz);
1562     ok( r == ERROR_SUCCESS, "format failed\n");
1563     todo_wine
1564     {
1565         ok( sz == 0, "size wrong(%i)\n",sz);
1566         ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
1567     }
1568
1569     sz = sizeof buffer;
1570     MsiRecordSetString(hrec, 0, "{{{def}}hi{jk}}");
1571     r = MsiFormatRecord(0, hrec, buffer, &sz);
1572     ok( r == ERROR_SUCCESS, "format failed\n");
1573     todo_wine
1574     {
1575         ok( sz == 7, "size wrong(%i)\n",sz);
1576         ok( 0 == strcmp(buffer,"hi{jk}}"), "wrong output (%s)\n",buffer);
1577     }
1578
1579     sz = sizeof buffer;
1580     MsiRecordSetString(hrec, 0, "{{def}hi{{jk}}}");
1581     r = MsiFormatRecord(0, hrec, buffer, &sz);
1582     ok( r == ERROR_SUCCESS, "format failed\n");
1583     todo_wine
1584     {
1585         ok( sz == 1, "size wrong(%i)\n",sz);
1586         ok( 0 == strcmp(buffer,"}"), "wrong output (%s)\n",buffer);
1587     }
1588
1589     sz = sizeof buffer;
1590     MsiRecordSetString(hrec, 0, "{{def}{jk}}");
1591     r = MsiFormatRecord(0, hrec, buffer, &sz);
1592     ok( r == ERROR_SUCCESS, "format failed\n");
1593     todo_wine
1594     {
1595         ok( sz == 0, "size wrong(%i)\n",sz);
1596         ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
1597     }
1598
1599     sz = sizeof buffer;
1600     MsiRecordSetString(hrec, 0, "{{def}}");
1601     r = MsiFormatRecord(0, hrec, buffer, &sz);
1602     ok( r == ERROR_SUCCESS, "format failed\n");
1603     todo_wine
1604     {
1605         ok( sz == 0, "size wrong(%i)\n",sz);
1606         ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
1607     }
1608
1609     sz = sizeof buffer;
1610     MsiRecordSetString(hrec, 0, "{a{b}c}");
1611     r = MsiFormatRecord(0, hrec, buffer, &sz);
1612     ok( r == ERROR_SUCCESS, "format failed\n");
1613     ok( sz == 7, "size wrong(%i)\n",sz);
1614     ok( 0 == strcmp(buffer,"{a{b}c}"), "wrong output (%s)\n",buffer);
1615
1616     sz = sizeof buffer;
1617     MsiRecordSetString(hrec, 0, "{a{b}}");
1618     r = MsiFormatRecord(0, hrec, buffer, &sz);
1619     ok( r == ERROR_SUCCESS, "format failed\n");
1620     ok( sz == 6, "size wrong(%i)\n",sz);
1621     ok( 0 == strcmp(buffer,"{a{b}}"), "wrong output (%s)\n",buffer);
1622
1623     sz = sizeof buffer;
1624     MsiRecordSetString(hrec, 0, "{{b}c}");
1625     r = MsiFormatRecord(0, hrec, buffer, &sz);
1626     ok( r == ERROR_SUCCESS, "format failed\n");
1627     ok( sz == 6, "size wrong(%i)\n",sz);
1628     ok( 0 == strcmp(buffer,"{{b}c}"), "wrong output (%s)\n",buffer);
1629
1630     sz = sizeof buffer;
1631     MsiRecordSetString(hrec, 0, "{{{{}}}}");
1632     r = MsiFormatRecord(0, hrec, buffer, &sz);
1633     ok( r == ERROR_SUCCESS, "format failed\n");
1634     todo_wine
1635     {
1636         ok( sz == 2, "size wrong(%i)\n",sz);
1637         ok( 0 == strcmp(buffer,"}}"), "wrong output (%s)\n",buffer);
1638     }
1639
1640     sz = sizeof buffer;
1641     MsiRecordSetInteger(hrec, 1, 100);
1642     MsiRecordSetInteger(hrec, 2, -100);
1643     MsiRecordSetString(hrec, 0, "[1] [2]");
1644     r = MsiFormatRecord(0, hrec, buffer, &sz);
1645     ok( r == ERROR_SUCCESS, "format failed\n");
1646     ok( sz == 8, "size wrong(%i)\n",sz);
1647     ok( 0 == strcmp(buffer,"100 -100"), "wrong output (%s)\n",buffer);
1648
1649     MsiCloseHandle( hrec );
1650 }
1651
1652 static void test_formatrecord_package(void)
1653 {
1654     static const CHAR filename[] = "winetest.msi";
1655     char buffer[100];
1656     MSIHANDLE hrec;
1657     MSIHANDLE package;
1658     UINT r;
1659     DWORD sz=100;
1660
1661     package = helper_createpackage( filename );
1662     ok(package!=0, "Unable to create package\n");
1663
1664     hrec = MsiCreateRecord(12);
1665     ok( hrec, "failed to create record\n");
1666
1667     r = MsiFormatRecord(package, 0, NULL, NULL );
1668     ok( r == ERROR_INVALID_HANDLE, "wrong error\n");
1669
1670     r = MsiFormatRecord(package, hrec, NULL, NULL );
1671     ok( r == ERROR_SUCCESS, "format failed\n");
1672
1673     r = MsiRecordSetString(hrec,0,NULL);
1674     r = MsiRecordSetString(hrec,1,NULL);
1675     r = MsiRecordSetString(hrec,2,NULL);
1676     r = MsiRecordSetString(hrec,3,NULL);
1677     r = MsiRecordSetString(hrec,4,NULL);
1678     r = MsiRecordSetString(hrec,5,NULL);
1679     r = MsiRecordSetString(hrec,6,NULL);
1680     r = MsiRecordSetString(hrec,7,NULL);
1681     r = MsiRecordSetString(hrec,8,NULL);
1682     r = MsiRecordSetString(hrec,9,NULL);
1683     r = MsiRecordSetString(hrec,10,NULL);
1684     r = MsiRecordSetString(hrec,11,NULL);
1685     r = MsiRecordSetString(hrec,12,NULL);
1686     ok( r == ERROR_SUCCESS, "set string failed\n");
1687
1688     sz = sizeof buffer;
1689     r = MsiFormatRecord(package, hrec, buffer, &sz);
1690     ok( r == ERROR_SUCCESS, "format failed with empty buffer (%i)\n",r);
1691     ok( sz == 51, "size wrong (%i)\n",sz);
1692     ok( 0 == strcmp(buffer,"1:  2:  3:  4:  5:  6:  7:  8:  9:  10:  11:  12:  "), "wrong output(%s)\n",buffer);
1693
1694     r = MsiSetProperty(package, "prop", "val");
1695     ok( r == ERROR_SUCCESS, "failed to set propertY: %d\n", r);
1696
1697     r = MsiRecordSetString(hrec, 0, NULL);
1698     r = MsiRecordSetString(hrec, 1, "[2]");
1699     r = MsiRecordSetString(hrec, 2, "stuff");
1700     r = MsiRecordSetString(hrec, 3, "prop");
1701     r = MsiRecordSetString(hrec, 4, "[prop]");
1702     r = MsiRecordSetString(hrec, 5, "[noprop]");
1703     sz = sizeof buffer;
1704     r = MsiFormatRecord(package, hrec, buffer, &sz);
1705     ok( r == ERROR_SUCCESS, "format failed with empty buffer (%i)\n",r);
1706     todo_wine
1707     {
1708         ok( sz == 66, "size wrong (%i)\n",sz);
1709         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);
1710     }
1711
1712     /* now put play games with escaping */
1713     r = MsiRecordSetString(hrec, 0, "[1] [2] [\\3asdf]");
1714     r = MsiRecordSetString(hrec, 1, "boo");
1715     r = MsiRecordSetString(hrec, 2, "hoo");
1716     ok( r == ERROR_SUCCESS, "set string failed\n");
1717     sz = sizeof buffer;
1718     r = MsiFormatRecord(package, hrec, buffer, &sz);
1719     ok( r == ERROR_SUCCESS, "format failed\n");
1720     ok( sz == 9, "size wrong(%i)\n",sz);
1721     ok( 0 == strcmp(buffer,"boo hoo 3"), "wrong output (%s)\n",buffer);
1722
1723     r = MsiRecordSetString(hrec, 0, "[1] [2] [\\x]");
1724     r = MsiRecordSetString(hrec, 1, "boo");
1725     r = MsiRecordSetString(hrec, 2, "hoo");
1726     ok( r == ERROR_SUCCESS, "set string failed\n");
1727     sz = sizeof buffer;
1728     r = MsiFormatRecord(package, hrec, buffer, &sz);
1729     ok( r == ERROR_SUCCESS, "format failed\n");
1730     ok( sz == 9, "size wrong(%i)\n",sz);
1731     ok( 0 == strcmp(buffer,"boo hoo x"), "wrong output (%s)\n",buffer);
1732
1733     MsiRecordSetString(hrec, 0, "[\\x]");
1734     sz = sizeof buffer;
1735     r = MsiFormatRecord(package, hrec, buffer, &sz);
1736     ok( r == ERROR_SUCCESS, "format failed\n");
1737     ok( sz == 1, "size wrong: %d\n", sz);
1738     ok( 0 == strcmp(buffer,"x"), "wrong output: %s\n", buffer);
1739
1740     MsiRecordSetString(hrec, 0, "{\\x}");
1741     sz = sizeof buffer;
1742     r = MsiFormatRecord(package, hrec, buffer, &sz);
1743     ok( r == ERROR_SUCCESS, "format failed\n");
1744     ok( sz == 4, "size wrong: %d\n", sz);
1745     ok( 0 == strcmp(buffer,"{\\x}"), "wrong output: %s\n", buffer);
1746
1747     MsiRecordSetString(hrec, 0, "[abc\\x]");
1748     sz = sizeof buffer;
1749     r = MsiFormatRecord(package, hrec, buffer, &sz);
1750     ok( r == ERROR_SUCCESS, "format failed\n");
1751     ok( sz == 0, "size wrong: %d\n", sz);
1752     ok( 0 == strcmp(buffer,""), "wrong output: %s\n", buffer);
1753
1754     MsiRecordSetString(hrec, 0, "[abc\\xdef]");
1755     sz = sizeof buffer;
1756     r = MsiFormatRecord(package, hrec, buffer, &sz);
1757     ok( r == ERROR_SUCCESS, "format failed\n");
1758     ok( sz == 0, "size wrong: %d\n", sz);
1759     ok( 0 == strcmp(buffer,""), "wrong output: %s\n", buffer);
1760
1761     MsiRecordSetString(hrec, 0, "[\\[]Bracket Text[\\]]");
1762     sz = sizeof buffer;
1763     r = MsiFormatRecord(package, hrec, buffer, &sz);
1764     ok( r == ERROR_SUCCESS, "format failed\n");
1765     ok( sz == 14, "size wrong: %d\n", sz);
1766     ok( 0 == strcmp(buffer,"[Bracket Text]"), "wrong output: %s\n", buffer);
1767
1768     /* null characters */
1769     r = MsiRecordSetString(hrec, 0, "[1] [~] [2]");
1770     r = MsiRecordSetString(hrec, 1, "boo");
1771     r = MsiRecordSetString(hrec, 2, "hoo");
1772     ok( r == ERROR_SUCCESS, "set string failed\n");
1773     sz = sizeof buffer;
1774     r = MsiFormatRecord(package, hrec, buffer, &sz);
1775     ok( r == ERROR_SUCCESS, "format failed\n");
1776     ok( sz == 9, "size wrong\n");
1777     ok( 0 == strcmp(buffer,"boo "), "wrong output\n");
1778
1779     /* properties */
1780     r = MsiSetProperty(package,"dummy","Bork");
1781     ok( r == ERROR_SUCCESS, "set property failed\n");
1782     r = MsiRecordSetString(hrec, 0, "[1] [dummy] [2]");
1783     r = MsiRecordSetString(hrec, 1, "boo");
1784     r = MsiRecordSetString(hrec, 2, "hoo");
1785     ok( r == ERROR_SUCCESS, "set string failed\n");
1786     sz = sizeof buffer;
1787     r = MsiFormatRecord(package, hrec, buffer, &sz);
1788     ok( r == ERROR_SUCCESS, "format failed\n");
1789     ok( sz == 12, "size wrong\n");
1790     ok( 0 == strcmp(buffer,"boo Bork hoo"), "wrong output\n");
1791
1792     r = MsiRecordSetString(hrec, 0, "[1] [invalid] [2]");
1793     r = MsiRecordSetString(hrec, 1, "boo");
1794     r = MsiRecordSetString(hrec, 2, "hoo");
1795     ok( r == ERROR_SUCCESS, "set string failed\n");
1796     sz = sizeof buffer;
1797     r = MsiFormatRecord(package, hrec, buffer, &sz);
1798     ok( r == ERROR_SUCCESS, "format failed\n");
1799     ok( sz == 8, "size wrong\n");
1800     ok( 0 == strcmp(buffer,"boo  hoo"), "wrong output\n");
1801
1802
1803     /* nesting tests */
1804     r = MsiSetProperty(package,"dummya","foo");
1805     r = MsiSetProperty(package,"dummyb","baa");
1806     r = MsiSetProperty(package,"adummyc","whoa");
1807     ok( r == ERROR_SUCCESS, "set property failed\n");
1808     r = MsiRecordSetString(hrec, 0, "[dummy[1]] [dummy[2]] [[1]dummy[3]]");
1809     r = MsiRecordSetString(hrec, 1, "a");
1810     r = MsiRecordSetString(hrec, 2, "b");
1811     r = MsiRecordSetString(hrec, 3, "c");
1812     ok( r == ERROR_SUCCESS, "set string failed\n");
1813     sz = sizeof buffer;
1814     r = MsiFormatRecord(package, hrec, buffer, &sz);
1815     ok( r == ERROR_SUCCESS, "format failed\n");
1816     ok( sz == 12, "size wrong(%i)\n",sz);
1817     ok( 0 == strcmp(buffer,"foo baa whoa"), "wrong output (%s)\n",buffer);
1818
1819
1820     r = MsiSetProperty(package,"dummya","1");
1821     r = MsiSetProperty(package,"dummyb","[2]");
1822     ok( r == ERROR_SUCCESS, "set property failed\n");
1823     r = MsiRecordSetString(hrec, 0, "[dummya] [[dummya]] [dummyb]");
1824     r = MsiRecordSetString(hrec, 1, "aaa");
1825     r = MsiRecordSetString(hrec, 2, "bbb");
1826     r = MsiRecordSetString(hrec, 3, "ccc");
1827     ok( r == ERROR_SUCCESS, "set string failed\n");
1828     sz = sizeof buffer;
1829     r = MsiFormatRecord(package, hrec, buffer, &sz);
1830     ok( r == ERROR_SUCCESS, "format failed\n");
1831     ok( sz == 9, "size wrong(%i)\n",sz);
1832     ok( 0 == strcmp(buffer,"1 [1] [2]"), "wrong output (%s)\n",buffer);
1833
1834     r = MsiSetProperty(package,"dummya","1");
1835     r = MsiSetProperty(package,"dummyb","a");
1836     r = MsiSetProperty(package,"dummyc","\\blath");
1837     r = MsiSetProperty(package,"dummyd","[\\blath]");
1838     ok( r == ERROR_SUCCESS, "set property failed\n");
1839     r = MsiRecordSetString(hrec, 0, "[dummyc] [[dummyc]] [dummy[dummyb]]");
1840     r = MsiRecordSetString(hrec, 1, "aaa");
1841     r = MsiRecordSetString(hrec, 2, "bbb");
1842     r = MsiRecordSetString(hrec, 3, "ccc");
1843     ok( r == ERROR_SUCCESS, "set string failed\n");
1844     sz = sizeof buffer;
1845     r = MsiFormatRecord(package, hrec, buffer, &sz);
1846     ok( r == ERROR_SUCCESS, "format failed\n");
1847     ok( sz == 10, "size wrong(%i)\n",sz);
1848     ok( 0 == strcmp(buffer,"\\blath b 1"), "wrong output (%s)\n",buffer);
1849
1850     r = MsiRecordSetString(hrec, 0, "[1] [2] [[\\3asdf]]");
1851     r = MsiRecordSetString(hrec, 1, "boo");
1852     r = MsiRecordSetString(hrec, 2, "hoo");
1853     r = MsiRecordSetString(hrec, 3, "yeah");
1854     ok( r == ERROR_SUCCESS, "set string failed\n");
1855     sz = sizeof buffer;
1856     r = MsiFormatRecord(package, hrec, buffer, &sz);
1857     ok( r == ERROR_SUCCESS, "format failed\n");
1858     ok( sz == 11, "size wrong(%i)\n",sz);
1859     ok( 0 == strcmp(buffer,"boo hoo [3]"), "wrong output (%s)\n",buffer);
1860
1861     r = MsiRecordSetString(hrec, 0, "[1] [2] [[3]]");
1862     r = MsiRecordSetString(hrec, 1, "boo");
1863     r = MsiRecordSetString(hrec, 2, "hoo");
1864     r = MsiRecordSetString(hrec, 3, "\\help");
1865     ok( r == ERROR_SUCCESS, "set string failed\n");
1866     sz = sizeof buffer;
1867     r = MsiFormatRecord(package, hrec, buffer, &sz);
1868     ok( r == ERROR_SUCCESS, "format failed\n");
1869     ok( sz == 9, "size wrong(%i)\n",sz);
1870     ok( 0 == strcmp(buffer,"boo hoo h"), "wrong output (%s)\n",buffer);
1871
1872     /* nested properties */
1873     MsiSetProperty(package, "PropA", "surprise");
1874     MsiSetProperty(package, "PropB", "[PropA]");
1875     MsiSetProperty(package, "PropC", "[PropB]");
1876     sz = sizeof buffer;
1877     MsiRecordSetString(hrec, 0, "[PropC]");
1878     r = MsiFormatRecord(package, hrec, buffer, &sz);
1879     ok( r == ERROR_SUCCESS, "format failed\n");
1880     ok( sz == 7, "size wrong(%i)\n",sz);
1881     ok( 0 == strcmp(buffer,"[PropB]"), "wrong output (%s)\n",buffer);
1882
1883     MsiSetProperty(package, "PropA", "surprise");
1884     MsiSetProperty(package, "PropB", "PropA");
1885     MsiSetProperty(package, "PropC", "PropB");
1886     sz = sizeof buffer;
1887     MsiRecordSetString(hrec, 0, "[PropC]");
1888     r = MsiFormatRecord(package, hrec, buffer, &sz);
1889     ok( r == ERROR_SUCCESS, "format failed\n");
1890     ok( sz == 5, "size wrong(%i)\n",sz);
1891     ok( 0 == strcmp(buffer,"PropB"), "wrong output (%s)\n",buffer);
1892
1893     MsiSetProperty(package, "PropA", "surprise");
1894     MsiSetProperty(package, "PropB", "[PropA]");
1895     MsiSetProperty(package, "PropC", "[PropB]");
1896     sz = sizeof buffer;
1897     MsiRecordSetString(hrec, 0, "[[PropC]]");
1898     r = MsiFormatRecord(package, hrec, buffer, &sz);
1899     ok( r == ERROR_SUCCESS, "format failed\n");
1900     ok( sz == 0, "size wrong(%i)\n",sz);
1901     ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
1902
1903     MsiSetProperty(package, "PropA", "surprise");
1904     MsiSetProperty(package, "PropB", "[PropA]");
1905     MsiSetProperty(package, "PropC", "PropB");
1906     sz = sizeof buffer;
1907     MsiRecordSetString(hrec, 0, "[[PropC]]");
1908     r = MsiFormatRecord(package, hrec, buffer, &sz);
1909     ok( r == ERROR_SUCCESS, "format failed\n");
1910     ok( sz == 7, "size wrong(%i)\n",sz);
1911     ok( 0 == strcmp(buffer,"[PropA]"), "wrong output (%s)\n",buffer);
1912
1913     MsiSetProperty(package, "PropA", "surprise");
1914     MsiSetProperty(package, "PropB", "PropA");
1915     MsiSetProperty(package, "PropC", "PropB");
1916     sz = sizeof buffer;
1917     MsiRecordSetString(hrec, 0, "[[PropC]]");
1918     r = MsiFormatRecord(package, hrec, buffer, &sz);
1919     ok( r == ERROR_SUCCESS, "format failed\n");
1920     ok( sz == 5, "size wrong(%i)\n",sz);
1921     ok( 0 == strcmp(buffer,"PropA"), "wrong output (%s)\n",buffer);
1922
1923     MsiSetProperty(package, "PropA", "surprise");
1924     MsiSetProperty(package, "PropB", "PropA");
1925     MsiSetProperty(package, "PropC", "PropB");
1926     sz = sizeof buffer;
1927     MsiRecordSetString(hrec, 0, "[[[PropC]]]");
1928     r = MsiFormatRecord(package, hrec, buffer, &sz);
1929     ok( r == ERROR_SUCCESS, "format failed\n");
1930     ok( sz == 8, "size wrong(%i)\n",sz);
1931     ok( 0 == strcmp(buffer,"surprise"), "wrong output (%s)\n",buffer);
1932
1933     /* properties inside braces */
1934     sz = sizeof buffer;
1935     MsiRecordSetString(hrec, 0, "{abcd}");
1936     r = MsiFormatRecord(package, hrec, buffer, &sz);
1937     ok( r == ERROR_SUCCESS, "format failed\n");
1938     ok( sz == 6, "size wrong(%i)\n",sz);
1939     ok( 0 == strcmp(buffer,"{abcd}"), "wrong output (%s)\n",buffer);
1940
1941     MsiSetProperty(package, "one", "mercury");
1942     MsiSetProperty(package, "two", "venus");
1943     sz = sizeof buffer;
1944     MsiRecordSetString(hrec, 0, "{a[one]bc[two]de[one]f}");
1945     r = MsiFormatRecord(package, hrec, buffer, &sz);
1946     ok( r == ERROR_SUCCESS, "format failed\n");
1947     ok( sz == 25, "size wrong(%i)\n",sz);
1948     ok( 0 == strcmp(buffer,"amercurybcvenusdemercuryf"), "wrong output (%s)\n",buffer);
1949
1950     MsiSetProperty(package, "one", "mercury");
1951     MsiSetProperty(package, "two", "venus");
1952     MsiSetProperty(package, "bad", "");
1953     sz = sizeof buffer;
1954     MsiRecordSetString(hrec, 0, "{a[one]bc[bad]de[two]f}");
1955     r = MsiFormatRecord(package, hrec, buffer, &sz);
1956     ok( r == ERROR_SUCCESS, "format failed\n");
1957     ok( sz == 0, "size wrong(%i)\n",sz);
1958     ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
1959
1960     MsiSetProperty(package, "bad", "");
1961     sz = sizeof buffer;
1962     MsiRecordSetString(hrec, 0, "{[bad]}");
1963     r = MsiFormatRecord(package, hrec, buffer, &sz);
1964     ok( r == ERROR_SUCCESS, "format failed\n");
1965     ok( sz == 0, "size wrong(%i)\n",sz);
1966     ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
1967
1968     MsiSetProperty(package, "one", "mercury");
1969     sz = sizeof buffer;
1970     MsiRecordSetString(hrec, 0, "{abc{d[one]ef}"); /* missing final brace */
1971     r = MsiFormatRecord(package, hrec, buffer, &sz);
1972     ok( r == ERROR_SUCCESS, "format failed\n");
1973     ok( sz == 14, "size wrong(%i)\n",sz);
1974     ok( 0 == strcmp(buffer,"abc{dmercuryef"), "wrong output (%s)\n",buffer);
1975
1976     MsiSetProperty(package, "one", "mercury");
1977     sz = sizeof buffer;
1978     MsiRecordSetString(hrec, 0, "{abc{d[one]ef}}");
1979     r = MsiFormatRecord(package, hrec, buffer, &sz);
1980     ok( r == ERROR_SUCCESS, "format failed\n");
1981     ok( sz == 15, "size wrong(%i)\n",sz);
1982     ok( 0 == strcmp(buffer,"abc{dmercuryef}"), "wrong output (%s)\n",buffer);
1983
1984     MsiSetProperty(package, "one", "mercury");
1985     sz = sizeof buffer;
1986     MsiRecordSetString(hrec, 0, "{abc}{{def}hi{j[one]k}}");
1987     r = MsiFormatRecord(package, hrec, buffer, &sz);
1988     ok( r == ERROR_SUCCESS, "format failed\n");
1989     todo_wine
1990     {
1991         ok( sz == 5, "size wrong(%i)\n",sz);
1992         ok( 0 == strcmp(buffer,"{abc}"), "wrong output (%s)\n",buffer);
1993     }
1994
1995     MsiSetProperty(package, "one", "mercury");
1996     sz = sizeof buffer;
1997     MsiRecordSetString(hrec, 0, "{{def}hi{j[one]k}}");
1998     r = MsiFormatRecord(package, hrec, buffer, &sz);
1999     ok( r == ERROR_SUCCESS, "format failed\n");
2000     todo_wine
2001     {
2002         ok( sz == 0, "size wrong(%i)\n",sz);
2003         ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer);
2004     }
2005
2006     MsiCloseHandle(hrec);
2007
2008     r = MsiCloseHandle(package);
2009     ok(r==ERROR_SUCCESS, "Unable to close package\n");
2010
2011     DeleteFile( filename );
2012 }
2013
2014 static void test_formatrecord_tables(void)
2015 {
2016     MSIHANDLE hdb, hpkg, hrec;
2017     CHAR buf[MAX_PATH];
2018     CHAR curr_dir[MAX_PATH];
2019     CHAR expected[MAX_PATH];
2020     DWORD size;
2021     UINT r;
2022
2023     GetCurrentDirectory( MAX_PATH, curr_dir );
2024
2025     hdb = create_package_db();
2026     ok ( hdb, "failed to create package database\n");
2027
2028     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
2029     ok( r == ERROR_SUCCESS, "cannot add directory: %d\n", r);
2030
2031     r = add_directory_entry( hdb, "'ReallyLongDir', 'TARGETDIR', "
2032                              "'I am a really long directory'" );
2033     ok( r == ERROR_SUCCESS, "cannot add directory: %d\n", r);
2034
2035     r = create_feature_table( hdb );
2036     ok( r == ERROR_SUCCESS, "cannot create Feature table: %d\n", r);
2037
2038     r = add_feature_entry( hdb, "'occipitofrontalis', '', '', '', 2, 1, '', 0" );
2039     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2040
2041     r = create_component_table( hdb );
2042     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r);
2043
2044     r = add_component_entry( hdb, "'frontal', '', 'TARGETDIR', 0, '', 'frontal_file'" );
2045     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r);
2046
2047     r = add_component_entry( hdb, "'parietal', '', 'TARGETDIR', 1, '', 'parietal_file'" );
2048     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r);
2049
2050     r = add_component_entry( hdb, "'temporal', '', 'ReallyLongDir', 0, '', 'temporal_file'" );
2051     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r);
2052
2053     r = create_feature_components_table( hdb );
2054     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r);
2055
2056     r = add_feature_components_entry( hdb, "'occipitofrontalis', 'frontal'" );
2057     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r);
2058
2059     r = add_feature_components_entry( hdb, "'occipitofrontalis', 'parietal'" );
2060     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r);
2061
2062     r = add_feature_components_entry( hdb, "'occipitofrontalis', 'temporal'" );
2063     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r);
2064
2065     r = create_file_table( hdb );
2066     ok( r == ERROR_SUCCESS, "cannot create File table: %d\n", r);
2067
2068     r = add_file_entry( hdb, "'frontal_file', 'frontal', 'frontal.txt', 0, '', '1033', 8192, 1" );
2069     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
2070
2071     r = add_file_entry( hdb, "'parietal_file', 'parietal', 'parietal.txt', 0, '', '1033', 8192, 1" );
2072     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
2073
2074     r = add_file_entry( hdb, "'temporal_file', 'temporal', 'temporal.txt', 0, '', '1033', 8192, 1" );
2075     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
2076
2077     r = create_custom_action_table( hdb );
2078     ok( r == ERROR_SUCCESS, "cannot create CustomAction table: %d\n", r);
2079
2080     r = add_custom_action_entry( hdb, "'MyCustom', 51, 'prop', '[!temporal_file]'" );
2081     ok( r == ERROR_SUCCESS, "cannt add custom action: %d\n", r);
2082
2083     r = add_custom_action_entry( hdb, "'EscapeIt1', 51, 'prop', '[\\[]Bracket Text[\\]]'" );
2084     ok( r == ERROR_SUCCESS, "cannt add custom action: %d\n", r);
2085
2086     r = add_custom_action_entry( hdb, "'EscapeIt2', 51, 'prop', '[\\xabcd]'" );
2087     ok( r == ERROR_SUCCESS, "cannt add custom action: %d\n", r);
2088
2089     r = add_custom_action_entry( hdb, "'EscapeIt3', 51, 'prop', '[abcd\\xefgh]'" );
2090     ok( r == ERROR_SUCCESS, "cannt add custom action: %d\n", r);
2091
2092     hpkg = package_from_db( hdb );
2093     ok( hpkg, "failed to create package\n");
2094
2095     MsiCloseHandle( hdb );
2096
2097     r = MsiSetPropertyA( hpkg, "imaprop", "ringer" );
2098     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2099
2100     hrec = MsiCreateRecord( 1 );
2101
2102     /* property doesn't exist */
2103     size = MAX_PATH;
2104     /*MsiRecordSetString( hrec, 0, "[1]" ); */
2105     MsiRecordSetString( hrec, 1, "[idontexist]" );
2106     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2107     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2108     ok( !lstrcmp( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2109
2110     /* property exists */
2111     size = MAX_PATH;
2112     MsiRecordSetString( hrec, 1, "[imaprop]" );
2113     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2114     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2115     ok( !lstrcmp( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2116
2117     /* environment variable doesn't exist */
2118     size = MAX_PATH;
2119     MsiRecordSetString( hrec, 1, "[%idontexist]" );
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     /* environment variable exists */
2125     size = MAX_PATH;
2126     SetEnvironmentVariable( "crazyvar", "crazyval" );
2127     MsiRecordSetString( hrec, 1, "[%crazyvar]" );
2128     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2129     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2130     ok( !lstrcmp( buf, "1: crazyval " ), "Expected '1: crazyval ', got %s\n", buf );
2131
2132     /* file key before CostInitialize */
2133     size = MAX_PATH;
2134     MsiRecordSetString( hrec, 1, "[#frontal_file]" );
2135     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2136     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2137     ok( !lstrcmp( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2138
2139     r = MsiDoAction(hpkg, "CostInitialize");
2140     ok( r == ERROR_SUCCESS, "CostInitialize failed: %d\n", r);
2141
2142     r = MsiDoAction(hpkg, "FileCost");
2143     ok( r == ERROR_SUCCESS, "FileCost failed: %d\n", r);
2144
2145     r = MsiDoAction(hpkg, "CostFinalize");
2146     ok( r == ERROR_SUCCESS, "CostFinalize failed: %d\n", r);
2147
2148     /* frontal full file key */
2149     size = MAX_PATH;
2150     MsiRecordSetString( hrec, 1, "[#frontal_file]" );
2151     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2152     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2153     ok( !lstrcmp( buf, "1: C:\\frontal.txt " ), "Expected '1: C:\\frontal.txt ', got %s\n", buf);
2154
2155     /* frontal short file key */
2156     size = MAX_PATH;
2157     MsiRecordSetString( hrec, 1, "[!frontal_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:\\frontal.txt " ), "Expected '1: C:\\frontal.txt ', got %s\n", buf);
2161
2162     /* temporal full file key */
2163     size = MAX_PATH;
2164     MsiRecordSetString( hrec, 1, "[#temporal_file]" );
2165     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2166     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2167     ok( !lstrcmp( buf, "1: C:\\I am a really long directory\\temporal.txt " ),
2168         "Expected '1: C:\\I am a really long directory\\temporal.txt ', got %s\n", buf);
2169
2170     /* temporal short file key */
2171     size = MAX_PATH;
2172     MsiRecordSetString( hrec, 1, "[!temporal_file]" );
2173     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2174     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2175     ok( !lstrcmp( buf, "1: C:\\I am a really long directory\\temporal.txt " ),
2176         "Expected '1: C:\\I am a really long directory\\temporal.txt ', got %s\n", buf);
2177
2178     /* custom action 51, files don't exist */
2179     r = MsiDoAction( hpkg, "MyCustom" );
2180     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2181
2182     size = MAX_PATH;
2183     r = MsiGetProperty( hpkg, "prop", buf, &size );
2184     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
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     CreateDirectory( "C:\\I am a really long directory", NULL );
2189     create_test_file( "C:\\I am a really long directory\\temporal.txt" );
2190
2191     /* custom action 51, files exist */
2192     r = MsiDoAction( hpkg, "MyCustom" );
2193     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2194
2195     size = MAX_PATH;
2196     r = MsiGetProperty( hpkg, "prop", buf, &size );
2197     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2198     todo_wine
2199     {
2200         ok( !lstrcmp( buf, "C:\\I am a really long directory\\temporal.txt" ),
2201             "Expected 'C:\\I am a really long directory\\temporal.txt', got %s\n", buf);
2202     }
2203
2204     /* custom action 51, escaped text 1 */
2205     r = MsiDoAction( hpkg, "EscapeIt1" );
2206     ok( r == ERROR_SUCCESS, "EscapeIt failed: %d\n", r);
2207
2208     size = MAX_PATH;
2209     r = MsiGetProperty( hpkg, "prop", buf, &size );
2210     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2211     ok( !lstrcmp( buf, "[Bracket Text]" ), "Expected '[Bracket Text]', got %s\n", buf);
2212
2213     /* custom action 51, escaped text 2 */
2214     r = MsiDoAction( hpkg, "EscapeIt2" );
2215     ok( r == ERROR_SUCCESS, "EscapeIt failed: %d\n", r);
2216
2217     size = MAX_PATH;
2218     r = MsiGetProperty( hpkg, "prop", buf, &size );
2219     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2220     ok( !lstrcmp( buf, "x" ), "Expected 'x', got %s\n", buf);
2221
2222     /* custom action 51, escaped text 3 */
2223     r = MsiDoAction( hpkg, "EscapeIt3" );
2224     ok( r == ERROR_SUCCESS, "EscapeIt failed: %d\n", r);
2225
2226     size = MAX_PATH;
2227     r = MsiGetProperty( hpkg, "prop", buf, &size );
2228     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2229     ok( !lstrcmp( buf, "" ), "Expected '', got %s\n", buf);
2230
2231     /* component with INSTALLSTATE_LOCAL */
2232     size = MAX_PATH;
2233     MsiRecordSetString( hrec, 1, "[$temporal]" );
2234     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2235     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2236     ok( !lstrcmp( buf, "1: C:\\I am a really long directory\\ " ),
2237         "Expected '1: C:\\I am a really long directory\\ ', got %s\n", buf);
2238
2239     r = MsiSetComponentState( hpkg, "temporal", INSTALLSTATE_SOURCE );
2240     ok( r == ERROR_SUCCESS, "failed to set install state: %d\n", r);
2241
2242     /* component with INSTALLSTATE_SOURCE */
2243     lstrcpy( expected, "1: " );
2244     lstrcat( expected, curr_dir );
2245     lstrcat( expected, "\\ " );
2246     size = MAX_PATH;
2247     MsiRecordSetString( hrec, 1, "[$parietal]" );
2248     r = MsiFormatRecord( hpkg, hrec, buf, &size );
2249     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2250     ok( !lstrcmp( buf, expected ), "Expected '%s', got %s\n", expected, buf);
2251
2252     DeleteFile( "C:\\I am a really long directory\\temporal.txt" );
2253     RemoveDirectory( "C:\\I am a really long directory" );
2254
2255     MsiCloseHandle( hrec );
2256     MsiCloseHandle( hpkg );
2257     DeleteFile( msifile );
2258 }
2259
2260 static void test_processmessage(void)
2261 {
2262     static const CHAR filename[] = "winetest.msi";
2263     MSIHANDLE hrec;
2264     MSIHANDLE package;
2265     int r;
2266
2267     package = helper_createpackage( filename );
2268     ok(package!=0, "Unable to create package\n");
2269
2270     hrec = MsiCreateRecord(3);
2271     ok( hrec, "failed to create record\n");
2272
2273     r = MsiRecordSetString(hrec, 1, "");
2274     ok( r == ERROR_SUCCESS, "set string failed\n");
2275
2276     r = MsiProcessMessage(package, INSTALLMESSAGE_ACTIONSTART, hrec);
2277     ok( r == IDOK, "expected IDOK, got %i\n", r);
2278
2279     MsiCloseHandle(hrec);
2280     MsiCloseHandle(package);
2281
2282     DeleteFile(filename);
2283 }
2284
2285 START_TEST(format)
2286 {
2287     test_createpackage();
2288     test_formatrecord();
2289     test_formatrecord_package();
2290     test_formatrecord_tables();
2291     test_processmessage();
2292 }