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