msi: Don't evaluate the condition table when there are overrides.
[wine] / dlls / msi / tests / install.c
1 /*
2  * Copyright (C) 2006 James Hawkins
3  *
4  * A test program for installing MSI products.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define _WIN32_MSI 300
22 #define COBJMACROS
23
24 #include <stdio.h>
25
26 #include <windows.h>
27 #include <msiquery.h>
28 #include <msidefs.h>
29 #include <msi.h>
30 #include <fci.h>
31 #include <objidl.h>
32 #include <srrestoreptapi.h>
33
34 #include "wine/test.h"
35
36 static UINT (WINAPI *pMsiQueryComponentStateA)
37     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
38 static UINT (WINAPI *pMsiSetExternalUIRecord)
39     (INSTALLUI_HANDLER_RECORD, DWORD, LPVOID, PINSTALLUI_HANDLER_RECORD);
40 static UINT (WINAPI *pMsiSourceListEnumSourcesA)
41     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPSTR, LPDWORD);
42 static UINT (WINAPI *pMsiSourceListGetInfoA)
43     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
44
45 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
46
47 static HMODULE hsrclient = 0;
48 static BOOL (WINAPI *pSRRemoveRestorePoint)(DWORD);
49 static BOOL (WINAPI *pSRSetRestorePointA)(RESTOREPOINTINFOA*, STATEMGRSTATUS*);
50
51 static BOOL on_win9x = FALSE;
52
53 static const char *msifile = "msitest.msi";
54 static const char *msifile2 = "winetest2.msi";
55 static const char *mstfile = "winetest.mst";
56 static CHAR CURR_DIR[MAX_PATH];
57 static CHAR PROG_FILES_DIR[MAX_PATH];
58 static CHAR COMMON_FILES_DIR[MAX_PATH];
59
60 /* msi database data */
61
62 static const CHAR component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
63                                     "s72\tS38\ts72\ti2\tS255\tS72\n"
64                                     "Component\tComponent\n"
65                                     "Five\t{8CC92E9D-14B2-4CA4-B2AA-B11D02078087}\tNEWDIR\t2\t\tfive.txt\n"
66                                     "Four\t{FD37B4EA-7209-45C0-8917-535F35A2F080}\tCABOUTDIR\t2\t\tfour.txt\n"
67                                     "One\t{783B242E-E185-4A56-AF86-C09815EC053C}\tMSITESTDIR\t2\tNOT REINSTALL\tone.txt\n"
68                                     "Three\t{010B6ADD-B27D-4EDD-9B3D-34C4F7D61684}\tCHANGEDDIR\t2\t\tthree.txt\n"
69                                     "Two\t{BF03D1A6-20DA-4A65-82F3-6CAC995915CE}\tFIRSTDIR\t2\t\ttwo.txt\n"
70                                     "dangler\t{6091DF25-EF96-45F1-B8E9-A9B1420C7A3C}\tTARGETDIR\t4\t\tregdata\n"
71                                     "component\t\tMSITESTDIR\t0\t1\tfile\n"
72                                     "service_comp\t\tMSITESTDIR\t0\t1\tservice_file";
73
74 static const CHAR directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
75                                     "s72\tS72\tl255\n"
76                                     "Directory\tDirectory\n"
77                                     "CABOUTDIR\tMSITESTDIR\tcabout\n"
78                                     "CHANGEDDIR\tMSITESTDIR\tchanged:second\n"
79                                     "FIRSTDIR\tMSITESTDIR\tfirst\n"
80                                     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
81                                     "NEWDIR\tCABOUTDIR\tnew\n"
82                                     "ProgramFilesFolder\tTARGETDIR\t.\n"
83                                     "TARGETDIR\t\tSourceDir";
84
85 static const CHAR feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
86                                   "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
87                                   "Feature\tFeature\n"
88                                   "Five\t\tFive\tThe Five Feature\t5\t3\tNEWDIR\t0\n"
89                                   "Four\t\tFour\tThe Four Feature\t4\t3\tCABOUTDIR\t0\n"
90                                   "One\t\tOne\tThe One Feature\t1\t3\tMSITESTDIR\t0\n"
91                                   "Three\t\tThree\tThe Three Feature\t3\t3\tCHANGEDDIR\t0\n"
92                                   "Two\t\tTwo\tThe Two Feature\t2\t3\tFIRSTDIR\t0\n"
93                                   "feature\t\t\t\t2\t1\tTARGETDIR\t0\n"
94                                   "service_feature\t\t\t\t2\t1\tTARGETDIR\t0";
95
96 static const CHAR feature_comp_dat[] = "Feature_\tComponent_\n"
97                                        "s38\ts72\n"
98                                        "FeatureComponents\tFeature_\tComponent_\n"
99                                        "Five\tFive\n"
100                                        "Four\tFour\n"
101                                        "One\tOne\n"
102                                        "Three\tThree\n"
103                                        "Two\tTwo\n"
104                                        "feature\tcomponent\n"
105                                        "service_feature\tservice_comp\n";
106
107 static const CHAR file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
108                                "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
109                                "File\tFile\n"
110                                "five.txt\tFive\tfive.txt\t1000\t\t\t16384\t5\n"
111                                "four.txt\tFour\tfour.txt\t1000\t\t\t16384\t4\n"
112                                "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n"
113                                "three.txt\tThree\tthree.txt\t1000\t\t\t0\t3\n"
114                                "two.txt\tTwo\ttwo.txt\t1000\t\t\t0\t2\n"
115                                "file\tcomponent\tfilename\t100\t\t\t8192\t1\n"
116                                "service_file\tservice_comp\tservice.exe\t100\t\t\t8192\t1";
117
118 static const CHAR install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
119                                            "s72\tS255\tI2\n"
120                                            "InstallExecuteSequence\tAction\n"
121                                            "AllocateRegistrySpace\tNOT Installed\t1550\n"
122                                            "CostFinalize\t\t1000\n"
123                                            "CostInitialize\t\t800\n"
124                                            "FileCost\t\t900\n"
125                                            "ResolveSource\t\t950\n"
126                                            "MoveFiles\t\t1700\n"
127                                            "InstallFiles\t\t4000\n"
128                                            "DuplicateFiles\t\t4500\n"
129                                            "WriteEnvironmentStrings\t\t4550\n"
130                                            "CreateShortcuts\t\t4600\n"
131                                            "InstallServices\t\t5000\n"
132                                            "InstallFinalize\t\t6600\n"
133                                            "InstallInitialize\t\t1500\n"
134                                            "InstallValidate\t\t1400\n"
135                                            "LaunchConditions\t\t100\n"
136                                            "WriteRegistryValues\tSourceDir And SOURCEDIR\t5000";
137
138 static const CHAR media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
139                                 "i2\ti4\tL64\tS255\tS32\tS72\n"
140                                 "Media\tDiskId\n"
141                                 "1\t3\t\t\tDISK1\t\n"
142                                 "2\t5\t\tmsitest.cab\tDISK2\t\n";
143
144 static const CHAR property_dat[] = "Property\tValue\n"
145                                    "s72\tl0\n"
146                                    "Property\tProperty\n"
147                                    "DefaultUIFont\tDlgFont8\n"
148                                    "HASUIRUN\t0\n"
149                                    "INSTALLLEVEL\t3\n"
150                                    "InstallMode\tTypical\n"
151                                    "Manufacturer\tWine\n"
152                                    "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
153                                    "ProductCode\t{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}\n"
154                                    "ProductID\tnone\n"
155                                    "ProductLanguage\t1033\n"
156                                    "ProductName\tMSITEST\n"
157                                    "ProductVersion\t1.1.1\n"
158                                    "PROMPTROLLBACKCOST\tP\n"
159                                    "Setup\tSetup\n"
160                                    "UpgradeCode\t{4C0EAA15-0264-4E5A-8758-609EF142B92D}\n"
161                                    "AdminProperties\tPOSTADMIN\n"
162                                    "ROOTDRIVE\tC:\\\n"
163                                    "SERVNAME\tTestService\n"
164                                    "SERVDISP\tTestServiceDisp\n";
165
166 static const CHAR aup_property_dat[] = "Property\tValue\n"
167                                        "s72\tl0\n"
168                                        "Property\tProperty\n"
169                                        "DefaultUIFont\tDlgFont8\n"
170                                        "HASUIRUN\t0\n"
171                                        "ALLUSERS\t1\n"
172                                        "INSTALLLEVEL\t3\n"
173                                        "InstallMode\tTypical\n"
174                                        "Manufacturer\tWine\n"
175                                        "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
176                                        "ProductCode\t{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}\n"
177                                        "ProductID\tnone\n"
178                                        "ProductLanguage\t1033\n"
179                                        "ProductName\tMSITEST\n"
180                                        "ProductVersion\t1.1.1\n"
181                                        "PROMPTROLLBACKCOST\tP\n"
182                                        "Setup\tSetup\n"
183                                        "UpgradeCode\t{4C0EAA15-0264-4E5A-8758-609EF142B92D}\n"
184                                        "AdminProperties\tPOSTADMIN\n"
185                                        "ROOTDRIVE\tC:\\\n"
186                                        "SERVNAME\tTestService\n"
187                                        "SERVDISP\tTestServiceDisp\n";
188
189 static const CHAR aup2_property_dat[] = "Property\tValue\n"
190                                         "s72\tl0\n"
191                                         "Property\tProperty\n"
192                                         "DefaultUIFont\tDlgFont8\n"
193                                         "HASUIRUN\t0\n"
194                                         "ALLUSERS\t2\n"
195                                         "INSTALLLEVEL\t3\n"
196                                         "InstallMode\tTypical\n"
197                                         "Manufacturer\tWine\n"
198                                         "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
199                                         "ProductCode\t{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}\n"
200                                         "ProductID\tnone\n"
201                                         "ProductLanguage\t1033\n"
202                                         "ProductName\tMSITEST\n"
203                                         "ProductVersion\t1.1.1\n"
204                                         "PROMPTROLLBACKCOST\tP\n"
205                                         "Setup\tSetup\n"
206                                         "UpgradeCode\t{4C0EAA15-0264-4E5A-8758-609EF142B92D}\n"
207                                         "AdminProperties\tPOSTADMIN\n"
208                                         "ROOTDRIVE\tC:\\\n"
209                                         "SERVNAME\tTestService\n"
210                                         "SERVDISP\tTestServiceDisp\n";
211
212 static const CHAR shortcut_dat[] = "Shortcut\tDirectory_\tName\tComponent_\tTarget\tArguments\tDescription\tHotkey\tIcon_\tIconIndex\tShowCmd\tWkDir\n"
213                                    "s72\ts72\tl128\ts72\ts72\tS255\tL255\tI2\tS72\tI2\tI2\tS72\n"
214                                    "Shortcut\tShortcut\n"
215                                    "Shortcut\tMSITESTDIR\tShortcut\tcomponent\tShortcut\t\tShortcut\t\t\t\t\t\n";
216
217 static const CHAR environment_dat[] = "Environment\tName\tValue\tComponent_\n"
218                                       "s72\tl255\tL255\ts72\n"
219                                       "Environment\tEnvironment\n"
220                                       "Var1\t=-MSITESTVAR1\t1\tOne\n"
221                                       "Var2\tMSITESTVAR2\t1\tOne\n"
222                                       "Var3\t=-MSITESTVAR3\t1\tOne\n"
223                                       "Var4\tMSITESTVAR4\t1\tOne\n"
224                                       "Var5\t-MSITESTVAR5\t\tOne\n"
225                                       "Var6\tMSITESTVAR6\t\tOne\n"
226                                       "Var7\t!-MSITESTVAR7\t\tOne\n"
227                                       "Var8\t!-*MSITESTVAR8\t\tOne\n"
228                                       "Var9\t=-MSITESTVAR9\t\tOne\n"
229                                       "Var10\t=MSITESTVAR10\t\tOne\n"
230                                       "Var11\t+-MSITESTVAR11\t[~];1\tOne\n"
231                                       "Var12\t+-MSITESTVAR11\t[~];2\tOne\n"
232                                       "Var13\t+-MSITESTVAR12\t[~];1\tOne\n"
233                                       "Var14\t=MSITESTVAR13\t[~];1\tOne\n"
234                                       "Var15\t=MSITESTVAR13\t[~];2\tOne\n"
235                                       "Var16\t=MSITESTVAR14\t;1;\tOne\n"
236                                       "Var17\t=MSITESTVAR15\t;;1;;\tOne\n"
237                                       "Var18\t=MSITESTVAR16\t 1 \tOne\n"
238                                       "Var19\t+-MSITESTVAR17\t1\tOne\n"
239                                       "Var20\t+-MSITESTVAR17\t;;2;;[~]\tOne\n"
240                                       "Var21\t+-MSITESTVAR18\t1\tOne\n"
241                                       "Var22\t+-MSITESTVAR18\t[~];;2;;\tOne\n"
242                                       "Var23\t+-MSITESTVAR19\t1\tOne\n"
243                                       "Var24\t+-MSITESTVAR19\t[~]2\tOne\n"
244                                       "Var25\t+-MSITESTVAR20\t1\tOne\n"
245                                       "Var26\t+-MSITESTVAR20\t2[~]\tOne\n";
246
247 /* Expected results, starting from MSITESTVAR11 onwards */
248 static const CHAR *environment_dat_results[] = {"1;2",    /*MSITESTVAR11*/
249                                                 "1",      /*MSITESTVAR12*/
250                                                 "1;2",    /*MSITESTVAR13*/
251                                                 ";1;",    /*MSITESTVAR14*/
252                                                 ";;1;;",  /*MSITESTVAR15*/
253                                                 " 1 ",    /*MSITESTVAR16*/
254                                                 ";;2;;1", /*MSITESTVAR17*/
255                                                 "1;;2;;", /*MSITESTVAR18*/
256                                                 "1",      /*MSITESTVAR19*/
257                                                 "1",      /*MSITESTVAR20*/
258                                                 NULL};
259
260 static const CHAR condition_dat[] = "Feature_\tLevel\tCondition\n"
261                                     "s38\ti2\tS255\n"
262                                     "Condition\tFeature_\tLevel\n"
263                                     "One\t4\t1\n";
264
265 static const CHAR up_property_dat[] = "Property\tValue\n"
266                                       "s72\tl0\n"
267                                       "Property\tProperty\n"
268                                       "DefaultUIFont\tDlgFont8\n"
269                                       "HASUIRUN\t0\n"
270                                       "INSTALLLEVEL\t3\n"
271                                       "InstallMode\tTypical\n"
272                                       "Manufacturer\tWine\n"
273                                       "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
274                                       "ProductCode\t{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}\n"
275                                       "ProductID\tnone\n"
276                                       "ProductLanguage\t1033\n"
277                                       "ProductName\tMSITEST\n"
278                                       "ProductVersion\t1.1.1\n"
279                                       "PROMPTROLLBACKCOST\tP\n"
280                                       "Setup\tSetup\n"
281                                       "UpgradeCode\t{4C0EAA15-0264-4E5A-8758-609EF142B92D}\n"
282                                       "AdminProperties\tPOSTADMIN\n"
283                                       "ROOTDRIVE\tC:\\\n"
284                                       "SERVNAME\tTestService\n"
285                                       "SERVDISP\tTestServiceDisp\n"
286                                       "RemovePreviousVersions\t1\n";
287
288 static const CHAR up2_property_dat[] = "Property\tValue\n"
289                                        "s72\tl0\n"
290                                        "Property\tProperty\n"
291                                        "DefaultUIFont\tDlgFont8\n"
292                                        "HASUIRUN\t0\n"
293                                        "INSTALLLEVEL\t3\n"
294                                        "InstallMode\tTypical\n"
295                                        "Manufacturer\tWine\n"
296                                        "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
297                                        "ProductCode\t{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}\n"
298                                        "ProductID\tnone\n"
299                                        "ProductLanguage\t1033\n"
300                                        "ProductName\tMSITEST\n"
301                                        "ProductVersion\t1.1.2\n"
302                                        "PROMPTROLLBACKCOST\tP\n"
303                                        "Setup\tSetup\n"
304                                        "UpgradeCode\t{4C0EAA15-0264-4E5A-8758-609EF142B92D}\n"
305                                        "AdminProperties\tPOSTADMIN\n"
306                                        "ROOTDRIVE\tC:\\\n"
307                                        "SERVNAME\tTestService\n"
308                                        "SERVDISP\tTestServiceDisp\n";
309
310 static const CHAR up3_property_dat[] = "Property\tValue\n"
311                                        "s72\tl0\n"
312                                        "Property\tProperty\n"
313                                        "DefaultUIFont\tDlgFont8\n"
314                                        "HASUIRUN\t0\n"
315                                        "INSTALLLEVEL\t3\n"
316                                        "InstallMode\tTypical\n"
317                                        "Manufacturer\tWine\n"
318                                        "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
319                                        "ProductCode\t{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}\n"
320                                        "ProductID\tnone\n"
321                                        "ProductLanguage\t1033\n"
322                                        "ProductName\tMSITEST\n"
323                                        "ProductVersion\t1.1.2\n"
324                                        "PROMPTROLLBACKCOST\tP\n"
325                                        "Setup\tSetup\n"
326                                        "UpgradeCode\t{4C0EAA15-0264-4E5A-8758-609EF142B92D}\n"
327                                        "AdminProperties\tPOSTADMIN\n"
328                                        "ROOTDRIVE\tC:\\\n"
329                                        "SERVNAME\tTestService\n"
330                                        "SERVDISP\tTestServiceDisp\n"
331                                        "RemovePreviousVersions\t1\n";
332
333 static const CHAR registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
334                                    "s72\ti2\tl255\tL255\tL0\ts72\n"
335                                    "Registry\tRegistry\n"
336                                    "Apples\t2\tSOFTWARE\\Wine\\msitest\tName\timaname\tOne\n"
337                                    "Oranges\t2\tSOFTWARE\\Wine\\msitest\tnumber\t#314\tTwo\n"
338                                    "regdata\t2\tSOFTWARE\\Wine\\msitest\tblah\tbad\tdangler\n"
339                                    "OrderTest\t2\tSOFTWARE\\Wine\\msitest\tOrderTestName\tOrderTestValue\tcomponent";
340
341 static const CHAR service_install_dat[] = "ServiceInstall\tName\tDisplayName\tServiceType\tStartType\tErrorControl\t"
342                                           "LoadOrderGroup\tDependencies\tStartName\tPassword\tArguments\tComponent_\tDescription\n"
343                                           "s72\ts255\tL255\ti4\ti4\ti4\tS255\tS255\tS255\tS255\tS255\ts72\tL255\n"
344                                           "ServiceInstall\tServiceInstall\n"
345                                           "TestService\t[SERVNAME]\t[SERVDISP]\t2\t3\t0\t\t\tTestService\t\t\tservice_comp\t\t";
346
347 static const CHAR service_control_dat[] = "ServiceControl\tName\tEvent\tArguments\tWait\tComponent_\n"
348                                           "s72\tl255\ti2\tL255\tI2\ts72\n"
349                                           "ServiceControl\tServiceControl\n"
350                                           "ServiceControl\tTestService\t8\t\t0\tservice_comp";
351
352 /* tables for test_continuouscabs */
353 static const CHAR cc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
354                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
355                                        "Component\tComponent\n"
356                                        "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
357                                        "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
358                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
359
360 static const CHAR cc2_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
361                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
362                                         "Component\tComponent\n"
363                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
364                                         "augustus\t\tMSITESTDIR\t0\t0\taugustus\n"
365                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
366
367 static const CHAR cc_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
368                                      "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
369                                      "Feature\tFeature\n"
370                                      "feature\t\t\t\t2\t1\tTARGETDIR\t0";
371
372 static const CHAR cc_feature_comp_dat[] = "Feature_\tComponent_\n"
373                                           "s38\ts72\n"
374                                           "FeatureComponents\tFeature_\tComponent_\n"
375                                           "feature\tmaximus\n"
376                                           "feature\taugustus\n"
377                                           "feature\tcaesar";
378
379 static const CHAR cc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
380                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
381                                   "File\tFile\n"
382                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
383                                   "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
384                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12";
385
386 static const CHAR cc2_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
387                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
388                                    "File\tFile\n"
389                                    "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
390                                    "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
391                                    "tiberius\tmaximus\ttiberius\t500\t\t\t16384\t3\n"
392                                    "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12";
393
394 static const CHAR cc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
395                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
396                                    "Media\tDiskId\n"
397                                    "1\t10\t\ttest1.cab\tDISK1\t\n"
398                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
399                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
400
401 static const CHAR co_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
402                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
403                                   "File\tFile\n"
404                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
405                                   "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
406                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
407
408 static const CHAR co_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
409                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
410                                    "Media\tDiskId\n"
411                                    "1\t10\t\ttest1.cab\tDISK1\t\n"
412                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
413                                    "3\t3\t\ttest3.cab\tDISK3\t\n";
414
415 static const CHAR co2_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
416                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
417                                     "Media\tDiskId\n"
418                                     "1\t10\t\ttest1.cab\tDISK1\t\n"
419                                     "2\t12\t\ttest3.cab\tDISK3\t\n"
420                                     "3\t2\t\ttest2.cab\tDISK2\t\n";
421
422 static const CHAR mm_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
423                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
424                                   "File\tFile\n"
425                                   "maximus\tmaximus\tmaximus\t500\t\t\t512\t1\n"
426                                   "augustus\taugustus\taugustus\t500\t\t\t512\t2\n"
427                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
428
429 static const CHAR mm_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
430                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
431                                    "Media\tDiskId\n"
432                                    "1\t3\t\ttest1.cab\tDISK1\t\n";
433
434 static const CHAR ss_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
435                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
436                                    "Media\tDiskId\n"
437                                    "1\t2\t\ttest1.cab\tDISK1\t\n"
438                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
439                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
440
441 /* tables for test_uiLevelFlags */
442 static const CHAR ui_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
443                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
444                                        "Component\tComponent\n"
445                                        "maximus\t\tMSITESTDIR\t0\tHASUIRUN=1\tmaximus\n"
446                                        "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
447                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
448
449 static const CHAR ui_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
450                                            "s72\tS255\tI2\n"
451                                            "InstallUISequence\tAction\n"
452                                            "SetUIProperty\t\t5\n"
453                                            "ExecuteAction\t\t1100\n";
454
455 static const CHAR ui_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
456                                            "s72\ti2\tS64\tS0\tS255\n"
457                                            "CustomAction\tAction\n"
458                                            "SetUIProperty\t51\tHASUIRUN\t1\t\n";
459
460 static const CHAR rof_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
461                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
462                                         "Component\tComponent\n"
463                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n";
464
465 static const CHAR rof_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
466                                       "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
467                                       "Feature\tFeature\n"
468                                       "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
469                                       "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
470
471 static const CHAR rof_feature_comp_dat[] = "Feature_\tComponent_\n"
472                                            "s38\ts72\n"
473                                            "FeatureComponents\tFeature_\tComponent_\n"
474                                            "feature\tmaximus\n"
475                                            "montecristo\tmaximus";
476
477 static const CHAR rof_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
478                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
479                                    "File\tFile\n"
480                                    "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
481
482 static const CHAR rof_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
483                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
484                                     "Media\tDiskId\n"
485                                     "1\t1\t\t\tDISK1\t\n";
486
487 static const CHAR rofc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
488                                     "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
489                                     "File\tFile\n"
490                                     "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1";
491
492 static const CHAR rofc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
493                                      "i2\ti4\tL64\tS255\tS32\tS72\n"
494                                      "Media\tDiskId\n"
495                                      "1\t1\t\ttest1.cab\tDISK1\t\n";
496
497 static const CHAR lus2_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
498                                      "i2\ti4\tL64\tS255\tS32\tS72\n"
499                                      "Media\tDiskId\n"
500                                      "1\t1\t\t#test1.cab\tDISK1\t\n";
501
502 static const CHAR sdp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
503                                                "s72\tS255\tI2\n"
504                                                "InstallExecuteSequence\tAction\n"
505                                                "AllocateRegistrySpace\tNOT Installed\t1550\n"
506                                                "CostFinalize\t\t1000\n"
507                                                "CostInitialize\t\t800\n"
508                                                "FileCost\t\t900\n"
509                                                "InstallFiles\t\t4000\n"
510                                                "InstallFinalize\t\t6600\n"
511                                                "InstallInitialize\t\t1500\n"
512                                                "InstallValidate\t\t1400\n"
513                                                "LaunchConditions\t\t100\n"
514                                                "SetDirProperty\t\t950";
515
516 static const CHAR sdp_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
517                                             "s72\ti2\tS64\tS0\tS255\n"
518                                             "CustomAction\tAction\n"
519                                             "SetDirProperty\t51\tMSITESTDIR\t[CommonFilesFolder]msitest\\\t\n";
520
521 static const CHAR cie_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
522                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
523                                         "Component\tComponent\n"
524                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
525                                         "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
526                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n"
527                                         "gaius\t\tMSITESTDIR\t0\t1\tgaius\n";
528
529 static const CHAR cie_feature_comp_dat[] = "Feature_\tComponent_\n"
530                                            "s38\ts72\n"
531                                            "FeatureComponents\tFeature_\tComponent_\n"
532                                            "feature\tmaximus\n"
533                                            "feature\taugustus\n"
534                                            "feature\tcaesar\n"
535                                            "feature\tgaius";
536
537 static const CHAR cie_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
538                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
539                                    "File\tFile\n"
540                                    "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
541                                    "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
542                                    "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12\n"
543                                    "gaius\tgaius\tgaius\t500\t\t\t8192\t11";
544
545 static const CHAR cie_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
546                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
547                                     "Media\tDiskId\n"
548                                     "1\t1\t\ttest1.cab\tDISK1\t\n"
549                                     "2\t2\t\ttest2.cab\tDISK2\t\n"
550                                     "3\t12\t\ttest3.cab\tDISK3\t\n";
551
552 static const CHAR ci_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
553                                               "s72\tS255\tI2\n"
554                                               "InstallExecuteSequence\tAction\n"
555                                               "CostFinalize\t\t1000\n"
556                                               "CostInitialize\t\t800\n"
557                                               "FileCost\t\t900\n"
558                                               "InstallFiles\t\t4000\n"
559                                               "InstallServices\t\t5000\n"
560                                               "InstallFinalize\t\t6600\n"
561                                               "InstallInitialize\t\t1500\n"
562                                               "RunInstall\t\t1600\n"
563                                               "InstallValidate\t\t1400\n"
564                                               "LaunchConditions\t\t100";
565
566 static const CHAR ci_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
567                                             "s72\ti2\tS64\tS0\tS255\n"
568                                             "CustomAction\tAction\n"
569                                             "RunInstall\t87\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
570
571 static const CHAR ci_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
572                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
573                                        "Component\tComponent\n"
574                                        "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
575
576 static const CHAR ci2_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
577                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
578                                         "Component\tComponent\n"
579                                         "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
580
581 static const CHAR ci2_feature_comp_dat[] = "Feature_\tComponent_\n"
582                                            "s38\ts72\n"
583                                            "FeatureComponents\tFeature_\tComponent_\n"
584                                            "feature\taugustus";
585
586 static const CHAR ci2_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
587                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
588                                    "File\tFile\n"
589                                    "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
590
591 static const CHAR spf_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
592                                             "s72\ti2\tS64\tS0\tS255\n"
593                                             "CustomAction\tAction\n"
594                                             "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n";
595
596 static const CHAR spf_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
597                                                "s72\tS255\tI2\n"
598                                                "InstallExecuteSequence\tAction\n"
599                                                "CostFinalize\t\t1000\n"
600                                                "CostInitialize\t\t800\n"
601                                                "FileCost\t\t900\n"
602                                                "SetFolderProp\t\t950\n"
603                                                "InstallFiles\t\t4000\n"
604                                                "InstallServices\t\t5000\n"
605                                                "InstallFinalize\t\t6600\n"
606                                                "InstallInitialize\t\t1500\n"
607                                                "InstallValidate\t\t1400\n"
608                                                "LaunchConditions\t\t100";
609
610 static const CHAR spf_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
611                                              "s72\tS255\tI2\n"
612                                              "InstallUISequence\tAction\n"
613                                              "CostInitialize\t\t800\n"
614                                              "FileCost\t\t900\n"
615                                              "CostFinalize\t\t1000\n"
616                                              "ExecuteAction\t\t1100\n";
617
618 static const CHAR pp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
619                                               "s72\tS255\tI2\n"
620                                               "InstallExecuteSequence\tAction\n"
621                                               "ValidateProductID\t\t700\n"
622                                               "CostInitialize\t\t800\n"
623                                               "FileCost\t\t900\n"
624                                               "CostFinalize\t\t1000\n"
625                                               "InstallValidate\t\t1400\n"
626                                               "InstallInitialize\t\t1500\n"
627                                               "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
628                                               "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
629                                               "RemoveFiles\t\t3500\n"
630                                               "InstallFiles\t\t4000\n"
631                                               "RegisterUser\tREGISTER_USER=1 Or FULL=1\t6000\n"
632                                               "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
633                                               "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
634                                               "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
635                                               "InstallFinalize\t\t6600";
636
637 static const CHAR ppc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
638                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
639                                         "Component\tComponent\n"
640                                         "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n"
641                                         "augustus\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t1\t\taugustus\n";
642
643 static const CHAR ppc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
644                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
645                                    "File\tFile\n"
646                                    "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1\n"
647                                    "augustus\taugustus\taugustus\t500\t\t\t8192\t2";
648
649 static const CHAR ppc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
650                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
651                                     "Media\tDiskId\n"
652                                     "1\t2\t\t\tDISK1\t\n";
653
654 static const CHAR ppc_feature_comp_dat[] = "Feature_\tComponent_\n"
655                                            "s38\ts72\n"
656                                            "FeatureComponents\tFeature_\tComponent_\n"
657                                            "feature\tmaximus\n"
658                                            "feature\taugustus\n"
659                                            "montecristo\tmaximus";
660
661 static const CHAR tp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
662                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
663                                        "Component\tComponent\n"
664                                        "augustus\t\tMSITESTDIR\t0\tprop=\"val\"\taugustus\n";
665
666 static const CHAR cwd_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
667                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
668                                         "Component\tComponent\n"
669                                         "augustus\t\tMSITESTDIR\t0\t\taugustus\n";
670
671 static const CHAR adm_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
672                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
673                                         "Component\tComponent\n"
674                                         "augustus\t\tMSITESTDIR\t0\tPOSTADMIN=1\taugustus";
675
676 static const CHAR adm_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
677                                             "s72\ti2\tS64\tS0\tS255\n"
678                                             "CustomAction\tAction\n"
679                                             "SetPOSTADMIN\t51\tPOSTADMIN\t1\t\n";
680
681 static const CHAR adm_admin_exec_seq_dat[] = "Action\tCondition\tSequence\n"
682                                              "s72\tS255\tI2\n"
683                                              "AdminExecuteSequence\tAction\n"
684                                              "CostFinalize\t\t1000\n"
685                                              "CostInitialize\t\t800\n"
686                                              "FileCost\t\t900\n"
687                                              "SetPOSTADMIN\t\t950\n"
688                                              "InstallFiles\t\t4000\n"
689                                              "InstallFinalize\t\t6600\n"
690                                              "InstallInitialize\t\t1500\n"
691                                              "InstallValidate\t\t1400\n"
692                                              "LaunchConditions\t\t100";
693
694 static const CHAR amp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
695                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
696                                         "Component\tComponent\n"
697                                         "augustus\t\tMSITESTDIR\t0\tMYPROP=2718 and MyProp=42\taugustus\n";
698
699 static const CHAR rem_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
700                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
701                                         "Component\tComponent\n"
702                                         "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t0\t\thydrogen\n"
703                                         "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t1\t\thelium\n"
704                                         "lithium\t\tMSITESTDIR\t2\t\tlithium\n";
705
706 static const CHAR rem_feature_comp_dat[] = "Feature_\tComponent_\n"
707                                            "s38\ts72\n"
708                                            "FeatureComponents\tFeature_\tComponent_\n"
709                                            "feature\thydrogen\n"
710                                            "feature\thelium\n"
711                                            "feature\tlithium";
712
713 static const CHAR rem_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
714                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
715                                    "File\tFile\n"
716                                    "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
717                                    "helium\thelium\thelium\t0\t\t\t8192\t1\n"
718                                    "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
719
720 static const CHAR rem_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
721                                                "s72\tS255\tI2\n"
722                                                "InstallExecuteSequence\tAction\n"
723                                                "ValidateProductID\t\t700\n"
724                                                "CostInitialize\t\t800\n"
725                                                "FileCost\t\t900\n"
726                                                "CostFinalize\t\t1000\n"
727                                                "InstallValidate\t\t1400\n"
728                                                "InstallInitialize\t\t1500\n"
729                                                "ProcessComponents\t\t1600\n"
730                                                "UnpublishFeatures\t\t1800\n"
731                                                "RemoveFiles\t\t3500\n"
732                                                "InstallFiles\t\t4000\n"
733                                                "RegisterProduct\t\t6100\n"
734                                                "PublishFeatures\t\t6300\n"
735                                                "PublishProduct\t\t6400\n"
736                                                "InstallFinalize\t\t6600";
737
738 static const CHAR rem_remove_files_dat[] = "FileKey\tComponent_\tFileName\tDirProperty\tInstallMode\n"
739                                            "s72\ts72\tS255\ts72\tI2\n"
740                                            "RemoveFile\tFileKey\n"
741                                            "furlong\thydrogen\tfurlong\tMSITESTDIR\t1\n"
742                                            "firkin\thelium\tfirkin\tMSITESTDIR\t1\n"
743                                            "fortnight\tlithium\tfortnight\tMSITESTDIR\t1\n"
744                                            "becquerel\thydrogen\tbecquerel\tMSITESTDIR\t2\n"
745                                            "dioptre\thelium\tdioptre\tMSITESTDIR\t2\n"
746                                            "attoparsec\tlithium\tattoparsec\tMSITESTDIR\t2\n"
747                                            "storeys\thydrogen\tstoreys\tMSITESTDIR\t3\n"
748                                            "block\thelium\tblock\tMSITESTDIR\t3\n"
749                                            "siriometer\tlithium\tsiriometer\tMSITESTDIR\t3\n"
750                                            "nanoacre\thydrogen\t\tCABOUTDIR\t3\n";
751
752 static const CHAR mov_move_file_dat[] = "FileKey\tComponent_\tSourceName\tDestName\tSourceFolder\tDestFolder\tOptions\n"
753                                         "s72\ts72\tS255\tS255\tS72\ts72\ti2\n"
754                                         "MoveFile\tFileKey\n"
755                                         "abkhazia\taugustus\tnonexistent\tdest\tSourceDir\tMSITESTDIR\t0\n"
756                                         "bahamas\taugustus\tnonexistent\tdest\tSourceDir\tMSITESTDIR\t1\n"
757                                         "cambodia\taugustus\tcameroon\tcanada\tSourceDir\tMSITESTDIR\t0\n"
758                                         "denmark\taugustus\tdjibouti\tdominica\tSourceDir\tMSITESTDIR\t1\n"
759                                         "ecuador\taugustus\tegypt\telsalvador\tNotAProp\tMSITESTDIR\t1\n"
760                                         "fiji\taugustus\tfinland\tfrance\tSourceDir\tNotAProp\t1\n"
761                                         "gabon\taugustus\tgambia\tgeorgia\tSOURCEFULL\tMSITESTDIR\t1\n"
762                                         "haiti\taugustus\thonduras\thungary\tSourceDir\tDESTFULL\t1\n"
763                                         "iceland\taugustus\tindia\tindonesia\tMSITESTDIR\tMSITESTDIR\t1\n"
764                                         "jamaica\taugustus\tjapan\tjordan\tFILEPATHBAD\tMSITESTDIR\t1\n"
765                                         "kazakhstan\taugustus\t\tkiribati\tFILEPATHGOOD\tMSITESTDIR\t1\n"
766                                         "laos\taugustus\tlatvia\tlebanon\tSourceDir\tMSITESTDIR\t1\n"
767                                         "namibia\taugustus\tnauru\tkiribati\tSourceDir\tMSITESTDIR\t1\n"
768                                         "pakistan\taugustus\tperu\tsfn|poland\tSourceDir\tMSITESTDIR\t1\n"
769                                         "wildcard\taugustus\tapp*\twildcard\tSourceDir\tMSITESTDIR\t1\n"
770                                         "single\taugustus\tf?o\tsingle\tSourceDir\tMSITESTDIR\t1\n"
771                                         "wildcardnodest\taugustus\tbudd*\t\tSourceDir\tMSITESTDIR\t1\n"
772                                         "singlenodest\taugustus\tb?r\t\tSourceDir\tMSITESTDIR\t1\n";
773
774 static const CHAR mc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
775                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
776                                         "Component\tComponent\n"
777                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
778                                         "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
779                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n"
780                                         "gaius\t\tMSITESTDIR\t0\tGAIUS=1\tgaius\n";
781
782 static const CHAR mc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
783                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
784                                   "File\tFile\n"
785                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
786                                   "augustus\taugustus\taugustus\t500\t\t\t0\t2\n"
787                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3\n"
788                                   "gaius\tgaius\tgaius\t500\t\t\t16384\t4";
789
790 static const CHAR mc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
791                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
792                                    "Media\tDiskId\n"
793                                    "1\t1\t\ttest1.cab\tDISK1\t\n"
794                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
795                                    "3\t3\t\ttest3.cab\tDISK3\t\n"
796                                    "4\t4\t\ttest3.cab\tDISK3\t\n";
797
798 static const CHAR mc_file_hash_dat[] = "File_\tOptions\tHashPart1\tHashPart2\tHashPart3\tHashPart4\n"
799                                        "s72\ti2\ti4\ti4\ti4\ti4\n"
800                                        "MsiFileHash\tFile_\n"
801                                        "caesar\t0\t850433704\t-241429251\t675791761\t-1221108824";
802
803 static const CHAR df_directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
804                                        "s72\tS72\tl255\n"
805                                        "Directory\tDirectory\n"
806                                        "THIS\tMSITESTDIR\tthis\n"
807                                        "DOESNOT\tTHIS\tdoesnot\n"
808                                        "NONEXISTENT\tDOESNOT\texist\n"
809                                        "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
810                                        "ProgramFilesFolder\tTARGETDIR\t.\n"
811                                        "TARGETDIR\t\tSourceDir";
812
813 static const CHAR df_duplicate_file_dat[] = "FileKey\tComponent_\tFile_\tDestName\tDestFolder\n"
814                                             "s72\ts72\ts72\tS255\tS72\n"
815                                             "DuplicateFile\tFileKey\n"
816                                             "maximus\tmaximus\tmaximus\taugustus\t\n"
817                                             "caesar\tmaximus\tmaximus\t\tNONEXISTENT\n";
818
819 static const CHAR wrv_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
820                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
821                                         "Component\tComponent\n"
822                                         "augustus\t\tMSITESTDIR\t0\t\taugustus\n";
823
824 static const CHAR wrv_registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
825                                        "s72\ti2\tl255\tL255\tL0\ts72\n"
826                                        "Registry\tRegistry\n"
827                                        "regdata\t2\tSOFTWARE\\Wine\\msitest\tValue\t[~]one[~]two[~]three\taugustus";
828
829 static const CHAR ca51_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
830                                          "s72\tS38\ts72\ti2\tS255\tS72\n"
831                                          "Component\tComponent\n"
832                                          "augustus\t\tMSITESTDIR\t0\tMYPROP=42\taugustus\n";
833
834 static const CHAR ca51_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
835                                                 "s72\tS255\tI2\n"
836                                                 "InstallExecuteSequence\tAction\n"
837                                                 "ValidateProductID\t\t700\n"
838                                                 "GoodSetProperty\t\t725\n"
839                                                 "BadSetProperty\t\t750\n"
840                                                 "CostInitialize\t\t800\n"
841                                                 "ResolveSource\t\t810\n"
842                                                 "FileCost\t\t900\n"
843                                                 "SetSourceDir\tSRCDIR\t910\n"
844                                                 "CostFinalize\t\t1000\n"
845                                                 "InstallValidate\t\t1400\n"
846                                                 "InstallInitialize\t\t1500\n"
847                                                 "InstallFiles\t\t4000\n"
848                                                 "InstallFinalize\t\t6600";
849
850 static const CHAR ca51_custom_action_dat[] = "Action\tType\tSource\tTarget\n"
851                                              "s72\ti2\tS64\tS0\n"
852                                              "CustomAction\tAction\n"
853                                              "GoodSetProperty\t51\tMYPROP\t42\n"
854                                              "BadSetProperty\t51\t\tMYPROP\n"
855                                              "SetSourceDir\t51\tSourceDir\t[SRCDIR]\n";
856
857 static const CHAR is_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
858                                      "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
859                                      "Feature\tFeature\n"
860                                      "one\t\t\t\t2\t1\t\t0\n" /* favorLocal */
861                                      "two\t\t\t\t2\t1\t\t1\n" /* favorSource */
862                                      "three\t\t\t\t2\t1\t\t4\n" /* favorAdvertise */
863                                      "four\t\t\t\t2\t0\t\t0"; /* disabled */
864
865 static const CHAR is_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
866                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
867                                        "Component\tComponent\n"
868                                        "alpha\t\tMSITESTDIR\t0\t\talpha_file\n" /* favorLocal:Local */
869                                        "beta\t\tMSITESTDIR\t1\t\tbeta_file\n" /* favorLocal:Source */
870                                        "gamma\t\tMSITESTDIR\t2\t\tgamma_file\n" /* favorLocal:Optional */
871                                        "theta\t\tMSITESTDIR\t0\t\ttheta_file\n" /* favorSource:Local */
872                                        "delta\t\tMSITESTDIR\t1\t\tdelta_file\n" /* favorSource:Source */
873                                        "epsilon\t\tMSITESTDIR\t2\t\tepsilon_file\n" /* favorSource:Optional */
874                                        "zeta\t\tMSITESTDIR\t0\t\tzeta_file\n" /* favorAdvertise:Local */
875                                        "iota\t\tMSITESTDIR\t1\t\tiota_file\n" /* favorAdvertise:Source */
876                                        "eta\t\tMSITESTDIR\t2\t\teta_file\n" /* favorAdvertise:Optional */
877                                        "kappa\t\tMSITESTDIR\t0\t\tkappa_file\n" /* disabled:Local */
878                                        "lambda\t\tMSITESTDIR\t1\t\tlambda_file\n" /* disabled:Source */
879                                        "mu\t\tMSITESTDIR\t2\t\tmu_file\n"; /* disabled:Optional */
880
881 static const CHAR is_feature_comp_dat[] = "Feature_\tComponent_\n"
882                                           "s38\ts72\n"
883                                           "FeatureComponents\tFeature_\tComponent_\n"
884                                           "one\talpha\n"
885                                           "one\tbeta\n"
886                                           "one\tgamma\n"
887                                           "two\ttheta\n"
888                                           "two\tdelta\n"
889                                           "two\tepsilon\n"
890                                           "three\tzeta\n"
891                                           "three\tiota\n"
892                                           "three\teta\n"
893                                           "four\tkappa\n"
894                                           "four\tlambda\n"
895                                           "four\tmu";
896
897 static const CHAR is_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
898                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
899                                   "File\tFile\n"
900                                   "alpha_file\talpha\talpha\t500\t\t\t8192\t1\n"
901                                   "beta_file\tbeta\tbeta\t500\t\t\t8291\t2\n"
902                                   "gamma_file\tgamma\tgamma\t500\t\t\t8192\t3\n"
903                                   "theta_file\ttheta\ttheta\t500\t\t\t8192\t4\n"
904                                   "delta_file\tdelta\tdelta\t500\t\t\t8192\t5\n"
905                                   "epsilon_file\tepsilon\tepsilon\t500\t\t\t8192\t6\n"
906                                   "zeta_file\tzeta\tzeta\t500\t\t\t8192\t7\n"
907                                   "iota_file\tiota\tiota\t500\t\t\t8192\t8\n"
908                                   "eta_file\teta\teta\t500\t\t\t8192\t9\n"
909                                   "kappa_file\tkappa\tkappa\t500\t\t\t8192\t10\n"
910                                   "lambda_file\tlambda\tlambda\t500\t\t\t8192\t11\n"
911                                   "mu_file\tmu\tmu\t500\t\t\t8192\t12";
912
913 static const CHAR is_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
914                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
915                                    "Media\tDiskId\n"
916                                    "1\t12\t\t\tDISK1\t\n";
917
918 static const CHAR sp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
919                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
920                                         "Component\tComponent\n"
921                                         "augustus\t\tTWODIR\t0\t\taugustus\n";
922
923 static const CHAR sp_directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
924                                        "s72\tS72\tl255\n"
925                                        "Directory\tDirectory\n"
926                                        "TARGETDIR\t\tSourceDir\n"
927                                        "ProgramFilesFolder\tTARGETDIR\t.\n"
928                                        "MSITESTDIR\tProgramFilesFolder\tmsitest:.\n"
929                                        "ONEDIR\tMSITESTDIR\t.:shortone|longone\n"
930                                        "TWODIR\tONEDIR\t.:shorttwo|longtwo";
931
932 static const CHAR mcp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
933                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
934                                         "Component\tComponent\n"
935                                         "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t2\t\thydrogen\n"
936                                         "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t2\t\thelium\n"
937                                         "lithium\t{4AF28FFC-71C7-4307-BDE4-B77C5338F56F}\tMSITESTDIR\t2\tPROPVAR=42\tlithium\n";
938
939 static const CHAR mcp_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
940                                       "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
941                                       "Feature\tFeature\n"
942                                       "hydroxyl\t\thydroxyl\thydroxyl\t2\t1\tTARGETDIR\t0\n"
943                                       "heliox\t\theliox\theliox\t2\t5\tTARGETDIR\t0\n"
944                                       "lithia\t\tlithia\tlithia\t2\t10\tTARGETDIR\t0";
945
946 static const CHAR mcp_feature_comp_dat[] = "Feature_\tComponent_\n"
947                                            "s38\ts72\n"
948                                            "FeatureComponents\tFeature_\tComponent_\n"
949                                            "hydroxyl\thydrogen\n"
950                                            "heliox\thelium\n"
951                                            "lithia\tlithium";
952
953 static const CHAR mcomp_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
954                                      "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
955                                      "File\tFile\n"
956                                      "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
957                                      "helium\thelium\thelium\t0\t\t\t8192\t1\n"
958                                      "lithium\tlithium\tlithium\t0\t\t\t8192\t1\n"
959                                      "beryllium\tmissingcomp\tberyllium\t0\t\t\t8192\t1";
960
961 static const CHAR ai_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
962                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
963                                   "File\tFile\n"
964                                   "five.txt\tFive\tfive.txt\t1000\t\t\t16384\t5\n"
965                                   "four.txt\tFour\tfour.txt\t1000\t\t\t16384\t4\n"
966                                   "one.txt\tOne\tone.txt\t1000\t\t\t16384\t1\n"
967                                   "three.txt\tThree\tthree.txt\t1000\t\t\t16384\t3\n"
968                                   "two.txt\tTwo\ttwo.txt\t1000\t\t\t16384\t2\n"
969                                   "file\tcomponent\tfilename\t100\t\t\t8192\t1\n"
970                                   "service_file\tservice_comp\tservice.exe\t100\t\t\t8192\t1";
971
972 static const CHAR ip_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
973                                               "s72\tS255\tI2\n"
974                                               "InstallExecuteSequence\tAction\n"
975                                               "CostFinalize\t\t1000\n"
976                                               "ValidateProductID\t\t700\n"
977                                               "CostInitialize\t\t800\n"
978                                               "FileCost\t\t900\n"
979                                               "RemoveFiles\t\t3500\n"
980                                               "InstallFiles\t\t4000\n"
981                                               "RegisterUser\t\t6000\n"
982                                               "RegisterProduct\t\t6100\n"
983                                               "PublishFeatures\t\t6300\n"
984                                               "PublishProduct\t\t6400\n"
985                                               "InstallFinalize\t\t6600\n"
986                                               "InstallInitialize\t\t1500\n"
987                                               "ProcessComponents\t\t1600\n"
988                                               "UnpublishFeatures\t\t1800\n"
989                                               "InstallValidate\t\t1400\n"
990                                               "LaunchConditions\t\t100\n"
991                                               "TestInstalledProp\tInstalled AND NOT REMOVE\t950\n";
992
993 static const CHAR ip_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
994                                            "s72\ti2\tS64\tS0\tS255\n"
995                                            "CustomAction\tAction\n"
996                                            "TestInstalledProp\t19\t\tTest failed\t\n";
997
998 static const CHAR aup_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
999                                                "s72\tS255\tI2\n"
1000                                                "InstallExecuteSequence\tAction\n"
1001                                                "CostFinalize\t\t1000\n"
1002                                                "ValidateProductID\t\t700\n"
1003                                                "CostInitialize\t\t800\n"
1004                                                "FileCost\t\t900\n"
1005                                                "RemoveFiles\t\t3500\n"
1006                                                "InstallFiles\t\t4000\n"
1007                                                "RegisterUser\t\t6000\n"
1008                                                "RegisterProduct\t\t6100\n"
1009                                                "PublishFeatures\t\t6300\n"
1010                                                "PublishProduct\t\t6400\n"
1011                                                "InstallFinalize\t\t6600\n"
1012                                                "InstallInitialize\t\t1500\n"
1013                                                "ProcessComponents\t\t1600\n"
1014                                                "UnpublishFeatures\t\t1800\n"
1015                                                "InstallValidate\t\t1400\n"
1016                                                "LaunchConditions\t\t100\n"
1017                                                "TestAllUsersProp\tALLUSERS AND NOT REMOVE\t50\n";
1018
1019 static const CHAR aup2_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
1020                                                 "s72\tS255\tI2\n"
1021                                                 "InstallExecuteSequence\tAction\n"
1022                                                 "CostFinalize\t\t1000\n"
1023                                                 "ValidateProductID\t\t700\n"
1024                                                 "CostInitialize\t\t800\n"
1025                                                 "FileCost\t\t900\n"
1026                                                 "RemoveFiles\t\t3500\n"
1027                                                 "InstallFiles\t\t4000\n"
1028                                                 "RegisterUser\t\t6000\n"
1029                                                 "RegisterProduct\t\t6100\n"
1030                                                 "PublishFeatures\t\t6300\n"
1031                                                 "PublishProduct\t\t6400\n"
1032                                                 "InstallFinalize\t\t6600\n"
1033                                                 "InstallInitialize\t\t1500\n"
1034                                                 "ProcessComponents\t\t1600\n"
1035                                                 "UnpublishFeatures\t\t1800\n"
1036                                                 "InstallValidate\t\t1400\n"
1037                                                 "LaunchConditions\t\t100\n"
1038                                                 "TestAllUsersProp\tALLUSERS=2 AND NOT REMOVE\t50\n";
1039
1040 static const CHAR aup3_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
1041                                                 "s72\tS255\tI2\n"
1042                                                 "InstallExecuteSequence\tAction\n"
1043                                                 "CostFinalize\t\t1000\n"
1044                                                 "ValidateProductID\t\t700\n"
1045                                                 "CostInitialize\t\t800\n"
1046                                                 "FileCost\t\t900\n"
1047                                                 "RemoveFiles\t\t3500\n"
1048                                                 "InstallFiles\t\t4000\n"
1049                                                 "RegisterUser\t\t6000\n"
1050                                                 "RegisterProduct\t\t6100\n"
1051                                                 "PublishFeatures\t\t6300\n"
1052                                                 "PublishProduct\t\t6400\n"
1053                                                 "InstallFinalize\t\t6600\n"
1054                                                 "InstallInitialize\t\t1500\n"
1055                                                 "ProcessComponents\t\t1600\n"
1056                                                 "UnpublishFeatures\t\t1800\n"
1057                                                 "InstallValidate\t\t1400\n"
1058                                                 "LaunchConditions\t\t100\n"
1059                                                 "TestAllUsersProp\tALLUSERS=1 AND NOT REMOVE\t50\n";
1060
1061 static const CHAR aup_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
1062                                             "s72\ti2\tS64\tS0\tS255\n"
1063                                             "CustomAction\tAction\n"
1064                                             "TestAllUsersProp\t19\t\tTest failed\t\n";
1065
1066 typedef struct _msi_table
1067 {
1068     const CHAR *filename;
1069     const CHAR *data;
1070     int size;
1071 } msi_table;
1072
1073 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
1074
1075 static const msi_table tables[] =
1076 {
1077     ADD_TABLE(component),
1078     ADD_TABLE(directory),
1079     ADD_TABLE(feature),
1080     ADD_TABLE(feature_comp),
1081     ADD_TABLE(file),
1082     ADD_TABLE(install_exec_seq),
1083     ADD_TABLE(media),
1084     ADD_TABLE(property),
1085     ADD_TABLE(registry),
1086     ADD_TABLE(service_install),
1087     ADD_TABLE(service_control)
1088 };
1089
1090 static const msi_table sc_tables[] =
1091 {
1092     ADD_TABLE(component),
1093     ADD_TABLE(directory),
1094     ADD_TABLE(feature),
1095     ADD_TABLE(feature_comp),
1096     ADD_TABLE(file),
1097     ADD_TABLE(install_exec_seq),
1098     ADD_TABLE(media),
1099     ADD_TABLE(property),
1100     ADD_TABLE(shortcut)
1101 };
1102
1103 static const msi_table ps_tables[] =
1104 {
1105     ADD_TABLE(component),
1106     ADD_TABLE(directory),
1107     ADD_TABLE(feature),
1108     ADD_TABLE(feature_comp),
1109     ADD_TABLE(file),
1110     ADD_TABLE(install_exec_seq),
1111     ADD_TABLE(media),
1112     ADD_TABLE(property),
1113     ADD_TABLE(condition)
1114 };
1115
1116 static const msi_table env_tables[] =
1117 {
1118     ADD_TABLE(component),
1119     ADD_TABLE(directory),
1120     ADD_TABLE(feature),
1121     ADD_TABLE(feature_comp),
1122     ADD_TABLE(file),
1123     ADD_TABLE(install_exec_seq),
1124     ADD_TABLE(media),
1125     ADD_TABLE(property),
1126     ADD_TABLE(environment)
1127 };
1128
1129 static const msi_table up_tables[] =
1130 {
1131     ADD_TABLE(component),
1132     ADD_TABLE(directory),
1133     ADD_TABLE(feature),
1134     ADD_TABLE(feature_comp),
1135     ADD_TABLE(file),
1136     ADD_TABLE(install_exec_seq),
1137     ADD_TABLE(media),
1138     ADD_TABLE(up_property),
1139     ADD_TABLE(registry),
1140     ADD_TABLE(service_install),
1141     ADD_TABLE(service_control)
1142 };
1143
1144 static const msi_table up2_tables[] =
1145 {
1146     ADD_TABLE(component),
1147     ADD_TABLE(directory),
1148     ADD_TABLE(feature),
1149     ADD_TABLE(feature_comp),
1150     ADD_TABLE(file),
1151     ADD_TABLE(install_exec_seq),
1152     ADD_TABLE(media),
1153     ADD_TABLE(up2_property),
1154     ADD_TABLE(registry),
1155     ADD_TABLE(service_install),
1156     ADD_TABLE(service_control)
1157 };
1158
1159 static const msi_table up3_tables[] =
1160 {
1161     ADD_TABLE(component),
1162     ADD_TABLE(directory),
1163     ADD_TABLE(feature),
1164     ADD_TABLE(feature_comp),
1165     ADD_TABLE(file),
1166     ADD_TABLE(install_exec_seq),
1167     ADD_TABLE(media),
1168     ADD_TABLE(up3_property),
1169     ADD_TABLE(registry),
1170     ADD_TABLE(service_install),
1171     ADD_TABLE(service_control)
1172 };
1173
1174 static const msi_table up4_tables[] =
1175 {
1176     ADD_TABLE(component),
1177     ADD_TABLE(directory),
1178     ADD_TABLE(feature),
1179     ADD_TABLE(feature_comp),
1180     ADD_TABLE(file),
1181     ADD_TABLE(pp_install_exec_seq),
1182     ADD_TABLE(media),
1183     ADD_TABLE(property),
1184     ADD_TABLE(registry),
1185     ADD_TABLE(service_install),
1186     ADD_TABLE(service_control)
1187 };
1188
1189 static const msi_table up5_tables[] =
1190 {
1191     ADD_TABLE(component),
1192     ADD_TABLE(directory),
1193     ADD_TABLE(feature),
1194     ADD_TABLE(feature_comp),
1195     ADD_TABLE(file),
1196     ADD_TABLE(pp_install_exec_seq),
1197     ADD_TABLE(media),
1198     ADD_TABLE(up_property),
1199     ADD_TABLE(registry),
1200     ADD_TABLE(service_install),
1201     ADD_TABLE(service_control)
1202 };
1203
1204 static const msi_table up6_tables[] =
1205 {
1206     ADD_TABLE(component),
1207     ADD_TABLE(directory),
1208     ADD_TABLE(feature),
1209     ADD_TABLE(feature_comp),
1210     ADD_TABLE(file),
1211     ADD_TABLE(pp_install_exec_seq),
1212     ADD_TABLE(media),
1213     ADD_TABLE(up2_property),
1214     ADD_TABLE(registry),
1215     ADD_TABLE(service_install),
1216     ADD_TABLE(service_control)
1217 };
1218
1219 static const msi_table up7_tables[] =
1220 {
1221     ADD_TABLE(component),
1222     ADD_TABLE(directory),
1223     ADD_TABLE(feature),
1224     ADD_TABLE(feature_comp),
1225     ADD_TABLE(file),
1226     ADD_TABLE(pp_install_exec_seq),
1227     ADD_TABLE(media),
1228     ADD_TABLE(up3_property),
1229     ADD_TABLE(registry),
1230     ADD_TABLE(service_install),
1231     ADD_TABLE(service_control)
1232 };
1233
1234 static const msi_table cc_tables[] =
1235 {
1236     ADD_TABLE(cc_component),
1237     ADD_TABLE(directory),
1238     ADD_TABLE(cc_feature),
1239     ADD_TABLE(cc_feature_comp),
1240     ADD_TABLE(cc_file),
1241     ADD_TABLE(install_exec_seq),
1242     ADD_TABLE(cc_media),
1243     ADD_TABLE(property),
1244 };
1245
1246 static const msi_table cc2_tables[] =
1247 {
1248     ADD_TABLE(cc2_component),
1249     ADD_TABLE(directory),
1250     ADD_TABLE(cc_feature),
1251     ADD_TABLE(cc_feature_comp),
1252     ADD_TABLE(cc2_file),
1253     ADD_TABLE(install_exec_seq),
1254     ADD_TABLE(cc_media),
1255     ADD_TABLE(property),
1256 };
1257
1258 static const msi_table co_tables[] =
1259 {
1260     ADD_TABLE(cc_component),
1261     ADD_TABLE(directory),
1262     ADD_TABLE(cc_feature),
1263     ADD_TABLE(cc_feature_comp),
1264     ADD_TABLE(co_file),
1265     ADD_TABLE(install_exec_seq),
1266     ADD_TABLE(co_media),
1267     ADD_TABLE(property),
1268 };
1269
1270 static const msi_table co2_tables[] =
1271 {
1272     ADD_TABLE(cc_component),
1273     ADD_TABLE(directory),
1274     ADD_TABLE(cc_feature),
1275     ADD_TABLE(cc_feature_comp),
1276     ADD_TABLE(cc_file),
1277     ADD_TABLE(install_exec_seq),
1278     ADD_TABLE(co2_media),
1279     ADD_TABLE(property),
1280 };
1281
1282 static const msi_table mm_tables[] =
1283 {
1284     ADD_TABLE(cc_component),
1285     ADD_TABLE(directory),
1286     ADD_TABLE(cc_feature),
1287     ADD_TABLE(cc_feature_comp),
1288     ADD_TABLE(mm_file),
1289     ADD_TABLE(install_exec_seq),
1290     ADD_TABLE(mm_media),
1291     ADD_TABLE(property),
1292 };
1293
1294 static const msi_table ss_tables[] =
1295 {
1296     ADD_TABLE(cc_component),
1297     ADD_TABLE(directory),
1298     ADD_TABLE(cc_feature),
1299     ADD_TABLE(cc_feature_comp),
1300     ADD_TABLE(cc_file),
1301     ADD_TABLE(install_exec_seq),
1302     ADD_TABLE(ss_media),
1303     ADD_TABLE(property),
1304 };
1305
1306 static const msi_table ui_tables[] =
1307 {
1308     ADD_TABLE(ui_component),
1309     ADD_TABLE(directory),
1310     ADD_TABLE(cc_feature),
1311     ADD_TABLE(cc_feature_comp),
1312     ADD_TABLE(cc_file),
1313     ADD_TABLE(install_exec_seq),
1314     ADD_TABLE(ui_install_ui_seq),
1315     ADD_TABLE(ui_custom_action),
1316     ADD_TABLE(cc_media),
1317     ADD_TABLE(property),
1318 };
1319
1320 static const msi_table rof_tables[] =
1321 {
1322     ADD_TABLE(rof_component),
1323     ADD_TABLE(directory),
1324     ADD_TABLE(rof_feature),
1325     ADD_TABLE(rof_feature_comp),
1326     ADD_TABLE(rof_file),
1327     ADD_TABLE(install_exec_seq),
1328     ADD_TABLE(rof_media),
1329     ADD_TABLE(property),
1330 };
1331
1332 static const msi_table rofc_tables[] =
1333 {
1334     ADD_TABLE(rof_component),
1335     ADD_TABLE(directory),
1336     ADD_TABLE(rof_feature),
1337     ADD_TABLE(rof_feature_comp),
1338     ADD_TABLE(rofc_file),
1339     ADD_TABLE(install_exec_seq),
1340     ADD_TABLE(rofc_media),
1341     ADD_TABLE(property),
1342 };
1343
1344 static const msi_table sdp_tables[] =
1345 {
1346     ADD_TABLE(rof_component),
1347     ADD_TABLE(directory),
1348     ADD_TABLE(rof_feature),
1349     ADD_TABLE(rof_feature_comp),
1350     ADD_TABLE(rof_file),
1351     ADD_TABLE(sdp_install_exec_seq),
1352     ADD_TABLE(sdp_custom_action),
1353     ADD_TABLE(rof_media),
1354     ADD_TABLE(property),
1355 };
1356
1357 static const msi_table cie_tables[] =
1358 {
1359     ADD_TABLE(cie_component),
1360     ADD_TABLE(directory),
1361     ADD_TABLE(cc_feature),
1362     ADD_TABLE(cie_feature_comp),
1363     ADD_TABLE(cie_file),
1364     ADD_TABLE(install_exec_seq),
1365     ADD_TABLE(cie_media),
1366     ADD_TABLE(property),
1367 };
1368
1369 static const msi_table ci_tables[] =
1370 {
1371     ADD_TABLE(ci_component),
1372     ADD_TABLE(directory),
1373     ADD_TABLE(rof_feature),
1374     ADD_TABLE(rof_feature_comp),
1375     ADD_TABLE(rof_file),
1376     ADD_TABLE(ci_install_exec_seq),
1377     ADD_TABLE(rof_media),
1378     ADD_TABLE(property),
1379     ADD_TABLE(ci_custom_action),
1380 };
1381
1382 static const msi_table ci2_tables[] =
1383 {
1384     ADD_TABLE(ci2_component),
1385     ADD_TABLE(directory),
1386     ADD_TABLE(rof_feature),
1387     ADD_TABLE(ci2_feature_comp),
1388     ADD_TABLE(ci2_file),
1389     ADD_TABLE(install_exec_seq),
1390     ADD_TABLE(rof_media),
1391     ADD_TABLE(property),
1392 };
1393
1394 static const msi_table spf_tables[] =
1395 {
1396     ADD_TABLE(ci_component),
1397     ADD_TABLE(directory),
1398     ADD_TABLE(rof_feature),
1399     ADD_TABLE(rof_feature_comp),
1400     ADD_TABLE(rof_file),
1401     ADD_TABLE(spf_install_exec_seq),
1402     ADD_TABLE(rof_media),
1403     ADD_TABLE(property),
1404     ADD_TABLE(spf_custom_action),
1405     ADD_TABLE(spf_install_ui_seq),
1406 };
1407
1408 static const msi_table pp_tables[] =
1409 {
1410     ADD_TABLE(ci_component),
1411     ADD_TABLE(directory),
1412     ADD_TABLE(rof_feature),
1413     ADD_TABLE(rof_feature_comp),
1414     ADD_TABLE(rof_file),
1415     ADD_TABLE(pp_install_exec_seq),
1416     ADD_TABLE(rof_media),
1417     ADD_TABLE(property),
1418 };
1419
1420 static const msi_table ppc_tables[] =
1421 {
1422     ADD_TABLE(ppc_component),
1423     ADD_TABLE(directory),
1424     ADD_TABLE(rof_feature),
1425     ADD_TABLE(ppc_feature_comp),
1426     ADD_TABLE(ppc_file),
1427     ADD_TABLE(pp_install_exec_seq),
1428     ADD_TABLE(ppc_media),
1429     ADD_TABLE(property),
1430 };
1431
1432 static const msi_table lus0_tables[] =
1433 {
1434     ADD_TABLE(ci_component),
1435     ADD_TABLE(directory),
1436     ADD_TABLE(rof_feature),
1437     ADD_TABLE(rof_feature_comp),
1438     ADD_TABLE(rof_file),
1439     ADD_TABLE(pp_install_exec_seq),
1440     ADD_TABLE(rof_media),
1441     ADD_TABLE(property),
1442 };
1443
1444 static const msi_table lus1_tables[] =
1445 {
1446     ADD_TABLE(ci_component),
1447     ADD_TABLE(directory),
1448     ADD_TABLE(rof_feature),
1449     ADD_TABLE(rof_feature_comp),
1450     ADD_TABLE(rof_file),
1451     ADD_TABLE(pp_install_exec_seq),
1452     ADD_TABLE(rofc_media),
1453     ADD_TABLE(property),
1454 };
1455
1456 static const msi_table lus2_tables[] =
1457 {
1458     ADD_TABLE(ci_component),
1459     ADD_TABLE(directory),
1460     ADD_TABLE(rof_feature),
1461     ADD_TABLE(rof_feature_comp),
1462     ADD_TABLE(rof_file),
1463     ADD_TABLE(pp_install_exec_seq),
1464     ADD_TABLE(lus2_media),
1465     ADD_TABLE(property),
1466 };
1467
1468 static const msi_table tp_tables[] =
1469 {
1470     ADD_TABLE(tp_component),
1471     ADD_TABLE(directory),
1472     ADD_TABLE(rof_feature),
1473     ADD_TABLE(ci2_feature_comp),
1474     ADD_TABLE(ci2_file),
1475     ADD_TABLE(install_exec_seq),
1476     ADD_TABLE(rof_media),
1477     ADD_TABLE(property),
1478 };
1479
1480 static const msi_table cwd_tables[] =
1481 {
1482     ADD_TABLE(cwd_component),
1483     ADD_TABLE(directory),
1484     ADD_TABLE(rof_feature),
1485     ADD_TABLE(ci2_feature_comp),
1486     ADD_TABLE(ci2_file),
1487     ADD_TABLE(install_exec_seq),
1488     ADD_TABLE(rof_media),
1489     ADD_TABLE(property),
1490 };
1491
1492 static const msi_table adm_tables[] =
1493 {
1494     ADD_TABLE(adm_component),
1495     ADD_TABLE(directory),
1496     ADD_TABLE(rof_feature),
1497     ADD_TABLE(ci2_feature_comp),
1498     ADD_TABLE(ci2_file),
1499     ADD_TABLE(install_exec_seq),
1500     ADD_TABLE(rof_media),
1501     ADD_TABLE(property),
1502     ADD_TABLE(adm_custom_action),
1503     ADD_TABLE(adm_admin_exec_seq),
1504 };
1505
1506 static const msi_table amp_tables[] =
1507 {
1508     ADD_TABLE(amp_component),
1509     ADD_TABLE(directory),
1510     ADD_TABLE(rof_feature),
1511     ADD_TABLE(ci2_feature_comp),
1512     ADD_TABLE(ci2_file),
1513     ADD_TABLE(install_exec_seq),
1514     ADD_TABLE(rof_media),
1515     ADD_TABLE(property),
1516 };
1517
1518 static const msi_table rem_tables[] =
1519 {
1520     ADD_TABLE(rem_component),
1521     ADD_TABLE(directory),
1522     ADD_TABLE(rof_feature),
1523     ADD_TABLE(rem_feature_comp),
1524     ADD_TABLE(rem_file),
1525     ADD_TABLE(rem_install_exec_seq),
1526     ADD_TABLE(rof_media),
1527     ADD_TABLE(property),
1528     ADD_TABLE(rem_remove_files),
1529 };
1530
1531 static const msi_table mov_tables[] =
1532 {
1533     ADD_TABLE(cwd_component),
1534     ADD_TABLE(directory),
1535     ADD_TABLE(rof_feature),
1536     ADD_TABLE(ci2_feature_comp),
1537     ADD_TABLE(ci2_file),
1538     ADD_TABLE(install_exec_seq),
1539     ADD_TABLE(rof_media),
1540     ADD_TABLE(property),
1541     ADD_TABLE(mov_move_file),
1542 };
1543
1544 static const msi_table mc_tables[] =
1545 {
1546     ADD_TABLE(mc_component),
1547     ADD_TABLE(directory),
1548     ADD_TABLE(cc_feature),
1549     ADD_TABLE(cie_feature_comp),
1550     ADD_TABLE(mc_file),
1551     ADD_TABLE(install_exec_seq),
1552     ADD_TABLE(mc_media),
1553     ADD_TABLE(property),
1554     ADD_TABLE(mc_file_hash),
1555 };
1556
1557 static const msi_table df_tables[] =
1558 {
1559     ADD_TABLE(rof_component),
1560     ADD_TABLE(df_directory),
1561     ADD_TABLE(rof_feature),
1562     ADD_TABLE(rof_feature_comp),
1563     ADD_TABLE(rof_file),
1564     ADD_TABLE(install_exec_seq),
1565     ADD_TABLE(rof_media),
1566     ADD_TABLE(property),
1567     ADD_TABLE(df_duplicate_file),
1568 };
1569
1570 static const msi_table wrv_tables[] =
1571 {
1572     ADD_TABLE(wrv_component),
1573     ADD_TABLE(directory),
1574     ADD_TABLE(rof_feature),
1575     ADD_TABLE(ci2_feature_comp),
1576     ADD_TABLE(ci2_file),
1577     ADD_TABLE(install_exec_seq),
1578     ADD_TABLE(rof_media),
1579     ADD_TABLE(property),
1580     ADD_TABLE(wrv_registry),
1581 };
1582
1583 static const msi_table sf_tables[] =
1584 {
1585     ADD_TABLE(wrv_component),
1586     ADD_TABLE(directory),
1587     ADD_TABLE(rof_feature),
1588     ADD_TABLE(ci2_feature_comp),
1589     ADD_TABLE(ci2_file),
1590     ADD_TABLE(install_exec_seq),
1591     ADD_TABLE(rof_media),
1592     ADD_TABLE(property),
1593 };
1594
1595 static const msi_table ca51_tables[] =
1596 {
1597     ADD_TABLE(ca51_component),
1598     ADD_TABLE(directory),
1599     ADD_TABLE(rof_feature),
1600     ADD_TABLE(ci2_feature_comp),
1601     ADD_TABLE(ci2_file),
1602     ADD_TABLE(ca51_install_exec_seq),
1603     ADD_TABLE(rof_media),
1604     ADD_TABLE(property),
1605     ADD_TABLE(ca51_custom_action),
1606 };
1607
1608 static const msi_table is_tables[] =
1609 {
1610     ADD_TABLE(is_component),
1611     ADD_TABLE(directory),
1612     ADD_TABLE(is_feature),
1613     ADD_TABLE(is_feature_comp),
1614     ADD_TABLE(is_file),
1615     ADD_TABLE(install_exec_seq),
1616     ADD_TABLE(is_media),
1617     ADD_TABLE(property),
1618 };
1619
1620 static const msi_table sp_tables[] =
1621 {
1622     ADD_TABLE(sp_component),
1623     ADD_TABLE(sp_directory),
1624     ADD_TABLE(rof_feature),
1625     ADD_TABLE(ci2_feature_comp),
1626     ADD_TABLE(ci2_file),
1627     ADD_TABLE(install_exec_seq),
1628     ADD_TABLE(rof_media),
1629     ADD_TABLE(property),
1630 };
1631
1632 static const msi_table mcp_tables[] =
1633 {
1634     ADD_TABLE(mcp_component),
1635     ADD_TABLE(directory),
1636     ADD_TABLE(mcp_feature),
1637     ADD_TABLE(mcp_feature_comp),
1638     ADD_TABLE(rem_file),
1639     ADD_TABLE(rem_install_exec_seq),
1640     ADD_TABLE(rof_media),
1641     ADD_TABLE(property),
1642 };
1643
1644 static const msi_table mcomp_tables[] =
1645 {
1646     ADD_TABLE(mcp_component),
1647     ADD_TABLE(directory),
1648     ADD_TABLE(mcp_feature),
1649     ADD_TABLE(mcp_feature_comp),
1650     ADD_TABLE(mcomp_file),
1651     ADD_TABLE(rem_install_exec_seq),
1652     ADD_TABLE(rof_media),
1653     ADD_TABLE(property),
1654 };
1655
1656 static const msi_table ai_tables[] =
1657 {
1658     ADD_TABLE(component),
1659     ADD_TABLE(directory),
1660     ADD_TABLE(feature),
1661     ADD_TABLE(feature_comp),
1662     ADD_TABLE(ai_file),
1663     ADD_TABLE(install_exec_seq),
1664     ADD_TABLE(media),
1665     ADD_TABLE(property)
1666 };
1667
1668 static const msi_table pc_tables[] =
1669 {
1670     ADD_TABLE(ca51_component),
1671     ADD_TABLE(directory),
1672     ADD_TABLE(rof_feature),
1673     ADD_TABLE(ci2_feature_comp),
1674     ADD_TABLE(ci2_file),
1675     ADD_TABLE(install_exec_seq),
1676     ADD_TABLE(rof_media),
1677     ADD_TABLE(property)
1678 };
1679
1680 static const msi_table ip_tables[] =
1681 {
1682     ADD_TABLE(component),
1683     ADD_TABLE(directory),
1684     ADD_TABLE(feature),
1685     ADD_TABLE(feature_comp),
1686     ADD_TABLE(file),
1687     ADD_TABLE(ip_install_exec_seq),
1688     ADD_TABLE(ip_custom_action),
1689     ADD_TABLE(media),
1690     ADD_TABLE(property)
1691 };
1692
1693 static const msi_table aup_tables[] =
1694 {
1695     ADD_TABLE(component),
1696     ADD_TABLE(directory),
1697     ADD_TABLE(feature),
1698     ADD_TABLE(feature_comp),
1699     ADD_TABLE(file),
1700     ADD_TABLE(aup_install_exec_seq),
1701     ADD_TABLE(aup_custom_action),
1702     ADD_TABLE(media),
1703     ADD_TABLE(property)
1704 };
1705
1706 static const msi_table aup2_tables[] =
1707 {
1708     ADD_TABLE(component),
1709     ADD_TABLE(directory),
1710     ADD_TABLE(feature),
1711     ADD_TABLE(feature_comp),
1712     ADD_TABLE(file),
1713     ADD_TABLE(aup2_install_exec_seq),
1714     ADD_TABLE(aup_custom_action),
1715     ADD_TABLE(media),
1716     ADD_TABLE(aup_property)
1717 };
1718
1719 static const msi_table aup3_tables[] =
1720 {
1721     ADD_TABLE(component),
1722     ADD_TABLE(directory),
1723     ADD_TABLE(feature),
1724     ADD_TABLE(feature_comp),
1725     ADD_TABLE(file),
1726     ADD_TABLE(aup2_install_exec_seq),
1727     ADD_TABLE(aup_custom_action),
1728     ADD_TABLE(media),
1729     ADD_TABLE(aup2_property)
1730 };
1731
1732 static const msi_table aup4_tables[] =
1733 {
1734     ADD_TABLE(component),
1735     ADD_TABLE(directory),
1736     ADD_TABLE(feature),
1737     ADD_TABLE(feature_comp),
1738     ADD_TABLE(file),
1739     ADD_TABLE(aup3_install_exec_seq),
1740     ADD_TABLE(aup_custom_action),
1741     ADD_TABLE(media),
1742     ADD_TABLE(aup2_property)
1743 };
1744
1745 static const msi_table fiu_tables[] =
1746 {
1747     ADD_TABLE(rof_component),
1748     ADD_TABLE(directory),
1749     ADD_TABLE(rof_feature),
1750     ADD_TABLE(rof_feature_comp),
1751     ADD_TABLE(rof_file),
1752     ADD_TABLE(pp_install_exec_seq),
1753     ADD_TABLE(rof_media),
1754     ADD_TABLE(property),
1755 };
1756
1757 static const msi_table fiuc_tables[] =
1758 {
1759     ADD_TABLE(rof_component),
1760     ADD_TABLE(directory),
1761     ADD_TABLE(rof_feature),
1762     ADD_TABLE(rof_feature_comp),
1763     ADD_TABLE(rofc_file),
1764     ADD_TABLE(pp_install_exec_seq),
1765     ADD_TABLE(rofc_media),
1766     ADD_TABLE(property),
1767 };
1768
1769 /* cabinet definitions */
1770
1771 /* make the max size large so there is only one cab file */
1772 #define MEDIA_SIZE          0x7FFFFFFF
1773 #define FOLDER_THRESHOLD    900000
1774
1775 /* the FCI callbacks */
1776
1777 static void * CDECL mem_alloc(ULONG cb)
1778 {
1779     return HeapAlloc(GetProcessHeap(), 0, cb);
1780 }
1781
1782 static void CDECL mem_free(void *memory)
1783 {
1784     HeapFree(GetProcessHeap(), 0, memory);
1785 }
1786
1787 static BOOL CDECL get_next_cabinet(PCCAB pccab, ULONG  cbPrevCab, void *pv)
1788 {
1789     sprintf(pccab->szCab, pv, pccab->iCab);
1790     return TRUE;
1791 }
1792
1793 static LONG CDECL progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
1794 {
1795     return 0;
1796 }
1797
1798 static int CDECL file_placed(PCCAB pccab, char *pszFile, LONG cbFile,
1799                              BOOL fContinuation, void *pv)
1800 {
1801     return 0;
1802 }
1803
1804 static INT_PTR CDECL fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
1805 {
1806     HANDLE handle;
1807     DWORD dwAccess = 0;
1808     DWORD dwShareMode = 0;
1809     DWORD dwCreateDisposition = OPEN_EXISTING;
1810     
1811     dwAccess = GENERIC_READ | GENERIC_WRITE;
1812     /* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
1813     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
1814
1815     if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
1816         dwCreateDisposition = OPEN_EXISTING;
1817     else
1818         dwCreateDisposition = CREATE_NEW;
1819
1820     handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
1821                          dwCreateDisposition, 0, NULL);
1822
1823     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
1824
1825     return (INT_PTR)handle;
1826 }
1827
1828 static UINT CDECL fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
1829 {
1830     HANDLE handle = (HANDLE)hf;
1831     DWORD dwRead;
1832     BOOL res;
1833     
1834     res = ReadFile(handle, memory, cb, &dwRead, NULL);
1835     ok(res, "Failed to ReadFile\n");
1836
1837     return dwRead;
1838 }
1839
1840 static UINT CDECL fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
1841 {
1842     HANDLE handle = (HANDLE)hf;
1843     DWORD dwWritten;
1844     BOOL res;
1845
1846     res = WriteFile(handle, memory, cb, &dwWritten, NULL);
1847     ok(res, "Failed to WriteFile\n");
1848
1849     return dwWritten;
1850 }
1851
1852 static int CDECL fci_close(INT_PTR hf, int *err, void *pv)
1853 {
1854     HANDLE handle = (HANDLE)hf;
1855     ok(CloseHandle(handle), "Failed to CloseHandle\n");
1856
1857     return 0;
1858 }
1859
1860 static LONG CDECL fci_seek(INT_PTR hf, LONG dist, int seektype, int *err, void *pv)
1861 {
1862     HANDLE handle = (HANDLE)hf;
1863     DWORD ret;
1864     
1865     ret = SetFilePointer(handle, dist, NULL, seektype);
1866     ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
1867
1868     return ret;
1869 }
1870
1871 static int CDECL fci_delete(char *pszFile, int *err, void *pv)
1872 {
1873     BOOL ret = DeleteFileA(pszFile);
1874     ok(ret, "Failed to DeleteFile %s\n", pszFile);
1875
1876     return 0;
1877 }
1878
1879 static void init_functionpointers(void)
1880 {
1881     HMODULE hmsi = GetModuleHandleA("msi.dll");
1882     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
1883
1884 #define GET_PROC(mod, func) \
1885     p ## func = (void*)GetProcAddress(mod, #func); \
1886     if(!p ## func) \
1887       trace("GetProcAddress(%s) failed\n", #func);
1888
1889     GET_PROC(hmsi, MsiQueryComponentStateA);
1890     GET_PROC(hmsi, MsiSetExternalUIRecord);
1891     GET_PROC(hmsi, MsiSourceListEnumSourcesA);
1892     GET_PROC(hmsi, MsiSourceListGetInfoA);
1893
1894     GET_PROC(hadvapi32, ConvertSidToStringSidA);
1895
1896     hsrclient = LoadLibraryA("srclient.dll");
1897     GET_PROC(hsrclient, SRRemoveRestorePoint);
1898     GET_PROC(hsrclient, SRSetRestorePointA);
1899
1900 #undef GET_PROC
1901 }
1902
1903 static BOOL check_win9x(void)
1904 {
1905     SC_HANDLE scm;
1906
1907     scm = OpenSCManager(NULL, NULL, GENERIC_ALL);
1908     if (!scm && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1909         return TRUE;
1910
1911     CloseServiceHandle(scm);
1912
1913     return FALSE;
1914 }
1915
1916 static LPSTR get_user_sid(LPSTR *usersid)
1917 {
1918     HANDLE token;
1919     BYTE buf[1024];
1920     DWORD size;
1921     PTOKEN_USER user;
1922
1923     if (!pConvertSidToStringSidA)
1924     {
1925         win_skip("ConvertSidToStringSidA is not available\n");
1926         return NULL;
1927     }
1928
1929     *usersid = NULL;
1930     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
1931     size = sizeof(buf);
1932     GetTokenInformation(token, TokenUser, buf, size, &size);
1933     user = (PTOKEN_USER)buf;
1934     pConvertSidToStringSidA(user->User.Sid, usersid);
1935     ok(*usersid != NULL, "pConvertSidToStringSidA failed lre=%d\n", GetLastError());
1936     CloseHandle(token);
1937     return *usersid;
1938 }
1939
1940 static BOOL check_record(MSIHANDLE rec, UINT field, LPCSTR val)
1941 {
1942     CHAR buffer[0x20];
1943     UINT r;
1944     DWORD sz;
1945
1946     sz = sizeof buffer;
1947     r = MsiRecordGetString(rec, field, buffer, &sz);
1948     return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
1949 }
1950
1951 static BOOL CDECL get_temp_file(char *pszTempName, int cbTempName, void *pv)
1952 {
1953     LPSTR tempname;
1954
1955     tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
1956     GetTempFileNameA(".", "xx", 0, tempname);
1957
1958     if (tempname && (strlen(tempname) < (unsigned)cbTempName))
1959     {
1960         lstrcpyA(pszTempName, tempname);
1961         HeapFree(GetProcessHeap(), 0, tempname);
1962         return TRUE;
1963     }
1964
1965     HeapFree(GetProcessHeap(), 0, tempname);
1966
1967     return FALSE;
1968 }
1969
1970 static INT_PTR CDECL get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
1971                                    USHORT *pattribs, int *err, void *pv)
1972 {
1973     BY_HANDLE_FILE_INFORMATION finfo;
1974     FILETIME filetime;
1975     HANDLE handle;
1976     DWORD attrs;
1977     BOOL res;
1978
1979     handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
1980                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
1981
1982     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
1983
1984     res = GetFileInformationByHandle(handle, &finfo);
1985     ok(res, "Expected GetFileInformationByHandle to succeed\n");
1986    
1987     FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
1988     FileTimeToDosDateTime(&filetime, pdate, ptime);
1989
1990     attrs = GetFileAttributes(pszName);
1991     ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
1992
1993     return (INT_PTR)handle;
1994 }
1995
1996 static BOOL add_file(HFCI hfci, const char *file, TCOMP compress)
1997 {
1998     char path[MAX_PATH];
1999     char filename[MAX_PATH];
2000
2001     lstrcpyA(path, CURR_DIR);
2002     lstrcatA(path, "\\");
2003     lstrcatA(path, file);
2004
2005     lstrcpyA(filename, file);
2006
2007     return FCIAddFile(hfci, path, filename, FALSE, get_next_cabinet,
2008                       progress, get_open_info, compress);
2009 }
2010
2011 static void set_cab_parameters(PCCAB pCabParams, const CHAR *name, DWORD max_size)
2012 {
2013     ZeroMemory(pCabParams, sizeof(CCAB));
2014
2015     pCabParams->cb = max_size;
2016     pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
2017     pCabParams->setID = 0xbeef;
2018     pCabParams->iCab = 1;
2019     lstrcpyA(pCabParams->szCabPath, CURR_DIR);
2020     lstrcatA(pCabParams->szCabPath, "\\");
2021     lstrcpyA(pCabParams->szCab, name);
2022 }
2023
2024 static void create_cab_file(const CHAR *name, DWORD max_size, const CHAR *files)
2025 {
2026     CCAB cabParams;
2027     LPCSTR ptr;
2028     HFCI hfci;
2029     ERF erf;
2030     BOOL res;
2031
2032     set_cab_parameters(&cabParams, name, max_size);
2033
2034     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
2035                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
2036                       get_temp_file, &cabParams, NULL);
2037
2038     ok(hfci != NULL, "Failed to create an FCI context\n");
2039
2040     ptr = files;
2041     while (*ptr)
2042     {
2043         res = add_file(hfci, ptr, tcompTYPE_MSZIP);
2044         ok(res, "Failed to add file: %s\n", ptr);
2045         ptr += lstrlen(ptr) + 1;
2046     }
2047
2048     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
2049     ok(res, "Failed to flush the cabinet\n");
2050
2051     res = FCIDestroy(hfci);
2052     ok(res, "Failed to destroy the cabinet\n");
2053 }
2054
2055 static BOOL get_program_files_dir(LPSTR buf, LPSTR buf2)
2056 {
2057     HKEY hkey;
2058     DWORD type, size;
2059
2060     if (RegOpenKey(HKEY_LOCAL_MACHINE,
2061                    "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
2062         return FALSE;
2063
2064     size = MAX_PATH;
2065     if (RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)buf, &size)) {
2066         RegCloseKey(hkey);
2067         return FALSE;
2068     }
2069
2070     size = MAX_PATH;
2071     if (RegQueryValueExA(hkey, "CommonFilesDir", 0, &type, (LPBYTE)buf2, &size)) {
2072         RegCloseKey(hkey);
2073         return FALSE;
2074     }
2075
2076     RegCloseKey(hkey);
2077     return TRUE;
2078 }
2079
2080 static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
2081 {
2082     HANDLE file;
2083     DWORD written;
2084
2085     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
2086     if (file == INVALID_HANDLE_VALUE)
2087         return;
2088
2089     WriteFile(file, data, strlen(data), &written, NULL);
2090
2091     if (size)
2092     {
2093         SetFilePointer(file, size, NULL, FILE_BEGIN);
2094         SetEndOfFile(file);
2095     }
2096
2097     CloseHandle(file);
2098 }
2099
2100 #define create_file(name, size) create_file_data(name, name, size)
2101
2102 static void create_test_files(void)
2103 {
2104     CreateDirectoryA("msitest", NULL);
2105     create_file("msitest\\one.txt", 100);
2106     CreateDirectoryA("msitest\\first", NULL);
2107     create_file("msitest\\first\\two.txt", 100);
2108     CreateDirectoryA("msitest\\second", NULL);
2109     create_file("msitest\\second\\three.txt", 100);
2110
2111     create_file("four.txt", 100);
2112     create_file("five.txt", 100);
2113     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
2114
2115     create_file("msitest\\filename", 100);
2116     create_file("msitest\\service.exe", 100);
2117
2118     DeleteFileA("four.txt");
2119     DeleteFileA("five.txt");
2120 }
2121
2122 static BOOL delete_pf(const CHAR *rel_path, BOOL is_file)
2123 {
2124     CHAR path[MAX_PATH];
2125
2126     lstrcpyA(path, PROG_FILES_DIR);
2127     lstrcatA(path, "\\");
2128     lstrcatA(path, rel_path);
2129
2130     if (is_file)
2131         return DeleteFileA(path);
2132     else
2133         return RemoveDirectoryA(path);
2134 }
2135
2136 static BOOL delete_cf(const CHAR *rel_path, BOOL is_file)
2137 {
2138     CHAR path[MAX_PATH];
2139
2140     lstrcpyA(path, COMMON_FILES_DIR);
2141     lstrcatA(path, "\\");
2142     lstrcatA(path, rel_path);
2143
2144     if (is_file)
2145         return DeleteFileA(path);
2146     else
2147         return RemoveDirectoryA(path);
2148 }
2149
2150 static void delete_test_files(void)
2151 {
2152     DeleteFileA("msitest.msi");
2153     DeleteFileA("msitest.cab");
2154     DeleteFileA("msitest\\second\\three.txt");
2155     DeleteFileA("msitest\\first\\two.txt");
2156     DeleteFileA("msitest\\one.txt");
2157     DeleteFileA("msitest\\service.exe");
2158     DeleteFileA("msitest\\filename");
2159     RemoveDirectoryA("msitest\\second");
2160     RemoveDirectoryA("msitest\\first");
2161     RemoveDirectoryA("msitest");
2162 }
2163
2164 static void write_file(const CHAR *filename, const char *data, int data_size)
2165 {
2166     DWORD size;
2167
2168     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
2169                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2170
2171     WriteFile(hf, data, data_size, &size, NULL);
2172     CloseHandle(hf);
2173 }
2174
2175 static void write_msi_summary_info(MSIHANDLE db, INT wordcount)
2176 {
2177     MSIHANDLE summary;
2178     UINT r;
2179
2180     r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
2181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2182
2183     r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, ";1033");
2184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2185
2186     r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
2187                                    "{004757CA-5092-49c2-AD20-28E1CE0DF5F2}");
2188     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2189
2190     r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
2191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2192
2193     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, wordcount, NULL, NULL);
2194     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2195
2196     r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
2197     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2198
2199     /* write the summary changes back to the stream */
2200     r = MsiSummaryInfoPersist(summary);
2201     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2202
2203     MsiCloseHandle(summary);
2204 }
2205
2206 #define create_database(name, tables, num_tables) \
2207     create_database_wordcount(name, tables, num_tables, 0);
2208
2209 static void create_database_wordcount(const CHAR *name, const msi_table *tables,
2210                                       int num_tables, INT wordcount)
2211 {
2212     MSIHANDLE db;
2213     UINT r;
2214     int j;
2215
2216     r = MsiOpenDatabaseA(name, MSIDBOPEN_CREATE, &db);
2217     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2218
2219     /* import the tables into the database */
2220     for (j = 0; j < num_tables; j++)
2221     {
2222         const msi_table *table = &tables[j];
2223
2224         write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
2225
2226         r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
2227         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2228
2229         DeleteFileA(table->filename);
2230     }
2231
2232     write_msi_summary_info(db, wordcount);
2233
2234     r = MsiDatabaseCommit(db);
2235     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2236
2237     MsiCloseHandle(db);
2238 }
2239
2240 static void check_service_is_installed(void)
2241 {
2242     SC_HANDLE scm, service;
2243     BOOL res;
2244
2245     scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
2246     ok(scm != NULL, "Failed to open the SC Manager\n");
2247
2248     service = OpenService(scm, "TestService", SC_MANAGER_ALL_ACCESS);
2249     ok(service != NULL, "Failed to open TestService\n");
2250
2251     res = DeleteService(service);
2252     ok(res, "Failed to delete TestService\n");
2253
2254     CloseServiceHandle(service);
2255     CloseServiceHandle(scm);
2256 }
2257
2258 static BOOL notify_system_change(DWORD event_type, STATEMGRSTATUS *status)
2259 {
2260     RESTOREPOINTINFOA spec;
2261
2262     spec.dwEventType = event_type;
2263     spec.dwRestorePtType = APPLICATION_INSTALL;
2264     spec.llSequenceNumber = status->llSequenceNumber;
2265     lstrcpyA(spec.szDescription, "msitest restore point");
2266
2267     return pSRSetRestorePointA(&spec, status);
2268 }
2269
2270 static void remove_restore_point(DWORD seq_number)
2271 {
2272     DWORD res;
2273
2274     res = pSRRemoveRestorePoint(seq_number);
2275     if (res != ERROR_SUCCESS)
2276         trace("Failed to remove the restore point : %08x\n", res);
2277 }
2278
2279 static void test_MsiInstallProduct(void)
2280 {
2281     UINT r;
2282     CHAR path[MAX_PATH];
2283     LONG res;
2284     HKEY hkey;
2285     DWORD num, size, type;
2286
2287     if (on_win9x)
2288     {
2289         win_skip("Services are not implemented on Win9x and WinMe\n");
2290         return;
2291     }
2292
2293     /* szPackagePath is NULL */
2294     r = MsiInstallProductA(NULL, "INSTALL=ALL");
2295     ok(r == ERROR_INVALID_PARAMETER,
2296        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2297
2298     /* both szPackagePath and szCommandLine are NULL */
2299     r = MsiInstallProductA(NULL, NULL);
2300     ok(r == ERROR_INVALID_PARAMETER,
2301        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2302
2303     /* szPackagePath is empty */
2304     r = MsiInstallProductA("", "INSTALL=ALL");
2305     ok(r == ERROR_PATH_NOT_FOUND,
2306        "Expected ERROR_PATH_NOT_FOUND, got %d\n", r);
2307
2308     create_test_files();
2309     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
2310
2311     /* install, don't publish */
2312     r = MsiInstallProductA(msifile, NULL);
2313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2314
2315     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
2316     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
2317     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
2318     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
2319     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
2320     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
2321     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
2322     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
2323     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
2324     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
2325     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
2326     ok(delete_pf("msitest", FALSE), "File not installed\n");
2327
2328     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
2329     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2330
2331     size = MAX_PATH;
2332     type = REG_SZ;
2333     res = RegQueryValueExA(hkey, "Name", NULL, &type, (LPBYTE)path, &size);
2334     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2335     ok(!lstrcmpA(path, "imaname"), "Expected imaname, got %s\n", path);
2336
2337     size = MAX_PATH;
2338     type = REG_SZ;
2339     res = RegQueryValueExA(hkey, "blah", NULL, &type, (LPBYTE)path, &size);
2340     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2341
2342     size = sizeof(num);
2343     type = REG_DWORD;
2344     res = RegQueryValueExA(hkey, "number", NULL, &type, (LPBYTE)&num, &size);
2345     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2346     ok(num == 314, "Expected 314, got %d\n", num);
2347
2348     size = MAX_PATH;
2349     type = REG_SZ;
2350     res = RegQueryValueExA(hkey, "OrderTestName", NULL, &type, (LPBYTE)path, &size);
2351     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2352     ok(!lstrcmpA(path, "OrderTestValue"), "Expected OrderTestValue, got %s\n", path);
2353
2354     check_service_is_installed();
2355
2356     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
2357
2358     /* not published, reinstall */
2359     r = MsiInstallProductA(msifile, NULL);
2360     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2361
2362     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
2363     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
2364     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
2365     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
2366     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
2367     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
2368     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
2369     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
2370     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
2371     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
2372     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
2373     ok(delete_pf("msitest", FALSE), "File not installed\n");
2374
2375     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
2376     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2377     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
2378
2379     create_database(msifile, up_tables, sizeof(up_tables) / sizeof(msi_table));
2380
2381     /* not published, RemovePreviousVersions set */
2382     r = MsiInstallProductA(msifile, NULL);
2383     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2384
2385     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
2386     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
2387     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
2388     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
2389     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
2390     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
2391     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
2392     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
2393     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
2394     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
2395     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
2396     ok(delete_pf("msitest", FALSE), "File not installed\n");
2397
2398     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
2399     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2400     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
2401
2402     create_database(msifile, up2_tables, sizeof(up2_tables) / sizeof(msi_table));
2403
2404     /* not published, version number bumped */
2405     r = MsiInstallProductA(msifile, NULL);
2406     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2407
2408     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
2409     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
2410     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
2411     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
2412     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
2413     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
2414     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
2415     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
2416     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
2417     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
2418     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
2419     ok(delete_pf("msitest", FALSE), "File not installed\n");
2420
2421     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
2422     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2423     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
2424
2425     create_database(msifile, up3_tables, sizeof(up3_tables) / sizeof(msi_table));
2426
2427     /* not published, RemovePreviousVersions set and version number bumped */
2428     r = MsiInstallProductA(msifile, NULL);
2429     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2430
2431     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
2432     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
2433     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
2434     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
2435     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
2436     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
2437     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
2438     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
2439     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
2440     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
2441     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
2442     ok(delete_pf("msitest", FALSE), "File not installed\n");
2443
2444     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
2445     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2446     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
2447
2448     create_database(msifile, up4_tables, sizeof(up4_tables) / sizeof(msi_table));
2449
2450     /* install, publish product */
2451     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
2452     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2453
2454     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
2455     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
2456     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
2457     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
2458     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
2459     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
2460     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
2461     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
2462     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
2463     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
2464     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
2465     ok(delete_pf("msitest", FALSE), "File not installed\n");
2466
2467     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
2468     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2469
2470     create_database(msifile, up4_tables, sizeof(up4_tables) / sizeof(msi_table));
2471
2472     /* published, reinstall */
2473     r = MsiInstallProductA(msifile, NULL);
2474     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2475
2476     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
2477     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
2478     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
2479     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
2480     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
2481     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
2482     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
2483     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
2484     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
2485     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
2486     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
2487     ok(delete_pf("msitest", FALSE), "File not installed\n");
2488
2489     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
2490     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2491
2492     create_database(msifile, up5_tables, sizeof(up5_tables) / sizeof(msi_table));
2493
2494     /* published product, RemovePreviousVersions set */
2495     r = MsiInstallProductA(msifile, NULL);
2496     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2497
2498     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
2499     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
2500     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
2501     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
2502     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
2503     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
2504     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
2505     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
2506     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
2507     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
2508     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
2509     ok(delete_pf("msitest", FALSE), "File not installed\n");
2510
2511     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
2512     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2513
2514     create_database(msifile, up6_tables, sizeof(up6_tables) / sizeof(msi_table));
2515
2516     /* published product, version number bumped */
2517     r = MsiInstallProductA(msifile, NULL);
2518     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2519
2520     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
2521     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
2522     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
2523     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
2524     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
2525     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
2526     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
2527     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
2528     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
2529     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
2530     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
2531     ok(delete_pf("msitest", FALSE), "File not installed\n");
2532
2533     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
2534     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2535
2536     create_database(msifile, up7_tables, sizeof(up7_tables) / sizeof(msi_table));
2537
2538     /* published product, RemovePreviousVersions set and version number bumped */
2539     r = MsiInstallProductA(msifile, NULL);
2540     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2541
2542     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
2543     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
2544     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
2545     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
2546     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
2547     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
2548     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
2549     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
2550     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
2551     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
2552     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
2553     ok(delete_pf("msitest", FALSE), "File not installed\n");
2554
2555     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
2556     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2557
2558     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2559     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2560
2561     delete_test_files();
2562 }
2563
2564 static void test_MsiSetComponentState(void)
2565 {
2566     INSTALLSTATE installed, action;
2567     MSIHANDLE package;
2568     char path[MAX_PATH];
2569     UINT r;
2570
2571     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
2572
2573     CoInitialize(NULL);
2574
2575     lstrcpy(path, CURR_DIR);
2576     lstrcat(path, "\\");
2577     lstrcat(path, msifile);
2578
2579     r = MsiOpenPackage(path, &package);
2580     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2581
2582     r = MsiDoAction(package, "CostInitialize");
2583     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2584
2585     r = MsiDoAction(package, "FileCost");
2586     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2587
2588     r = MsiDoAction(package, "CostFinalize");
2589     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2590
2591     r = MsiGetComponentState(package, "dangler", &installed, &action);
2592     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2593     ok(installed == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", installed);
2594     ok(action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
2595
2596     r = MsiSetComponentState(package, "dangler", INSTALLSTATE_SOURCE);
2597     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2598
2599     MsiCloseHandle(package);
2600     CoUninitialize();
2601
2602     DeleteFileA(msifile);
2603 }
2604
2605 static void test_packagecoltypes(void)
2606 {
2607     MSIHANDLE hdb, view, rec;
2608     char path[MAX_PATH];
2609     LPCSTR query;
2610     UINT r, count;
2611
2612     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
2613
2614     CoInitialize(NULL);
2615
2616     lstrcpy(path, CURR_DIR);
2617     lstrcat(path, "\\");
2618     lstrcat(path, msifile);
2619
2620     r = MsiOpenDatabase(path, MSIDBOPEN_READONLY, &hdb);
2621     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2622
2623     query = "SELECT * FROM `Media`";
2624     r = MsiDatabaseOpenView( hdb, query, &view );
2625     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
2626
2627     r = MsiViewGetColumnInfo( view, MSICOLINFO_NAMES, &rec );
2628     count = MsiRecordGetFieldCount( rec );
2629     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
2630     ok(count == 6, "Expected 6, got %d\n", count);
2631     ok(check_record(rec, 1, "DiskId"), "wrong column label\n");
2632     ok(check_record(rec, 2, "LastSequence"), "wrong column label\n");
2633     ok(check_record(rec, 3, "DiskPrompt"), "wrong column label\n");
2634     ok(check_record(rec, 4, "Cabinet"), "wrong column label\n");
2635     ok(check_record(rec, 5, "VolumeLabel"), "wrong column label\n");
2636     ok(check_record(rec, 6, "Source"), "wrong column label\n");
2637     MsiCloseHandle(rec);
2638
2639     r = MsiViewGetColumnInfo( view, MSICOLINFO_TYPES, &rec );
2640     count = MsiRecordGetFieldCount( rec );
2641     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
2642     ok(count == 6, "Expected 6, got %d\n", count);
2643     ok(check_record(rec, 1, "i2"), "wrong column label\n");
2644     ok(check_record(rec, 2, "i4"), "wrong column label\n");
2645     ok(check_record(rec, 3, "L64"), "wrong column label\n");
2646     ok(check_record(rec, 4, "S255"), "wrong column label\n");
2647     ok(check_record(rec, 5, "S32"), "wrong column label\n");
2648     ok(check_record(rec, 6, "S72"), "wrong column label\n");
2649
2650     MsiCloseHandle(rec);
2651     MsiCloseHandle(view);
2652     MsiCloseHandle(hdb);
2653     CoUninitialize();
2654
2655     DeleteFile(msifile);
2656 }
2657
2658 static void create_cc_test_files(void)
2659 {
2660     CCAB cabParams;
2661     HFCI hfci;
2662     ERF erf;
2663     static CHAR cab_context[] = "test%d.cab";
2664     BOOL res;
2665
2666     create_file("maximus", 500);
2667     create_file("augustus", 50000);
2668     create_file("tiberius", 500);
2669     create_file("caesar", 500);
2670
2671     set_cab_parameters(&cabParams, "test1.cab", 40000);
2672
2673     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
2674                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
2675                       get_temp_file, &cabParams, cab_context);
2676     ok(hfci != NULL, "Failed to create an FCI context\n");
2677
2678     res = add_file(hfci, "maximus", tcompTYPE_NONE);
2679     ok(res, "Failed to add file maximus\n");
2680
2681     res = add_file(hfci, "augustus", tcompTYPE_NONE);
2682     ok(res, "Failed to add file augustus\n");
2683
2684     res = add_file(hfci, "tiberius", tcompTYPE_NONE);
2685     ok(res, "Failed to add file tiberius\n");
2686
2687     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
2688     ok(res, "Failed to flush the cabinet\n");
2689
2690     res = FCIDestroy(hfci);
2691     ok(res, "Failed to destroy the cabinet\n");
2692
2693     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
2694
2695     DeleteFile("maximus");
2696     DeleteFile("augustus");
2697     DeleteFile("tiberius");
2698     DeleteFile("caesar");
2699 }
2700
2701 static void delete_cab_files(void)
2702 {
2703     SHFILEOPSTRUCT shfl;
2704     CHAR path[MAX_PATH+10];
2705
2706     lstrcpyA(path, CURR_DIR);
2707     lstrcatA(path, "\\*.cab");
2708     path[strlen(path) + 1] = '\0';
2709
2710     shfl.hwnd = NULL;
2711     shfl.wFunc = FO_DELETE;
2712     shfl.pFrom = path;
2713     shfl.pTo = NULL;
2714     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
2715
2716     SHFileOperation(&shfl);
2717 }
2718
2719 static void test_continuouscabs(void)
2720 {
2721     UINT r;
2722
2723     create_cc_test_files();
2724     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
2725
2726     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2727
2728     r = MsiInstallProductA(msifile, NULL);
2729     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
2730     {
2731         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2732         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2733         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2734         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2735         ok(delete_pf("msitest", FALSE), "File not installed\n");
2736     }
2737
2738     delete_cab_files();
2739     DeleteFile(msifile);
2740
2741     create_cc_test_files();
2742     create_database(msifile, cc2_tables, sizeof(cc2_tables) / sizeof(msi_table));
2743
2744     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2745
2746     r = MsiInstallProductA(msifile, NULL);
2747     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2748     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2749     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2750     ok(delete_pf("msitest\\tiberius", TRUE), "File not installed\n");
2751     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2752     ok(delete_pf("msitest", FALSE), "File not installed\n");
2753
2754     delete_cab_files();
2755     DeleteFile(msifile);
2756 }
2757
2758 static void test_caborder(void)
2759 {
2760     UINT r;
2761
2762     create_file("imperator", 100);
2763     create_file("maximus", 500);
2764     create_file("augustus", 50000);
2765     create_file("caesar", 500);
2766
2767     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
2768
2769     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2770
2771     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
2772     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
2773     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
2774
2775     r = MsiInstallProductA(msifile, NULL);
2776     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
2777     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
2778     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
2779     todo_wine
2780     {
2781         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
2782         ok(!delete_pf("msitest", FALSE), "File is installed\n");
2783     }
2784
2785     delete_cab_files();
2786
2787     create_cab_file("test1.cab", MEDIA_SIZE, "imperator\0");
2788     create_cab_file("test2.cab", MEDIA_SIZE, "maximus\0augustus\0");
2789     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
2790
2791     r = MsiInstallProductA(msifile, NULL);
2792     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
2793     ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
2794     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
2795     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
2796     todo_wine
2797     {
2798         ok(!delete_pf("msitest", FALSE), "File is installed\n");
2799     }
2800
2801     delete_cab_files();
2802     DeleteFile(msifile);
2803
2804     create_cc_test_files();
2805     create_database(msifile, co_tables, sizeof(co_tables) / sizeof(msi_table));
2806
2807     r = MsiInstallProductA(msifile, NULL);
2808     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
2809     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
2810     ok(!delete_pf("msitest", FALSE), "File is installed\n");
2811     todo_wine
2812     {
2813         ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
2814         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
2815     }
2816
2817     delete_cab_files();
2818     DeleteFile(msifile);
2819
2820     create_cc_test_files();
2821     create_database(msifile, co2_tables, sizeof(co2_tables) / sizeof(msi_table));
2822
2823     r = MsiInstallProductA(msifile, NULL);
2824     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
2825     todo_wine
2826     {
2827         ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
2828         ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
2829         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
2830         ok(!delete_pf("msitest", FALSE), "File is installed\n");
2831     }
2832
2833     delete_cab_files();
2834     DeleteFile("imperator");
2835     DeleteFile("maximus");
2836     DeleteFile("augustus");
2837     DeleteFile("caesar");
2838     DeleteFile(msifile);
2839 }
2840
2841 static void test_mixedmedia(void)
2842 {
2843     UINT r;
2844
2845     CreateDirectoryA("msitest", NULL);
2846     create_file("msitest\\maximus", 500);
2847     create_file("msitest\\augustus", 500);
2848     create_file("caesar", 500);
2849
2850     create_database(msifile, mm_tables, sizeof(mm_tables) / sizeof(msi_table));
2851
2852     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2853
2854     create_cab_file("test1.cab", MEDIA_SIZE, "caesar\0");
2855
2856     r = MsiInstallProductA(msifile, NULL);
2857     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2858     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2859     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2860     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2861     ok(delete_pf("msitest", FALSE), "File not installed\n");
2862
2863     /* Delete the files in the temp (current) folder */
2864     DeleteFile("msitest\\maximus");
2865     DeleteFile("msitest\\augustus");
2866     RemoveDirectory("msitest");
2867     DeleteFile("caesar");
2868     DeleteFile("test1.cab");
2869     DeleteFile(msifile);
2870 }
2871
2872 static void test_samesequence(void)
2873 {
2874     UINT r;
2875
2876     create_cc_test_files();
2877     create_database(msifile, ss_tables, sizeof(ss_tables) / sizeof(msi_table));
2878
2879     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2880
2881     r = MsiInstallProductA(msifile, NULL);
2882     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
2883     {
2884         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2885         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2886         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2887         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2888         ok(delete_pf("msitest", FALSE), "File not installed\n");
2889     }
2890
2891     delete_cab_files();
2892     DeleteFile(msifile);
2893 }
2894
2895 static void test_uiLevelFlags(void)
2896 {
2897     UINT r;
2898
2899     create_cc_test_files();
2900     create_database(msifile, ui_tables, sizeof(ui_tables) / sizeof(msi_table));
2901
2902     MsiSetInternalUI(INSTALLUILEVEL_NONE | INSTALLUILEVEL_SOURCERESONLY, NULL);
2903
2904     r = MsiInstallProductA(msifile, NULL);
2905     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
2906     {
2907         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2908         ok(!delete_pf("msitest\\maximus", TRUE), "UI install occurred, but execute-only was requested.\n");
2909         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2910         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2911         ok(delete_pf("msitest", FALSE), "File not installed\n");
2912     }
2913
2914     delete_cab_files();
2915     DeleteFile(msifile);
2916 }
2917
2918 static BOOL file_matches(LPSTR path)
2919 {
2920     CHAR buf[MAX_PATH];
2921     HANDLE file;
2922     DWORD size;
2923
2924     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
2925                       NULL, OPEN_EXISTING, 0, NULL);
2926
2927     ZeroMemory(buf, MAX_PATH);
2928     ReadFile(file, buf, 15, &size, NULL);
2929     CloseHandle(file);
2930
2931     return !lstrcmp(buf, "msitest\\maximus");
2932 }
2933
2934 static void test_readonlyfile(void)
2935 {
2936     UINT r;
2937     DWORD size;
2938     HANDLE file;
2939     CHAR path[MAX_PATH];
2940
2941     CreateDirectoryA("msitest", NULL);
2942     create_file("msitest\\maximus", 500);
2943     create_database(msifile, rof_tables, sizeof(rof_tables) / sizeof(msi_table));
2944
2945     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2946
2947     lstrcpy(path, PROG_FILES_DIR);
2948     lstrcat(path, "\\msitest");
2949     CreateDirectory(path, NULL);
2950
2951     lstrcat(path, "\\maximus");
2952     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
2953                       NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
2954
2955     WriteFile(file, "readonlyfile", strlen("readonlyfile"), &size, NULL);
2956     CloseHandle(file);
2957
2958     r = MsiInstallProductA(msifile, NULL);
2959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2960     ok(file_matches(path), "Expected file to be overwritten\n");
2961     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2962     ok(delete_pf("msitest", FALSE), "File not installed\n");
2963
2964     /* Delete the files in the temp (current) folder */
2965     DeleteFile("msitest\\maximus");
2966     RemoveDirectory("msitest");
2967     DeleteFile(msifile);
2968 }
2969
2970 static void test_readonlyfile_cab(void)
2971 {
2972     UINT r;
2973     DWORD size;
2974     HANDLE file;
2975     CHAR path[MAX_PATH];
2976     CHAR buf[16];
2977
2978     CreateDirectoryA("msitest", NULL);
2979     create_file("maximus", 500);
2980     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
2981     DeleteFile("maximus");
2982
2983     create_database(msifile, rofc_tables, sizeof(rofc_tables) / sizeof(msi_table));
2984
2985     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2986
2987     lstrcpy(path, PROG_FILES_DIR);
2988     lstrcat(path, "\\msitest");
2989     CreateDirectory(path, NULL);
2990
2991     lstrcat(path, "\\maximus");
2992     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
2993                       NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
2994
2995     WriteFile(file, "readonlyfile", strlen("readonlyfile"), &size, NULL);
2996     CloseHandle(file);
2997
2998     r = MsiInstallProductA(msifile, NULL);
2999     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3000
3001     memset( buf, 0, sizeof(buf) );
3002     if ((file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
3003                            NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
3004     {
3005         ReadFile(file, buf, sizeof(buf) - 1, &size, NULL);
3006         CloseHandle(file);
3007     }
3008     ok(!memcmp( buf, "maximus", sizeof("maximus")-1 ), "Expected file to be overwritten, got '%s'\n", buf);
3009     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3010     ok(delete_pf("msitest", FALSE), "File not installed\n");
3011
3012     /* Delete the files in the temp (current) folder */
3013     delete_cab_files();
3014     DeleteFile("msitest\\maximus");
3015     RemoveDirectory("msitest");
3016     DeleteFile(msifile);
3017 }
3018
3019 static BOOL add_cabinet_storage(LPCSTR db, LPCSTR cabinet)
3020 {
3021     WCHAR dbW[MAX_PATH], cabinetW[MAX_PATH];
3022     IStorage *stg;
3023     IStream *stm;
3024     HRESULT hr;
3025     HANDLE handle;
3026
3027     MultiByteToWideChar(CP_ACP, 0, db, -1, dbW, MAX_PATH);
3028     hr = StgOpenStorage(dbW, NULL, STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
3029     if (FAILED(hr))
3030         return FALSE;
3031
3032     MultiByteToWideChar(CP_ACP, 0, cabinet, -1, cabinetW, MAX_PATH);
3033     hr = IStorage_CreateStream(stg, cabinetW, STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3034     if (FAILED(hr))
3035     {
3036         IStorage_Release(stg);
3037         return FALSE;
3038     }
3039
3040     handle = CreateFileW(cabinetW, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
3041     if (handle != INVALID_HANDLE_VALUE)
3042     {
3043         DWORD count;
3044         char buffer[1024];
3045         if (ReadFile(handle, buffer, sizeof(buffer), &count, NULL))
3046             IStream_Write(stm, buffer, count, &count);
3047         CloseHandle(handle);
3048     }
3049
3050     IStream_Release(stm);
3051     IStorage_Release(stg);
3052
3053     return TRUE;
3054 }
3055
3056 static void test_lastusedsource(void)
3057 {
3058     static char prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
3059
3060     UINT r;
3061     char value[MAX_PATH], path[MAX_PATH];
3062     DWORD size;
3063
3064     if (!pMsiSourceListGetInfoA)
3065     {
3066         win_skip("MsiSourceListGetInfoA is not available\n");
3067         return;
3068     }
3069
3070     CreateDirectoryA("msitest", NULL);
3071     create_file("maximus", 500);
3072     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
3073     DeleteFile("maximus");
3074
3075     create_database("msifile0.msi", lus0_tables, sizeof(lus0_tables) / sizeof(msi_table));
3076     create_database("msifile1.msi", lus1_tables, sizeof(lus1_tables) / sizeof(msi_table));
3077     create_database("msifile2.msi", lus2_tables, sizeof(lus2_tables) / sizeof(msi_table));
3078
3079     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3080
3081     /* no cabinet file */
3082
3083     size = MAX_PATH;
3084     lstrcpyA(value, "aaa");
3085     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3086                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size);
3087     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
3088     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
3089
3090     r = MsiInstallProductA("msifile0.msi", "PUBLISH_PRODUCT=1");
3091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3092
3093     lstrcpyA(path, CURR_DIR);
3094     lstrcatA(path, "\\");
3095
3096     size = MAX_PATH;
3097     lstrcpyA(value, "aaa");
3098     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3099                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size);
3100     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3101     todo_wine
3102     {
3103     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3104     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3105     }
3106
3107     r = MsiInstallProductA("msifile0.msi", "REMOVE=ALL");
3108     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3109
3110     /* separate cabinet file */
3111
3112     size = MAX_PATH;
3113     lstrcpyA(value, "aaa");
3114     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3115                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size);
3116     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
3117     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
3118
3119     r = MsiInstallProductA("msifile1.msi", "PUBLISH_PRODUCT=1");
3120     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3121
3122     lstrcpyA(path, CURR_DIR);
3123     lstrcatA(path, "\\");
3124
3125     size = MAX_PATH;
3126     lstrcpyA(value, "aaa");
3127     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3128                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size);
3129     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3130     todo_wine
3131     {
3132     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3133     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3134     }
3135
3136     r = MsiInstallProductA("msifile1.msi", "REMOVE=ALL");
3137     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3138
3139     size = MAX_PATH;
3140     lstrcpyA(value, "aaa");
3141     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3142                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size);
3143     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
3144     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
3145
3146     /* embedded cabinet stream */
3147
3148     add_cabinet_storage("msifile2.msi", "test1.cab");
3149
3150     r = MsiInstallProductA("msifile2.msi", "PUBLISH_PRODUCT=1");
3151     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3152
3153     size = MAX_PATH;
3154     lstrcpyA(value, "aaa");
3155     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3156                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size);
3157     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3158     todo_wine
3159     {
3160     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3161     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3162     }
3163
3164     r = MsiInstallProductA("msifile2.msi", "REMOVE=ALL");
3165     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3166
3167     size = MAX_PATH;
3168     lstrcpyA(value, "aaa");
3169     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3170                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size);
3171     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
3172     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
3173
3174     /* Delete the files in the temp (current) folder */
3175     delete_cab_files();
3176     DeleteFile("msitest\\maximus");
3177     RemoveDirectory("msitest");
3178     DeleteFile("msifile0.msi");
3179     DeleteFile("msifile1.msi");
3180     DeleteFile("msifile2.msi");
3181 }
3182
3183 static void test_setdirproperty(void)
3184 {
3185     UINT r;
3186
3187     CreateDirectoryA("msitest", NULL);
3188     create_file("msitest\\maximus", 500);
3189     create_database(msifile, sdp_tables, sizeof(sdp_tables) / sizeof(msi_table));
3190
3191     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3192
3193     r = MsiInstallProductA(msifile, NULL);
3194     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3195     ok(delete_cf("msitest\\maximus", TRUE), "File not installed\n");
3196     ok(delete_cf("msitest", FALSE), "File not installed\n");
3197
3198     /* Delete the files in the temp (current) folder */
3199     DeleteFile(msifile);
3200     DeleteFile("msitest\\maximus");
3201     RemoveDirectory("msitest");
3202 }
3203
3204 static void test_cabisextracted(void)
3205 {
3206     UINT r;
3207
3208     CreateDirectoryA("msitest", NULL);
3209     create_file("msitest\\gaius", 500);
3210     create_file("maximus", 500);
3211     create_file("augustus", 500);
3212     create_file("caesar", 500);
3213
3214     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
3215     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
3216     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
3217
3218     create_database(msifile, cie_tables, sizeof(cie_tables) / sizeof(msi_table));
3219
3220     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3221
3222     r = MsiInstallProductA(msifile, NULL);
3223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3224     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3225     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
3226     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
3227     ok(delete_pf("msitest\\gaius", TRUE), "File not installed\n");
3228     ok(delete_pf("msitest", FALSE), "File not installed\n");
3229
3230     /* Delete the files in the temp (current) folder */
3231     delete_cab_files();
3232     DeleteFile(msifile);
3233     DeleteFile("maximus");
3234     DeleteFile("augustus");
3235     DeleteFile("caesar");
3236     DeleteFile("msitest\\gaius");
3237     RemoveDirectory("msitest");
3238 }
3239
3240 static void test_concurrentinstall(void)
3241 {
3242     UINT r;
3243     CHAR path[MAX_PATH];
3244
3245     CreateDirectoryA("msitest", NULL);
3246     CreateDirectoryA("msitest\\msitest", NULL);
3247     create_file("msitest\\maximus", 500);
3248     create_file("msitest\\msitest\\augustus", 500);
3249
3250     create_database(msifile, ci_tables, sizeof(ci_tables) / sizeof(msi_table));
3251
3252     lstrcpyA(path, CURR_DIR);
3253     lstrcatA(path, "\\msitest\\concurrent.msi");
3254     create_database(path, ci2_tables, sizeof(ci2_tables) / sizeof(msi_table));
3255
3256     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3257
3258     r = MsiInstallProductA(msifile, NULL);
3259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3260     if (!delete_pf("msitest\\augustus", TRUE))
3261         trace("concurrent installs not supported\n");
3262     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3263     ok(delete_pf("msitest", FALSE), "File not installed\n");
3264
3265     DeleteFile(path);
3266
3267     r = MsiInstallProductA(msifile, NULL);
3268     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3269     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3270     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3271     ok(delete_pf("msitest", FALSE), "File not installed\n");
3272
3273     DeleteFile(msifile);
3274     DeleteFile("msitest\\msitest\\augustus");
3275     DeleteFile("msitest\\maximus");
3276     RemoveDirectory("msitest\\msitest");
3277     RemoveDirectory("msitest");
3278 }
3279
3280 static void test_setpropertyfolder(void)
3281 {
3282     UINT r;
3283     CHAR path[MAX_PATH];
3284     DWORD attr;
3285
3286     lstrcpyA(path, PROG_FILES_DIR);
3287     lstrcatA(path, "\\msitest\\added");
3288
3289     CreateDirectoryA("msitest", NULL);
3290     create_file("msitest\\maximus", 500);
3291
3292     create_database(msifile, spf_tables, sizeof(spf_tables) / sizeof(msi_table));
3293
3294     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3295
3296     r = MsiInstallProductA(msifile, NULL);
3297     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3298     attr = GetFileAttributesA(path);
3299     if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY))
3300     {
3301         ok(delete_pf("msitest\\added\\maximus", TRUE), "File not installed\n");
3302         ok(delete_pf("msitest\\added", FALSE), "File not installed\n");
3303         ok(delete_pf("msitest", FALSE), "File not installed\n");
3304     }
3305     else
3306     {
3307         trace("changing folder property not supported\n");
3308         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3309         ok(delete_pf("msitest", FALSE), "File not installed\n");
3310     }
3311
3312     /* Delete the files in the temp (current) folder */
3313     DeleteFile(msifile);
3314     DeleteFile("msitest\\maximus");
3315     RemoveDirectory("msitest");
3316 }
3317
3318 static BOOL file_exists(LPCSTR file)
3319 {
3320     return GetFileAttributes(file) != INVALID_FILE_ATTRIBUTES;
3321 }
3322
3323 static BOOL pf_exists(LPCSTR file)
3324 {
3325     CHAR path[MAX_PATH];
3326
3327     lstrcpyA(path, PROG_FILES_DIR);
3328     lstrcatA(path, "\\");
3329     lstrcatA(path, file);
3330
3331     return file_exists(path);
3332 }
3333
3334 static void delete_pfmsitest_files(void)
3335 {
3336     SHFILEOPSTRUCT shfl;
3337     CHAR path[MAX_PATH+11];
3338
3339     lstrcpyA(path, PROG_FILES_DIR);
3340     lstrcatA(path, "\\msitest\\*");
3341     path[strlen(path) + 1] = '\0';
3342
3343     shfl.hwnd = NULL;
3344     shfl.wFunc = FO_DELETE;
3345     shfl.pFrom = path;
3346     shfl.pTo = NULL;
3347     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
3348
3349     SHFileOperation(&shfl);
3350
3351     lstrcpyA(path, PROG_FILES_DIR);
3352     lstrcatA(path, "\\msitest");
3353     RemoveDirectoryA(path);
3354 }
3355
3356 static void check_reg_str(HKEY prodkey, LPCSTR name, LPCSTR expected, BOOL bcase, DWORD line)
3357 {
3358     char val[MAX_PATH];
3359     DWORD size, type;
3360     LONG res;
3361
3362     size = MAX_PATH;
3363     val[0] = '\0';
3364     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)val, &size);
3365
3366     if (res != ERROR_SUCCESS ||
3367         (type != REG_SZ && type != REG_EXPAND_SZ && type != REG_MULTI_SZ))
3368     {
3369         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
3370         return;
3371     }
3372
3373     if (!expected)
3374         ok_(__FILE__, line)(lstrlenA(val) == 0, "Expected empty string, got %s\n", val);
3375     else
3376     {
3377         if (bcase)
3378             ok_(__FILE__, line)(!lstrcmpA(val, expected), "Expected %s, got %s\n", expected, val);
3379         else
3380             ok_(__FILE__, line)(!lstrcmpiA(val, expected), "Expected %s, got %s\n", expected, val);
3381     }
3382 }
3383
3384 static void check_reg_dword(HKEY prodkey, LPCSTR name, DWORD expected, DWORD line)
3385 {
3386     DWORD val, size, type;
3387     LONG res;
3388
3389     size = sizeof(DWORD);
3390     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)&val, &size);
3391
3392     if (res != ERROR_SUCCESS || type != REG_DWORD)
3393     {
3394         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
3395         return;
3396     }
3397
3398     ok_(__FILE__, line)(val == expected, "Expected %d, got %d\n", expected, val);
3399 }
3400
3401 static void check_reg_dword2(HKEY prodkey, LPCSTR name, DWORD expected1, DWORD expected2, DWORD line)
3402 {
3403     DWORD val, size, type;
3404     LONG res;
3405
3406     size = sizeof(DWORD);
3407     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)&val, &size);
3408
3409     if (res != ERROR_SUCCESS || type != REG_DWORD)
3410     {
3411         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
3412         return;
3413     }
3414
3415     ok_(__FILE__, line)(val == expected1 || val == expected2, "Expected %d or %d, got %d\n", expected1, expected2, val);
3416 }
3417
3418 static void check_reg_dword3(HKEY prodkey, LPCSTR name, DWORD expected1, DWORD expected2, DWORD expected3, DWORD line)
3419 {
3420     DWORD val, size, type;
3421     LONG res;
3422
3423     size = sizeof(DWORD);
3424     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)&val, &size);
3425
3426     if (res != ERROR_SUCCESS || type != REG_DWORD)
3427     {
3428         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
3429         return;
3430     }
3431
3432     ok_(__FILE__, line)(val == expected1 || val == expected2 || val == expected3,
3433                         "Expected %d, %d or %d, got %d\n", expected1, expected2, expected3, val);
3434 }
3435
3436 #define CHECK_REG_STR(prodkey, name, expected) \
3437     check_reg_str(prodkey, name, expected, TRUE, __LINE__);
3438
3439 #define CHECK_DEL_REG_STR(prodkey, name, expected) \
3440     check_reg_str(prodkey, name, expected, TRUE, __LINE__); \
3441     RegDeleteValueA(prodkey, name);
3442
3443 #define CHECK_REG_ISTR(prodkey, name, expected) \
3444     check_reg_str(prodkey, name, expected, FALSE, __LINE__);
3445
3446 #define CHECK_DEL_REG_ISTR(prodkey, name, expected) \
3447     check_reg_str(prodkey, name, expected, FALSE, __LINE__); \
3448     RegDeleteValueA(prodkey, name);
3449
3450 #define CHECK_REG_DWORD(prodkey, name, expected) \
3451     check_reg_dword(prodkey, name, expected, __LINE__);
3452
3453 #define CHECK_DEL_REG_DWORD(prodkey, name, expected) \
3454     check_reg_dword(prodkey, name, expected, __LINE__); \
3455     RegDeleteValueA(prodkey, name);
3456
3457 #define CHECK_REG_DWORD2(prodkey, name, expected1, expected2) \
3458     check_reg_dword2(prodkey, name, expected1, expected2, __LINE__);
3459
3460 #define CHECK_DEL_REG_DWORD2(prodkey, name, expected1, expected2) \
3461     check_reg_dword2(prodkey, name, expected1, expected2, __LINE__); \
3462     RegDeleteValueA(prodkey, name);
3463
3464 #define CHECK_REG_DWORD3(prodkey, name, expected1, expected2, expected3) \
3465     check_reg_dword3(prodkey, name, expected1, expected2, expected3, __LINE__);
3466
3467 #define CHECK_DEL_REG_DWORD3(prodkey, name, expected1, expected2, expected3) \
3468     check_reg_dword3(prodkey, name, expected1, expected2, expected3, __LINE__); \
3469     RegDeleteValueA(prodkey, name);
3470
3471 static void get_date_str(LPSTR date)
3472 {
3473     SYSTEMTIME systime;
3474
3475     static const char date_fmt[] = "%d%02d%02d";
3476     GetLocalTime(&systime);
3477     sprintf(date, date_fmt, systime.wYear, systime.wMonth, systime.wDay);
3478 }
3479
3480 static void test_publish_registerproduct(void)
3481 {
3482     UINT r;
3483     LONG res;
3484     HKEY hkey;
3485     HKEY props, usage;
3486     LPSTR usersid;
3487     char date[MAX_PATH];
3488     char temp[MAX_PATH];
3489     char keypath[MAX_PATH];
3490
3491     static const CHAR uninstall[] = "Software\\Microsoft\\Windows\\CurrentVersion"
3492                                     "\\Uninstall\\{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
3493     static const CHAR userdata[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Installer"
3494                                    "\\UserData\\%s\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB";
3495     static const CHAR ugkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Installer"
3496                                 "\\UpgradeCodes\\51AAE0C44620A5E4788506E91F249BD2";
3497     static const CHAR userugkey[] = "Software\\Microsoft\\Installer\\UpgradeCodes"
3498                                     "\\51AAE0C44620A5E4788506E91F249BD2";
3499
3500     if (!get_user_sid(&usersid))
3501         return;
3502
3503     get_date_str(date);
3504     GetTempPath(MAX_PATH, temp);
3505
3506     CreateDirectoryA("msitest", NULL);
3507     create_file("msitest\\maximus", 500);
3508
3509     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
3510
3511     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3512
3513     /* RegisterProduct */
3514     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
3515     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3516     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3517     ok(delete_pf("msitest", FALSE), "File not installed\n");
3518
3519     res = RegOpenKeyA(HKEY_CURRENT_USER, userugkey, &hkey);
3520     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3521
3522     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, uninstall, &hkey);
3523     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3524
3525     CHECK_DEL_REG_STR(hkey, "DisplayName", "MSITEST");
3526     CHECK_DEL_REG_STR(hkey, "DisplayVersion", "1.1.1");
3527     CHECK_DEL_REG_STR(hkey, "InstallDate", date);
3528     CHECK_DEL_REG_STR(hkey, "InstallSource", temp);
3529     CHECK_DEL_REG_ISTR(hkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3530     CHECK_DEL_REG_STR(hkey, "Publisher", "Wine");
3531     CHECK_DEL_REG_STR(hkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3532     CHECK_DEL_REG_STR(hkey, "AuthorizedCDFPrefix", NULL);
3533     CHECK_DEL_REG_STR(hkey, "Comments", NULL);
3534     CHECK_DEL_REG_STR(hkey, "Contact", NULL);
3535     CHECK_DEL_REG_STR(hkey, "HelpLink", NULL);
3536     CHECK_DEL_REG_STR(hkey, "HelpTelephone", NULL);
3537     CHECK_DEL_REG_STR(hkey, "InstallLocation", NULL);
3538     CHECK_DEL_REG_STR(hkey, "Readme", NULL);
3539     CHECK_DEL_REG_STR(hkey, "Size", NULL);
3540     CHECK_DEL_REG_STR(hkey, "URLInfoAbout", NULL);
3541     CHECK_DEL_REG_STR(hkey, "URLUpdateInfo", NULL);
3542     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
3543     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
3544     CHECK_DEL_REG_DWORD(hkey, "VersionMajor", 1);
3545     CHECK_DEL_REG_DWORD(hkey, "VersionMinor", 1);
3546     CHECK_DEL_REG_DWORD(hkey, "WindowsInstaller", 1);
3547     todo_wine
3548     {
3549         CHECK_DEL_REG_DWORD3(hkey, "EstimatedSize", 12, -12, 4);
3550     }
3551
3552     RegDeleteKeyA(hkey, "");
3553     RegCloseKey(hkey);
3554
3555     sprintf(keypath, userdata, usersid);
3556     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
3557     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3558
3559     res = RegOpenKeyA(hkey, "InstallProperties", &props);
3560     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3561
3562     RegDeleteValueA(props, "LocalPackage"); /* LocalPackage is nondeterministic */
3563     CHECK_DEL_REG_STR(props, "DisplayName", "MSITEST");
3564     CHECK_DEL_REG_STR(props, "DisplayVersion", "1.1.1");
3565     CHECK_DEL_REG_STR(props, "InstallDate", date);
3566     CHECK_DEL_REG_STR(props, "InstallSource", temp);
3567     CHECK_DEL_REG_ISTR(props, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3568     CHECK_DEL_REG_STR(props, "Publisher", "Wine");
3569     CHECK_DEL_REG_STR(props, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3570     CHECK_DEL_REG_STR(props, "AuthorizedCDFPrefix", NULL);
3571     CHECK_DEL_REG_STR(props, "Comments", NULL);
3572     CHECK_DEL_REG_STR(props, "Contact", NULL);
3573     CHECK_DEL_REG_STR(props, "HelpLink", NULL);
3574     CHECK_DEL_REG_STR(props, "HelpTelephone", NULL);
3575     CHECK_DEL_REG_STR(props, "InstallLocation", NULL);
3576     CHECK_DEL_REG_STR(props, "Readme", NULL);
3577     CHECK_DEL_REG_STR(props, "Size", NULL);
3578     CHECK_DEL_REG_STR(props, "URLInfoAbout", NULL);
3579     CHECK_DEL_REG_STR(props, "URLUpdateInfo", NULL);
3580     CHECK_DEL_REG_DWORD(props, "Language", 1033);
3581     CHECK_DEL_REG_DWORD(props, "Version", 0x1010001);
3582     CHECK_DEL_REG_DWORD(props, "VersionMajor", 1);
3583     CHECK_DEL_REG_DWORD(props, "VersionMinor", 1);
3584     CHECK_DEL_REG_DWORD(props, "WindowsInstaller", 1);
3585     todo_wine
3586     {
3587         CHECK_DEL_REG_DWORD3(props, "EstimatedSize", 12, -12, 4);
3588     }
3589
3590     RegDeleteKeyA(props, "");
3591     RegCloseKey(props);
3592
3593     res = RegOpenKeyA(hkey, "Usage", &usage);
3594     todo_wine
3595     {
3596         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3597     }
3598
3599     RegDeleteKeyA(usage, "");
3600     RegCloseKey(usage);
3601     RegDeleteKeyA(hkey, "");
3602     RegCloseKey(hkey);
3603
3604     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, ugkey, &hkey);
3605     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3606
3607     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
3608
3609     RegDeleteKeyA(hkey, "");
3610     RegCloseKey(hkey);
3611
3612     /* RegisterProduct, machine */
3613     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 ALLUSERS=1");
3614     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3615     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3616     ok(delete_pf("msitest", FALSE), "File not installed\n");
3617
3618     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, userugkey, &hkey);
3619     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3620
3621     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, uninstall, &hkey);
3622     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3623
3624     CHECK_DEL_REG_STR(hkey, "DisplayName", "MSITEST");
3625     CHECK_DEL_REG_STR(hkey, "DisplayVersion", "1.1.1");
3626     CHECK_DEL_REG_STR(hkey, "InstallDate", date);
3627     CHECK_DEL_REG_STR(hkey, "InstallSource", temp);
3628     CHECK_DEL_REG_ISTR(hkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3629     CHECK_DEL_REG_STR(hkey, "Publisher", "Wine");
3630     CHECK_DEL_REG_STR(hkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3631     CHECK_DEL_REG_STR(hkey, "AuthorizedCDFPrefix", NULL);
3632     CHECK_DEL_REG_STR(hkey, "Comments", NULL);
3633     CHECK_DEL_REG_STR(hkey, "Contact", NULL);
3634     CHECK_DEL_REG_STR(hkey, "HelpLink", NULL);
3635     CHECK_DEL_REG_STR(hkey, "HelpTelephone", NULL);
3636     CHECK_DEL_REG_STR(hkey, "InstallLocation", NULL);
3637     CHECK_DEL_REG_STR(hkey, "Readme", NULL);
3638     CHECK_DEL_REG_STR(hkey, "Size", NULL);
3639     CHECK_DEL_REG_STR(hkey, "URLInfoAbout", NULL);
3640     CHECK_DEL_REG_STR(hkey, "URLUpdateInfo", NULL);
3641     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
3642     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
3643     CHECK_DEL_REG_DWORD(hkey, "VersionMajor", 1);
3644     CHECK_DEL_REG_DWORD(hkey, "VersionMinor", 1);
3645     CHECK_DEL_REG_DWORD(hkey, "WindowsInstaller", 1);
3646     todo_wine
3647     {
3648         CHECK_DEL_REG_DWORD3(hkey, "EstimatedSize", 12, -12, 4);
3649     }
3650
3651     RegDeleteKeyA(hkey, "");
3652     RegCloseKey(hkey);
3653
3654     sprintf(keypath, userdata, "S-1-5-18");
3655     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
3656     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3657
3658     res = RegOpenKeyA(hkey, "InstallProperties", &props);
3659     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3660
3661     RegDeleteValueA(props, "LocalPackage"); /* LocalPackage is nondeterministic */
3662     CHECK_DEL_REG_STR(props, "DisplayName", "MSITEST");
3663     CHECK_DEL_REG_STR(props, "DisplayVersion", "1.1.1");
3664     CHECK_DEL_REG_STR(props, "InstallDate", date);
3665     CHECK_DEL_REG_STR(props, "InstallSource", temp);
3666     CHECK_DEL_REG_ISTR(props, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3667     CHECK_DEL_REG_STR(props, "Publisher", "Wine");
3668     CHECK_DEL_REG_STR(props, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3669     CHECK_DEL_REG_STR(props, "AuthorizedCDFPrefix", NULL);
3670     CHECK_DEL_REG_STR(props, "Comments", NULL);
3671     CHECK_DEL_REG_STR(props, "Contact", NULL);
3672     CHECK_DEL_REG_STR(props, "HelpLink", NULL);
3673     CHECK_DEL_REG_STR(props, "HelpTelephone", NULL);
3674     CHECK_DEL_REG_STR(props, "InstallLocation", NULL);
3675     CHECK_DEL_REG_STR(props, "Readme", NULL);
3676     CHECK_DEL_REG_STR(props, "Size", NULL);
3677     CHECK_DEL_REG_STR(props, "URLInfoAbout", NULL);
3678     CHECK_DEL_REG_STR(props, "URLUpdateInfo", NULL);
3679     CHECK_DEL_REG_DWORD(props, "Language", 1033);
3680     CHECK_DEL_REG_DWORD(props, "Version", 0x1010001);
3681     CHECK_DEL_REG_DWORD(props, "VersionMajor", 1);
3682     CHECK_DEL_REG_DWORD(props, "VersionMinor", 1);
3683     CHECK_DEL_REG_DWORD(props, "WindowsInstaller", 1);
3684     todo_wine
3685     {
3686         CHECK_DEL_REG_DWORD3(props, "EstimatedSize", 12, -12, 4);
3687     }
3688
3689     RegDeleteKeyA(props, "");
3690     RegCloseKey(props);
3691
3692     res = RegOpenKeyA(hkey, "Usage", &usage);
3693     todo_wine
3694     {
3695         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3696     }
3697
3698     RegDeleteKeyA(usage, "");
3699     RegCloseKey(usage);
3700     RegDeleteKeyA(hkey, "");
3701     RegCloseKey(hkey);
3702
3703     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, ugkey, &hkey);
3704     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3705
3706     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
3707
3708     RegDeleteKeyA(hkey, "");
3709     RegCloseKey(hkey);
3710
3711     DeleteFile(msifile);
3712     DeleteFile("msitest\\maximus");
3713     RemoveDirectory("msitest");
3714     HeapFree(GetProcessHeap(), 0, usersid);
3715 }
3716
3717 static void test_publish_publishproduct(void)
3718 {
3719     UINT r;
3720     LONG res;
3721     LPSTR usersid;
3722     HKEY sourcelist, net, props;
3723     HKEY hkey, patches, media;
3724     CHAR keypath[MAX_PATH];
3725     CHAR temp[MAX_PATH];
3726     CHAR path[MAX_PATH];
3727
3728     static const CHAR prodpath[] = "Software\\Microsoft\\Windows\\CurrentVersion"
3729                                    "\\Installer\\UserData\\%s\\Products"
3730                                    "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
3731     static const CHAR cuprodpath[] = "Software\\Microsoft\\Installer\\Products"
3732                                      "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
3733     static const CHAR cuupgrades[] = "Software\\Microsoft\\Installer\\UpgradeCodes"
3734                                      "\\51AAE0C44620A5E4788506E91F249BD2";
3735     static const CHAR badprod[] = "Software\\Microsoft\\Windows\\CurrentVersion"
3736                                   "\\Installer\\Products"
3737                                   "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
3738     static const CHAR machprod[] = "Installer\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB";
3739     static const CHAR machup[] = "Installer\\UpgradeCodes\\51AAE0C44620A5E4788506E91F249BD2";
3740
3741     if (!get_user_sid(&usersid))
3742         return;
3743
3744     GetTempPath(MAX_PATH, temp);
3745
3746     CreateDirectoryA("msitest", NULL);
3747     create_file("msitest\\maximus", 500);
3748
3749     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
3750
3751     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3752
3753     /* PublishProduct, current user */
3754     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
3755     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3756     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3757     ok(delete_pf("msitest", FALSE), "File not installed\n");
3758
3759     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, badprod, &hkey);
3760     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3761
3762     sprintf(keypath, prodpath, usersid);
3763     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
3764     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3765
3766     res = RegOpenKeyA(hkey, "InstallProperties", &props);
3767     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3768
3769     res = RegOpenKeyA(hkey, "Patches", &patches);
3770     todo_wine
3771     {
3772         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3773
3774         CHECK_DEL_REG_STR(patches, "AllPatches", NULL);
3775     }
3776
3777     RegDeleteKeyA(patches, "");
3778     RegCloseKey(patches);
3779     RegDeleteKeyA(hkey, "");
3780     RegCloseKey(hkey);
3781
3782     res = RegOpenKeyA(HKEY_CURRENT_USER, cuprodpath, &hkey);
3783     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3784
3785     CHECK_DEL_REG_STR(hkey, "ProductName", "MSITEST");
3786     CHECK_DEL_REG_STR(hkey, "PackageCode", "AC75740029052c94DA02821EECD05F2F");
3787     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
3788     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
3789     CHECK_DEL_REG_DWORD(hkey, "AuthorizedLUAApp", 0);
3790     CHECK_DEL_REG_DWORD(hkey, "Assignment", 0);
3791     CHECK_DEL_REG_DWORD(hkey, "AdvertiseFlags", 0x184);
3792     CHECK_DEL_REG_DWORD(hkey, "InstanceType", 0);
3793     CHECK_DEL_REG_STR(hkey, "Clients", ":");
3794
3795     res = RegOpenKeyA(hkey, "SourceList", &sourcelist);
3796     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3797
3798     lstrcpyA(path, "n;1;");
3799     lstrcatA(path, temp);
3800     CHECK_DEL_REG_STR(sourcelist, "LastUsedSource", path);
3801     CHECK_DEL_REG_STR(sourcelist, "PackageName", "msitest.msi");
3802
3803     res = RegOpenKeyA(sourcelist, "Net", &net);
3804     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3805
3806     CHECK_DEL_REG_STR(net, "1", temp);
3807
3808     RegDeleteKeyA(net, "");
3809     RegCloseKey(net);
3810
3811     res = RegOpenKeyA(sourcelist, "Media", &media);
3812     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3813
3814     CHECK_DEL_REG_STR(media, "1", "DISK1;");
3815
3816     RegDeleteKeyA(media, "");
3817     RegCloseKey(media);
3818     RegDeleteKeyA(sourcelist, "");
3819     RegCloseKey(sourcelist);
3820     RegDeleteKeyA(hkey, "");
3821     RegCloseKey(hkey);
3822
3823     res = RegOpenKeyA(HKEY_CURRENT_USER, cuupgrades, &hkey);
3824     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3825
3826     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
3827
3828     RegDeleteKeyA(hkey, "");
3829     RegCloseKey(hkey);
3830
3831     /* PublishProduct, machine */
3832     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1 ALLUSERS=1");
3833     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3834     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3835     ok(delete_pf("msitest", FALSE), "File not installed\n");
3836
3837     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, badprod, &hkey);
3838     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3839
3840     sprintf(keypath, prodpath, "S-1-5-18");
3841     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
3842     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3843
3844     res = RegOpenKeyA(hkey, "InstallProperties", &props);
3845     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3846
3847     res = RegOpenKeyA(hkey, "Patches", &patches);
3848     todo_wine
3849     {
3850         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3851
3852         CHECK_DEL_REG_STR(patches, "AllPatches", NULL);
3853     }
3854
3855     RegDeleteKeyA(patches, "");
3856     RegCloseKey(patches);
3857     RegDeleteKeyA(hkey, "");
3858     RegCloseKey(hkey);
3859
3860     res = RegOpenKeyA(HKEY_CLASSES_ROOT, machprod, &hkey);
3861     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3862
3863     CHECK_DEL_REG_STR(hkey, "ProductName", "MSITEST");
3864     CHECK_DEL_REG_STR(hkey, "PackageCode", "AC75740029052c94DA02821EECD05F2F");
3865     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
3866     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
3867     CHECK_DEL_REG_DWORD(hkey, "AuthorizedLUAApp", 0);
3868     todo_wine CHECK_DEL_REG_DWORD(hkey, "Assignment", 1);
3869     CHECK_DEL_REG_DWORD(hkey, "AdvertiseFlags", 0x184);
3870     CHECK_DEL_REG_DWORD(hkey, "InstanceType", 0);
3871     CHECK_DEL_REG_STR(hkey, "Clients", ":");
3872
3873     res = RegOpenKeyA(hkey, "SourceList", &sourcelist);
3874     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3875
3876     lstrcpyA(path, "n;1;");
3877     lstrcatA(path, temp);
3878     CHECK_DEL_REG_STR(sourcelist, "LastUsedSource", path);
3879     CHECK_DEL_REG_STR(sourcelist, "PackageName", "msitest.msi");
3880
3881     res = RegOpenKeyA(sourcelist, "Net", &net);
3882     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3883
3884     CHECK_DEL_REG_STR(net, "1", temp);
3885
3886     RegDeleteKeyA(net, "");
3887     RegCloseKey(net);
3888
3889     res = RegOpenKeyA(sourcelist, "Media", &media);
3890     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3891
3892     CHECK_DEL_REG_STR(media, "1", "DISK1;");
3893
3894     RegDeleteKeyA(media, "");
3895     RegCloseKey(media);
3896     RegDeleteKeyA(sourcelist, "");
3897     RegCloseKey(sourcelist);
3898     RegDeleteKeyA(hkey, "");
3899     RegCloseKey(hkey);
3900
3901     res = RegOpenKeyA(HKEY_CLASSES_ROOT, machup, &hkey);
3902     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3903
3904     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
3905
3906     RegDeleteKeyA(hkey, "");
3907     RegCloseKey(hkey);
3908
3909     DeleteFile(msifile);
3910     DeleteFile("msitest\\maximus");
3911     RemoveDirectory("msitest");
3912     HeapFree(GetProcessHeap(), 0, usersid);
3913 }
3914
3915 static void test_publish_publishfeatures(void)
3916 {
3917     UINT r;
3918     LONG res;
3919     HKEY hkey;
3920     LPSTR usersid;
3921     CHAR keypath[MAX_PATH];
3922
3923     static const CHAR cupath[] = "Software\\Microsoft\\Installer\\Features"
3924                                  "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
3925     static const CHAR udpath[] = "Software\\Microsoft\\Windows\\CurrentVersion"
3926                                  "\\Installer\\UserData\\%s\\Products"
3927                                  "\\84A88FD7F6998CE40A22FB59F6B9C2BB\\Features";
3928     static const CHAR featkey[] = "Software\\Microsoft\\Windows\\CurrentVersion"
3929                                   "\\Installer\\Features";
3930     static const CHAR classfeat[] = "Software\\Classes\\Installer\\Features"
3931                                     "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
3932
3933     if (!get_user_sid(&usersid))
3934         return;
3935
3936     CreateDirectoryA("msitest", NULL);
3937     create_file("msitest\\maximus", 500);
3938
3939     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
3940
3941     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3942
3943     /* PublishFeatures, current user */
3944     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
3945     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3946     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3947     ok(delete_pf("msitest", FALSE), "File not installed\n");
3948
3949     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, featkey, &hkey);
3950     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3951
3952     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, classfeat, &hkey);
3953     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3954
3955     res = RegOpenKeyA(HKEY_CURRENT_USER, cupath, &hkey);
3956     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3957
3958     CHECK_REG_STR(hkey, "feature", "");
3959     CHECK_REG_STR(hkey, "montecristo", "");
3960
3961     RegDeleteValueA(hkey, "feature");
3962     RegDeleteValueA(hkey, "montecristo");
3963     RegDeleteKeyA(hkey, "");
3964     RegCloseKey(hkey);
3965
3966     sprintf(keypath, udpath, usersid);
3967     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
3968     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3969
3970     CHECK_REG_STR(hkey, "feature", "VGtfp^p+,?82@JU1j_KE");
3971     CHECK_REG_STR(hkey, "montecristo", "VGtfp^p+,?82@JU1j_KE");
3972
3973     RegDeleteValueA(hkey, "feature");
3974     RegDeleteValueA(hkey, "montecristo");
3975     RegDeleteKeyA(hkey, "");
3976     RegCloseKey(hkey);
3977
3978     /* PublishFeatures, machine */
3979     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1 ALLUSERS=1");
3980     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3981     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3982     ok(delete_pf("msitest", FALSE), "File not installed\n");
3983
3984     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, featkey, &hkey);
3985     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3986
3987     res = RegOpenKeyA(HKEY_CURRENT_USER, cupath, &hkey);
3988     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3989
3990     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, classfeat, &hkey);
3991     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3992
3993     CHECK_REG_STR(hkey, "feature", "");
3994     CHECK_REG_STR(hkey, "montecristo", "");
3995
3996     RegDeleteValueA(hkey, "feature");
3997     RegDeleteValueA(hkey, "montecristo");
3998     RegDeleteKeyA(hkey, "");
3999     RegCloseKey(hkey);
4000
4001     sprintf(keypath, udpath, "S-1-5-18");
4002     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
4003     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4004
4005     CHECK_REG_STR(hkey, "feature", "VGtfp^p+,?82@JU1j_KE");
4006     CHECK_REG_STR(hkey, "montecristo", "VGtfp^p+,?82@JU1j_KE");
4007
4008     RegDeleteValueA(hkey, "feature");
4009     RegDeleteValueA(hkey, "montecristo");
4010     RegDeleteKeyA(hkey, "");
4011     RegCloseKey(hkey);
4012
4013     DeleteFile(msifile);
4014     DeleteFile("msitest\\maximus");
4015     RemoveDirectory("msitest");
4016     HeapFree(GetProcessHeap(), 0, usersid);
4017 }
4018
4019 static LPSTR reg_get_val_str(HKEY hkey, LPCSTR name)
4020 {
4021     DWORD len = 0;
4022     LPSTR val;
4023     LONG r;
4024
4025     r = RegQueryValueExA(hkey, name, NULL, NULL, NULL, &len);
4026     if (r != ERROR_SUCCESS)
4027         return NULL;
4028
4029     len += sizeof (WCHAR);
4030     val = HeapAlloc(GetProcessHeap(), 0, len);
4031     if (!val) return NULL;
4032     val[0] = 0;
4033     RegQueryValueExA(hkey, name, NULL, NULL, (LPBYTE)val, &len);
4034     return val;
4035 }
4036
4037 static void get_owner_company(LPSTR *owner, LPSTR *company)
4038 {
4039     LONG res;
4040     HKEY hkey;
4041
4042     *owner = *company = NULL;
4043
4044     res = RegOpenKeyA(HKEY_CURRENT_USER,
4045                       "Software\\Microsoft\\MS Setup (ACME)\\User Info", &hkey);
4046     if (res == ERROR_SUCCESS)
4047     {
4048         *owner = reg_get_val_str(hkey, "DefName");
4049         *company = reg_get_val_str(hkey, "DefCompany");
4050         RegCloseKey(hkey);
4051     }
4052
4053     if (!*owner || !*company)
4054     {
4055         res = RegOpenKeyA(HKEY_LOCAL_MACHINE,
4056                           "Software\\Microsoft\\Windows\\CurrentVersion", &hkey);
4057         if (res == ERROR_SUCCESS)
4058         {
4059             *owner = reg_get_val_str(hkey, "RegisteredOwner");
4060             *company = reg_get_val_str(hkey, "RegisteredOrganization");
4061             RegCloseKey(hkey);
4062         }
4063     }
4064
4065     if (!*owner || !*company)
4066     {
4067         res = RegOpenKeyA(HKEY_LOCAL_MACHINE,
4068                           "Software\\Microsoft\\Windows NT\\CurrentVersion", &hkey);
4069         if (res == ERROR_SUCCESS)
4070         {
4071             *owner = reg_get_val_str(hkey, "RegisteredOwner");
4072             *company = reg_get_val_str(hkey, "RegisteredOrganization");
4073             RegCloseKey(hkey);
4074         }
4075     }
4076 }
4077
4078 static void test_publish_registeruser(void)
4079 {
4080     UINT r;
4081     LONG res;
4082     HKEY props;
4083     LPSTR usersid;
4084     LPSTR owner, company;
4085     CHAR keypath[MAX_PATH];
4086
4087     static const CHAR keyfmt[] =
4088         "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\"
4089         "UserData\\%s\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties";
4090
4091     if (!get_user_sid(&usersid))
4092         return;
4093
4094     get_owner_company(&owner, &company);
4095
4096     CreateDirectoryA("msitest", NULL);
4097     create_file("msitest\\maximus", 500);
4098
4099     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
4100
4101     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
4102
4103     /* RegisterUser, per-user */
4104     r = MsiInstallProductA(msifile, "REGISTER_USER=1");
4105     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4106     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4107     ok(delete_pf("msitest", FALSE), "File not installed\n");
4108
4109     sprintf(keypath, keyfmt, usersid);
4110
4111     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
4112     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4113
4114     CHECK_REG_STR(props, "ProductID", "none");
4115     CHECK_REG_STR(props, "RegCompany", company);
4116     CHECK_REG_STR(props, "RegOwner", owner);
4117
4118     RegDeleteValueA(props, "ProductID");
4119     RegDeleteValueA(props, "RegCompany");
4120     RegDeleteValueA(props, "RegOwner");
4121     RegDeleteKeyA(props, "");
4122     RegCloseKey(props);
4123
4124     /* RegisterUser, machine */
4125     r = MsiInstallProductA(msifile, "REGISTER_USER=1 ALLUSERS=1");
4126     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4127     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4128     ok(delete_pf("msitest", FALSE), "File not installed\n");
4129
4130     sprintf(keypath, keyfmt, "S-1-5-18");
4131
4132     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
4133     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4134
4135     CHECK_REG_STR(props, "ProductID", "none");
4136     CHECK_REG_STR(props, "RegCompany", company);
4137     CHECK_REG_STR(props, "RegOwner", owner);
4138
4139     RegDeleteValueA(props, "ProductID");
4140     RegDeleteValueA(props, "RegCompany");
4141     RegDeleteValueA(props, "RegOwner");
4142     RegDeleteKeyA(props, "");
4143     RegCloseKey(props);
4144
4145     HeapFree(GetProcessHeap(), 0, company);
4146     HeapFree(GetProcessHeap(), 0, owner);
4147
4148     DeleteFile(msifile);
4149     DeleteFile("msitest\\maximus");
4150     RemoveDirectory("msitest");
4151     LocalFree(usersid);
4152 }
4153
4154 static void test_publish_processcomponents(void)
4155 {
4156     UINT r;
4157     LONG res;
4158     DWORD size;
4159     HKEY comp, hkey;
4160     LPSTR usersid;
4161     CHAR val[MAX_PATH];
4162     CHAR keypath[MAX_PATH];
4163     CHAR program_files_maximus[MAX_PATH];
4164
4165     static const CHAR keyfmt[] =
4166         "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\"
4167         "UserData\\%s\\Components\\%s";
4168     static const CHAR compkey[] =
4169         "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Components";
4170
4171     if (!get_user_sid(&usersid))
4172         return;
4173
4174     CreateDirectoryA("msitest", NULL);
4175     create_file("msitest\\maximus", 500);
4176
4177     create_database(msifile, ppc_tables, sizeof(ppc_tables) / sizeof(msi_table));
4178
4179     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
4180
4181     /* ProcessComponents, per-user */
4182     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
4183     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4184     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4185     ok(delete_pf("msitest", FALSE), "File not installed\n");
4186
4187     sprintf(keypath, keyfmt, usersid, "CBABC2FDCCB35E749A8944D8C1C098B5");
4188
4189     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
4190     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4191
4192     size = MAX_PATH;
4193     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
4194                            NULL, NULL, (LPBYTE)val, &size);
4195     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4196
4197     lstrcpyA(program_files_maximus,PROG_FILES_DIR);
4198     lstrcatA(program_files_maximus,"\\msitest\\maximus");
4199
4200     ok(!lstrcmpiA(val, program_files_maximus),
4201        "Expected \"%s\", got \"%s\"\n", program_files_maximus, val);
4202
4203     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
4204     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
4205
4206     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
4207     RegDeleteKeyA(comp, "");
4208     RegCloseKey(comp);
4209
4210     sprintf(keypath, keyfmt, usersid, "241C3DA58FECD0945B9687D408766058");
4211
4212     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
4213     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4214
4215     size = MAX_PATH;
4216     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
4217                            NULL, NULL, (LPBYTE)val, &size);
4218     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4219     ok(!lstrcmpA(val, "01\\msitest\\augustus"),
4220        "Expected \"01\\msitest\\augustus\", got \"%s\"\n", val);
4221
4222     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
4223     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
4224
4225     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
4226     RegDeleteKeyA(comp, "");
4227     RegCloseKey(comp);
4228
4229     /* ProcessComponents, machine */
4230     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1 ALLUSERS=1");
4231     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4232     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4233     ok(delete_pf("msitest", FALSE), "File not installed\n");
4234
4235     sprintf(keypath, keyfmt, "S-1-5-18", "CBABC2FDCCB35E749A8944D8C1C098B5");
4236
4237     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
4238     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4239
4240     size = MAX_PATH;
4241     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
4242                            NULL, NULL, (LPBYTE)val, &size);
4243     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4244     ok(!lstrcmpiA(val, program_files_maximus),
4245        "Expected \"%s\", got \"%s\"\n", program_files_maximus, val);
4246
4247     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
4248     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
4249
4250     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
4251     RegDeleteKeyA(comp, "");
4252     RegCloseKey(comp);
4253
4254     sprintf(keypath, keyfmt, "S-1-5-18", "241C3DA58FECD0945B9687D408766058");
4255
4256     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
4257     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4258
4259     size = MAX_PATH;
4260     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
4261                            NULL, NULL, (LPBYTE)val, &size);
4262     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4263     ok(!lstrcmpA(val, "01\\msitest\\augustus"),
4264        "Expected \"01\\msitest\\augustus\", got \"%s\"\n", val);
4265
4266     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
4267     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
4268
4269     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
4270     RegDeleteKeyA(comp, "");
4271     RegCloseKey(comp);
4272
4273     DeleteFile(msifile);
4274     DeleteFile("msitest\\maximus");
4275     RemoveDirectory("msitest");
4276     LocalFree(usersid);
4277 }
4278
4279 static void test_publish(void)
4280 {
4281     UINT r;
4282     LONG res;
4283     HKEY uninstall, prodkey;
4284     INSTALLSTATE state;
4285     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
4286     char date[MAX_PATH];
4287     char temp[MAX_PATH];
4288
4289     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
4290
4291     if (!pMsiQueryComponentStateA)
4292     {
4293         win_skip("MsiQueryComponentStateA is not available\n");
4294         return;
4295     }
4296
4297     get_date_str(date);
4298     GetTempPath(MAX_PATH, temp);
4299
4300     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
4301     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4302
4303     CreateDirectoryA("msitest", NULL);
4304     create_file("msitest\\maximus", 500);
4305
4306     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
4307
4308     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
4309
4310     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4311     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4312
4313     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
4314     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4315
4316     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
4317     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4318
4319     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4320                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
4321     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4322     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4323
4324     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
4325     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
4326
4327     /* nothing published */
4328     r = MsiInstallProductA(msifile, NULL);
4329     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4330     ok(pf_exists("msitest\\maximus"), "File not installed\n");
4331     ok(pf_exists("msitest"), "File not installed\n");
4332
4333     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4334     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4335
4336     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
4337     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4338
4339     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
4340     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4341
4342     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4343                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
4344     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4345     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4346
4347     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
4348     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
4349
4350     /* PublishProduct and RegisterProduct */
4351     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1");
4352     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4353     ok(pf_exists("msitest\\maximus"), "File not installed\n");
4354     ok(pf_exists("msitest"), "File not installed\n");
4355
4356     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4357     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
4358
4359     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
4360     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4361
4362     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
4363     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4364
4365     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4366                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
4367     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
4368     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4369
4370     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
4371     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4372
4373     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
4374     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
4375     CHECK_REG_STR(prodkey, "InstallDate", date);
4376     CHECK_REG_STR(prodkey, "InstallSource", temp);
4377     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4378     CHECK_REG_STR(prodkey, "Publisher", "Wine");
4379     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4380     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
4381     CHECK_REG_STR(prodkey, "Comments", NULL);
4382     CHECK_REG_STR(prodkey, "Contact", NULL);
4383     CHECK_REG_STR(prodkey, "HelpLink", NULL);
4384     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
4385     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
4386     CHECK_REG_STR(prodkey, "Readme", NULL);
4387     CHECK_REG_STR(prodkey, "Size", NULL);
4388     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
4389     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
4390     CHECK_REG_DWORD(prodkey, "Language", 1033);
4391     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
4392     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
4393     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
4394     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
4395     todo_wine
4396     {
4397         CHECK_REG_DWORD2(prodkey, "EstimatedSize", 12, -12);
4398     }
4399
4400     RegCloseKey(prodkey);
4401
4402     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
4403     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4404     ok(pf_exists("msitest\\maximus"), "File deleted\n");
4405     ok(pf_exists("msitest"), "File deleted\n");
4406
4407     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4408     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4409
4410     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
4411     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4412
4413     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
4414     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4415
4416     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4417                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
4418     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4419     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4420
4421     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
4422     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
4423
4424     /* complete install */
4425     r = MsiInstallProductA(msifile, "FULL=1");
4426     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4427     ok(pf_exists("msitest\\maximus"), "File not installed\n");
4428     ok(pf_exists("msitest"), "File not installed\n");
4429
4430     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4431     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
4432
4433     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
4434     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
4435
4436     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
4437     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
4438
4439     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4440                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
4441     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4442     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
4443
4444     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
4445     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4446
4447     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
4448     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
4449     CHECK_REG_STR(prodkey, "InstallDate", date);
4450     CHECK_REG_STR(prodkey, "InstallSource", temp);
4451     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4452     CHECK_REG_STR(prodkey, "Publisher", "Wine");
4453     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4454     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
4455     CHECK_REG_STR(prodkey, "Comments", NULL);
4456     CHECK_REG_STR(prodkey, "Contact", NULL);
4457     CHECK_REG_STR(prodkey, "HelpLink", NULL);
4458     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
4459     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
4460     CHECK_REG_STR(prodkey, "Readme", NULL);
4461     CHECK_REG_STR(prodkey, "Size", NULL);
4462     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
4463     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
4464     CHECK_REG_DWORD(prodkey, "Language", 1033);
4465     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
4466     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
4467     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
4468     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
4469     todo_wine
4470     {
4471         CHECK_REG_DWORD2(prodkey, "EstimatedSize", 12, -12);
4472     }
4473
4474     RegCloseKey(prodkey);
4475
4476     /* no UnpublishFeatures */
4477     r = MsiInstallProductA(msifile, "REMOVE=ALL");
4478     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4479     ok(!pf_exists("msitest\\maximus"), "File deleted\n");
4480     todo_wine
4481     {
4482         ok(!pf_exists("msitest"), "File deleted\n");
4483     }
4484
4485     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4486     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4487
4488     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
4489     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4490
4491     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
4492     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4493
4494     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4495                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
4496     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4497     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4498
4499     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
4500     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
4501
4502     /* complete install */
4503     r = MsiInstallProductA(msifile, "FULL=1");
4504     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4505     ok(pf_exists("msitest\\maximus"), "File not installed\n");
4506     ok(pf_exists("msitest"), "File not installed\n");
4507
4508     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4509     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
4510
4511     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
4512     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
4513
4514     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
4515     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
4516
4517     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4518                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
4519     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4520     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
4521
4522     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
4523     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4524
4525     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
4526     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
4527     CHECK_REG_STR(prodkey, "InstallDate", date);
4528     CHECK_REG_STR(prodkey, "InstallSource", temp);
4529     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4530     CHECK_REG_STR(prodkey, "Publisher", "Wine");
4531     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4532     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
4533     CHECK_REG_STR(prodkey, "Comments", NULL);
4534     CHECK_REG_STR(prodkey, "Contact", NULL);
4535     CHECK_REG_STR(prodkey, "HelpLink", NULL);
4536     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
4537     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
4538     CHECK_REG_STR(prodkey, "Readme", NULL);
4539     CHECK_REG_STR(prodkey, "Size", NULL);
4540     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
4541     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
4542     CHECK_REG_DWORD(prodkey, "Language", 1033);
4543     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
4544     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
4545     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
4546     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
4547     todo_wine
4548     {
4549         CHECK_REG_DWORD2(prodkey, "EstimatedSize", 12, -12);
4550     }
4551
4552     RegCloseKey(prodkey);
4553
4554     /* UnpublishFeatures, only feature removed.  Only works when entire product is removed */
4555     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature");
4556     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4557     todo_wine ok(pf_exists("msitest\\maximus"), "File deleted\n");
4558     ok(pf_exists("msitest"), "File deleted\n");
4559
4560     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4561     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
4562
4563     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
4564     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
4565
4566     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
4567     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
4568
4569     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4570                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
4571     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4572     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
4573
4574     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
4575     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4576
4577     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
4578     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
4579     CHECK_REG_STR(prodkey, "InstallDate", date);
4580     CHECK_REG_STR(prodkey, "InstallSource", temp);
4581     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4582     CHECK_REG_STR(prodkey, "Publisher", "Wine");
4583     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4584     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
4585     CHECK_REG_STR(prodkey, "Comments", NULL);
4586     CHECK_REG_STR(prodkey, "Contact", NULL);
4587     CHECK_REG_STR(prodkey, "HelpLink", NULL);
4588     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
4589     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
4590     CHECK_REG_STR(prodkey, "Readme", NULL);
4591     CHECK_REG_STR(prodkey, "Size", NULL);
4592     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
4593     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
4594     CHECK_REG_DWORD(prodkey, "Language", 1033);
4595     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
4596     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
4597     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
4598     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
4599     todo_wine
4600     {
4601         CHECK_REG_DWORD2(prodkey, "EstimatedSize", 12, -12);
4602     }
4603
4604     RegCloseKey(prodkey);
4605
4606     /* complete install */
4607     r = MsiInstallProductA(msifile, "FULL=1");
4608     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4609     ok(pf_exists("msitest\\maximus"), "File not installed\n");
4610     ok(pf_exists("msitest"), "File not installed\n");
4611
4612     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4613     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
4614
4615     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
4616     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
4617
4618     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
4619     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
4620
4621     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4622                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
4623     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4624     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
4625
4626     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
4627     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4628
4629     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
4630     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
4631     CHECK_REG_STR(prodkey, "InstallDate", date);
4632     CHECK_REG_STR(prodkey, "InstallSource", temp);
4633     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4634     CHECK_REG_STR(prodkey, "Publisher", "Wine");
4635     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4636     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
4637     CHECK_REG_STR(prodkey, "Comments", NULL);
4638     CHECK_REG_STR(prodkey, "Contact", NULL);
4639     CHECK_REG_STR(prodkey, "HelpLink", NULL);
4640     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
4641     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
4642     CHECK_REG_STR(prodkey, "Readme", NULL);
4643     CHECK_REG_STR(prodkey, "Size", NULL);
4644     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
4645     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
4646     CHECK_REG_DWORD(prodkey, "Language", 1033);
4647     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
4648     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
4649     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
4650     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
4651     todo_wine
4652     {
4653         CHECK_REG_DWORD2(prodkey, "EstimatedSize", 12, -20);
4654     }
4655
4656     RegCloseKey(prodkey);
4657
4658     /* UnpublishFeatures, both features removed */
4659     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature,montecristo");
4660     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4661     ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
4662     todo_wine
4663     {
4664         ok(!pf_exists("msitest"), "File not deleted\n");
4665     }
4666
4667     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4668     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4669
4670     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
4671     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4672
4673     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
4674     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4675
4676     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4677                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
4678     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4679     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4680
4681     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
4682     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
4683
4684     /* complete install */
4685     r = MsiInstallProductA(msifile, "FULL=1");
4686     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4687     ok(pf_exists("msitest\\maximus"), "File not installed\n");
4688     ok(pf_exists("msitest"), "File not installed\n");
4689
4690     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4691     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
4692
4693     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
4694     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
4695
4696     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
4697     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
4698
4699     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4700                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
4701     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4702     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
4703
4704     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
4705     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4706
4707     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
4708     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
4709     CHECK_REG_STR(prodkey, "InstallDate", date);
4710     CHECK_REG_STR(prodkey, "InstallSource", temp);
4711     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4712     CHECK_REG_STR(prodkey, "Publisher", "Wine");
4713     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4714     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
4715     CHECK_REG_STR(prodkey, "Comments", NULL);
4716     CHECK_REG_STR(prodkey, "Contact", NULL);
4717     CHECK_REG_STR(prodkey, "HelpLink", NULL);
4718     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
4719     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
4720     CHECK_REG_STR(prodkey, "Readme", NULL);
4721     CHECK_REG_STR(prodkey, "Size", NULL);
4722     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
4723     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
4724     CHECK_REG_DWORD(prodkey, "Language", 1033);
4725     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
4726     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
4727     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
4728     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
4729     todo_wine
4730     {
4731         CHECK_REG_DWORD2(prodkey, "EstimatedSize", 12, -12);
4732     }
4733
4734     RegCloseKey(prodkey);
4735
4736     /* complete uninstall */
4737     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
4738     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4739     ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
4740     todo_wine
4741     {
4742         ok(!pf_exists("msitest"), "File not deleted\n");
4743     }
4744
4745     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
4746     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4747
4748     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
4749     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4750
4751     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
4752     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4753
4754     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4755                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
4756     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4757     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
4758
4759     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
4760     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
4761
4762     /* make sure 'Program Files\msitest' is removed */
4763     delete_pfmsitest_files();
4764
4765     RegCloseKey(uninstall);
4766     DeleteFile(msifile);
4767     DeleteFile("msitest\\maximus");
4768     RemoveDirectory("msitest");
4769 }
4770
4771 static void test_publishsourcelist(void)
4772 {
4773     UINT r;
4774     DWORD size;
4775     CHAR value[MAX_PATH];
4776     CHAR path[MAX_PATH];
4777     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
4778
4779     if (!pMsiSourceListEnumSourcesA || !pMsiSourceListGetInfoA)
4780     {
4781         win_skip("MsiSourceListEnumSourcesA and/or MsiSourceListGetInfoA are not available\n");
4782         return;
4783     }
4784
4785     CreateDirectoryA("msitest", NULL);
4786     create_file("msitest\\maximus", 500);
4787
4788     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
4789
4790     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
4791
4792     r = MsiInstallProductA(msifile, NULL);
4793     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4794     ok(pf_exists("msitest\\maximus"), "File not installed\n");
4795     ok(pf_exists("msitest"), "File not installed\n");
4796
4797     /* nothing published */
4798     size = MAX_PATH;
4799     lstrcpyA(value, "aaa");
4800     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4801                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
4802     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4803     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
4804     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
4805
4806     size = MAX_PATH;
4807     lstrcpyA(value, "aaa");
4808     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4809                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
4810     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4811     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
4812     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
4813
4814     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
4815     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4816     ok(pf_exists("msitest\\maximus"), "File not installed\n");
4817     ok(pf_exists("msitest"), "File not installed\n");
4818
4819     /* after RegisterProduct */
4820     size = MAX_PATH;
4821     lstrcpyA(value, "aaa");
4822     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4823                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
4824     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4825     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
4826     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
4827
4828     size = MAX_PATH;
4829     lstrcpyA(value, "aaa");
4830     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4831                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
4832     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4833     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
4834     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
4835
4836     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
4837     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4838     ok(pf_exists("msitest\\maximus"), "File not installed\n");
4839     ok(pf_exists("msitest"), "File not installed\n");
4840
4841     /* after ProcessComponents */
4842     size = MAX_PATH;
4843     lstrcpyA(value, "aaa");
4844     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4845                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
4846     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4847     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
4848     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
4849
4850     size = MAX_PATH;
4851     lstrcpyA(value, "aaa");
4852     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4853                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
4854     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4855     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
4856     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
4857
4858     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
4859     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4860     ok(pf_exists("msitest\\maximus"), "File not installed\n");
4861     ok(pf_exists("msitest"), "File not installed\n");
4862
4863     /* after PublishFeatures */
4864     size = MAX_PATH;
4865     lstrcpyA(value, "aaa");
4866     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4867                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
4868     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4869     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
4870     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
4871
4872     size = MAX_PATH;
4873     lstrcpyA(value, "aaa");
4874     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4875                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
4876     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
4877     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
4878     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
4879
4880     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
4881     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4882     ok(pf_exists("msitest\\maximus"), "File not installed\n");
4883     ok(pf_exists("msitest"), "File not installed\n");
4884
4885     /* after PublishProduct */
4886     size = MAX_PATH;
4887     lstrcpyA(value, "aaa");
4888     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4889                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
4890     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4891     ok(!lstrcmpA(value, "msitest.msi"), "Expected 'msitest.msi', got %s\n", value);
4892     ok(size == 11, "Expected 11, got %d\n", size);
4893
4894     size = MAX_PATH;
4895     lstrcpyA(value, "aaa");
4896     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4897                                MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATH, value, &size);
4898     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4899     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
4900     ok(size == 0, "Expected 0, got %d\n", size);
4901
4902     size = MAX_PATH;
4903     lstrcpyA(value, "aaa");
4904     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4905                                MSICODE_PRODUCT, INSTALLPROPERTY_DISKPROMPT, value, &size);
4906     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4907     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
4908     ok(size == 0, "Expected 0, got %d\n", size);
4909
4910     lstrcpyA(path, CURR_DIR);
4911     lstrcatA(path, "\\");
4912
4913     size = MAX_PATH;
4914     lstrcpyA(value, "aaa");
4915     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4916                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size);
4917     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4918     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
4919     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
4920
4921     size = MAX_PATH;
4922     lstrcpyA(value, "aaa");
4923     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4924                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE, value, &size);
4925     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4926     ok(!lstrcmpA(value, "n"), "Expected \"n\", got \"%s\"\n", value);
4927     ok(size == 1, "Expected 1, got %d\n", size);
4928
4929     size = MAX_PATH;
4930     lstrcpyA(value, "aaa");
4931     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4932                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
4933     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4934     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
4935     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
4936
4937     size = MAX_PATH;
4938     lstrcpyA(value, "aaa");
4939     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4940                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
4941     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4942     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
4943     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
4944
4945     size = MAX_PATH;
4946     lstrcpyA(value, "aaa");
4947     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
4948                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 1, value, &size);
4949     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4950     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
4951     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
4952
4953     /* complete uninstall */
4954     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
4955     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4956     ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
4957     todo_wine
4958     {
4959         ok(!pf_exists("msitest"), "File not deleted\n");
4960     }
4961
4962     /* make sure 'Program Files\msitest' is removed */
4963     delete_pfmsitest_files();
4964
4965     DeleteFile(msifile);
4966     DeleteFile("msitest\\maximus");
4967     RemoveDirectory("msitest");
4968 }
4969
4970 static UINT run_query(MSIHANDLE hdb, MSIHANDLE hrec, const char *query)
4971 {
4972     MSIHANDLE hview = 0;
4973     UINT r;
4974
4975     r = MsiDatabaseOpenView(hdb, query, &hview);
4976     if(r != ERROR_SUCCESS)
4977         return r;
4978
4979     r = MsiViewExecute(hview, hrec);
4980     if(r == ERROR_SUCCESS)
4981         r = MsiViewClose(hview);
4982     MsiCloseHandle(hview);
4983     return r;
4984 }
4985
4986 static void set_transform_summary_info(void)
4987 {
4988     UINT r;
4989     MSIHANDLE suminfo = 0;
4990
4991     /* build summary info */
4992     r = MsiGetSummaryInformation(0, mstfile, 3, &suminfo);
4993     ok(r == ERROR_SUCCESS , "Failed to open summaryinfo\n");
4994
4995     r = MsiSummaryInfoSetProperty(suminfo, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
4996     ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
4997
4998     r = MsiSummaryInfoSetProperty(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
4999                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
5000                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
5001                         "{4C0EAA15-0264-4E5A-8758-609EF142B92D}");
5002     ok(r == ERROR_SUCCESS , "Failed to set summary info\n");
5003
5004     r = MsiSummaryInfoSetProperty(suminfo, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
5005     ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
5006
5007     r = MsiSummaryInfoPersist(suminfo);
5008     ok(r == ERROR_SUCCESS , "Failed to make summary info persist\n");
5009
5010     r = MsiCloseHandle(suminfo);
5011     ok(r == ERROR_SUCCESS , "Failed to close suminfo\n");
5012 }
5013
5014 static void generate_transform(void)
5015 {
5016     MSIHANDLE hdb1, hdb2;
5017     LPCSTR query;
5018     UINT r;
5019
5020     /* start with two identical databases */
5021     CopyFile(msifile, msifile2, FALSE);
5022
5023     r = MsiOpenDatabase(msifile2, MSIDBOPEN_TRANSACT, &hdb1);
5024     ok(r == ERROR_SUCCESS , "Failed to create database\n");
5025
5026     r = MsiDatabaseCommit(hdb1);
5027     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
5028
5029     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb2);
5030     ok(r == ERROR_SUCCESS , "Failed to create database\n");
5031
5032     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
5033     r = run_query(hdb1, 0, query);
5034     ok(r == ERROR_SUCCESS, "failed to add property\n");
5035
5036     /* database needs to be committed */
5037     MsiDatabaseCommit(hdb1);
5038
5039     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
5040     ok(r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r);
5041
5042 #if 0  /* not implemented in wine yet */
5043     r = MsiCreateTransformSummaryInfo(hdb2, hdb2, mstfile, 0, 0);
5044     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5045 #endif
5046
5047     MsiCloseHandle(hdb1);
5048     MsiCloseHandle(hdb2);
5049 }
5050
5051 /* data for generating a transform */
5052
5053 /* tables transform names - encoded as they would be in an msi database file */
5054 static const WCHAR name1[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
5055 static const WCHAR name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
5056 static const WCHAR name3[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
5057
5058 /* data in each table */
5059 static const char data1[] = /* _StringData */
5060     "propval";  /* all the strings squashed together */
5061
5062 static const WCHAR data2[] = { /* _StringPool */
5063 /*  len, refs */
5064     0,   0,    /* string 0 ''     */
5065     4,   1,    /* string 1 'prop' */
5066     3,   1,    /* string 2 'val'  */
5067 };
5068
5069 static const WCHAR data3[] = { /* Property */
5070     0x0201, 0x0001, 0x0002,
5071 };
5072
5073 static const struct {
5074     LPCWSTR name;
5075     const void *data;
5076     DWORD size;
5077 } table_transform_data[] =
5078 {
5079     { name1, data1, sizeof data1 - 1 },
5080     { name2, data2, sizeof data2 },
5081     { name3, data3, sizeof data3 },
5082 };
5083
5084 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
5085
5086 static void generate_transform_manual(void)
5087 {
5088     IStorage *stg = NULL;
5089     IStream *stm;
5090     WCHAR name[0x20];
5091     HRESULT r;
5092     DWORD i, count;
5093     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
5094
5095     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
5096
5097     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
5098
5099     r = StgCreateDocfile(name, mode, 0, &stg);
5100     ok(r == S_OK, "failed to create storage\n");
5101     if (!stg)
5102         return;
5103
5104     r = IStorage_SetClass(stg, &CLSID_MsiTransform);
5105     ok(r == S_OK, "failed to set storage type\n");
5106
5107     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
5108     {
5109         r = IStorage_CreateStream(stg, table_transform_data[i].name,
5110                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
5111         if (FAILED(r))
5112         {
5113             ok(0, "failed to create stream %08x\n", r);
5114             continue;
5115         }
5116
5117         r = IStream_Write(stm, table_transform_data[i].data,
5118                           table_transform_data[i].size, &count);
5119         if (FAILED(r) || count != table_transform_data[i].size)
5120             ok(0, "failed to write stream\n");
5121         IStream_Release(stm);
5122     }
5123
5124     IStorage_Release(stg);
5125
5126     set_transform_summary_info();
5127 }
5128
5129 static void test_transformprop(void)
5130 {
5131     UINT r;
5132
5133     CreateDirectoryA("msitest", NULL);
5134     create_file("msitest\\augustus", 500);
5135
5136     create_database(msifile, tp_tables, sizeof(tp_tables) / sizeof(msi_table));
5137
5138     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5139
5140     r = MsiInstallProductA(msifile, NULL);
5141     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5142     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
5143     ok(!delete_pf("msitest", FALSE), "File installed\n");
5144
5145     if (0)
5146         generate_transform();
5147     else
5148         generate_transform_manual();
5149
5150     r = MsiInstallProductA(msifile, "TRANSFORMS=winetest.mst");
5151     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5152     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
5153     ok(delete_pf("msitest", FALSE), "File not installed\n");
5154
5155     /* Delete the files in the temp (current) folder */
5156     DeleteFile(msifile);
5157     DeleteFile(msifile2);
5158     DeleteFile(mstfile);
5159     DeleteFile("msitest\\augustus");
5160     RemoveDirectory("msitest");
5161 }
5162
5163 static void test_currentworkingdir(void)
5164 {
5165     UINT r;
5166     CHAR drive[MAX_PATH], path[MAX_PATH];
5167     LPSTR ptr;
5168
5169     CreateDirectoryA("msitest", NULL);
5170     create_file("msitest\\augustus", 500);
5171
5172     create_database(msifile, cwd_tables, sizeof(cwd_tables) / sizeof(msi_table));
5173
5174     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5175
5176     CreateDirectoryA("diffdir", NULL);
5177     SetCurrentDirectoryA("diffdir");
5178
5179     sprintf(path, "..\\%s", msifile);
5180     r = MsiInstallProductA(path, NULL);
5181     todo_wine
5182     {
5183         ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
5184         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
5185         ok(!delete_pf("msitest", FALSE), "File installed\n");
5186     }
5187
5188     sprintf(path, "%s\\%s", CURR_DIR, msifile);
5189     r = MsiInstallProductA(path, NULL);
5190     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5191     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
5192     ok(delete_pf("msitest", FALSE), "File not installed\n");
5193
5194     lstrcpyA(drive, CURR_DIR);
5195     drive[2] = '\\';
5196     drive[3] = '\0';
5197     SetCurrentDirectoryA(drive);
5198
5199     lstrcpy(path, CURR_DIR);
5200     if (path[lstrlenA(path) - 1] != '\\')
5201         lstrcatA(path, "\\");
5202     lstrcatA(path, msifile);
5203     ptr = strchr(path, ':');
5204     ptr +=2;
5205
5206     r = MsiInstallProductA(ptr, NULL);
5207     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5208     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
5209     ok(delete_pf("msitest", FALSE), "File not installed\n");
5210
5211     SetCurrentDirectoryA(CURR_DIR);
5212
5213     DeleteFile(msifile);
5214     DeleteFile("msitest\\augustus");
5215     RemoveDirectory("msitest");
5216     RemoveDirectory("diffdir");
5217 }
5218
5219 static void set_admin_summary_info(const CHAR *name)
5220 {
5221     MSIHANDLE db, summary;
5222     UINT r;
5223
5224     r = MsiOpenDatabaseA(name, MSIDBOPEN_DIRECT, &db);
5225     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5226
5227     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
5228     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5229
5230     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 5, NULL, NULL);
5231     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5232
5233     /* write the summary changes back to the stream */
5234     r = MsiSummaryInfoPersist(summary);
5235     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5236
5237     MsiCloseHandle(summary);
5238
5239     r = MsiDatabaseCommit(db);
5240     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5241
5242     MsiCloseHandle(db);
5243 }
5244
5245 static void test_admin(void)
5246 {
5247     UINT r;
5248
5249     CreateDirectoryA("msitest", NULL);
5250     create_file("msitest\\augustus", 500);
5251
5252     create_database(msifile, adm_tables, sizeof(adm_tables) / sizeof(msi_table));
5253     set_admin_summary_info(msifile);
5254
5255     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5256
5257     r = MsiInstallProductA(msifile, NULL);
5258     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5259     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
5260     ok(!delete_pf("msitest", FALSE), "File installed\n");
5261     ok(!DeleteFile("c:\\msitest\\augustus"), "File installed\n");
5262     ok(!RemoveDirectory("c:\\msitest"), "File installed\n");
5263
5264     r = MsiInstallProductA(msifile, "ACTION=ADMIN");
5265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5266     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
5267     ok(!delete_pf("msitest", FALSE), "File installed\n");
5268     todo_wine
5269     {
5270         ok(DeleteFile("c:\\msitest\\augustus"), "File not installed\n");
5271         ok(RemoveDirectory("c:\\msitest"), "File not installed\n");
5272     }
5273
5274     DeleteFile(msifile);
5275     DeleteFile("msitest\\augustus");
5276     RemoveDirectory("msitest");
5277 }
5278
5279 static void set_admin_property_stream(LPCSTR file)
5280 {
5281     IStorage *stg;
5282     IStream *stm;
5283     WCHAR fileW[MAX_PATH];
5284     HRESULT hr;
5285     DWORD count;
5286     const DWORD mode = STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
5287
5288     /* AdminProperties */
5289     static const WCHAR stmname[] = {0x41ca,0x4330,0x3e71,0x44b5,0x4233,0x45f5,0x422c,0x4836,0};
5290     static const WCHAR data[] = {'M','Y','P','R','O','P','=','2','7','1','8',' ',
5291         'M','y','P','r','o','p','=','4','2',0};
5292
5293     MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH);
5294
5295     hr = StgOpenStorage(fileW, NULL, mode, NULL, 0, &stg);
5296     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5297     if (!stg)
5298         return;
5299
5300     hr = IStorage_CreateStream(stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
5301     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5302
5303     hr = IStream_Write(stm, data, sizeof(data), &count);
5304     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
5305
5306     IStream_Release(stm);
5307     IStorage_Release(stg);
5308 }
5309
5310 static void test_adminprops(void)
5311 {
5312     UINT r;
5313
5314     CreateDirectoryA("msitest", NULL);
5315     create_file("msitest\\augustus", 500);
5316
5317     create_database(msifile, amp_tables, sizeof(amp_tables) / sizeof(msi_table));
5318     set_admin_summary_info(msifile);
5319     set_admin_property_stream(msifile);
5320
5321     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5322
5323     r = MsiInstallProductA(msifile, NULL);
5324     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5325     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
5326     ok(delete_pf("msitest", FALSE), "File installed\n");
5327
5328     DeleteFile(msifile);
5329     DeleteFile("msitest\\augustus");
5330     RemoveDirectory("msitest");
5331 }
5332
5333 static void create_pf_data(LPCSTR file, LPCSTR data, BOOL is_file)
5334 {
5335     CHAR path[MAX_PATH];
5336
5337     lstrcpyA(path, PROG_FILES_DIR);
5338     lstrcatA(path, "\\");
5339     lstrcatA(path, file);
5340
5341     if (is_file)
5342         create_file_data(path, data, 500);
5343     else
5344         CreateDirectoryA(path, NULL);
5345 }
5346
5347 #define create_pf(file, is_file) create_pf_data(file, file, is_file)
5348
5349 static void test_removefiles(void)
5350 {
5351     UINT r;
5352
5353     CreateDirectoryA("msitest", NULL);
5354     create_file("msitest\\hydrogen", 500);
5355     create_file("msitest\\helium", 500);
5356     create_file("msitest\\lithium", 500);
5357
5358     create_database(msifile, rem_tables, sizeof(rem_tables) / sizeof(msi_table));
5359
5360     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
5361
5362     r = MsiInstallProductA(msifile, NULL);
5363     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5364     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5365     ok(!pf_exists("msitest\\helium"), "File installed\n");
5366     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5367     ok(pf_exists("msitest"), "File not installed\n");
5368
5369     r = MsiInstallProductA(msifile, "REMOVE=ALL");
5370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5371     ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
5372     ok(!pf_exists("msitest\\helium"), "File not deleted\n");
5373     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
5374     ok(delete_pf("msitest", FALSE), "File deleted\n");
5375
5376     create_pf("msitest", FALSE);
5377     create_pf("msitest\\hydrogen", TRUE);
5378     create_pf("msitest\\helium", TRUE);
5379     create_pf("msitest\\lithium", TRUE);
5380
5381     r = MsiInstallProductA(msifile, NULL);
5382     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5383     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5384     ok(pf_exists("msitest\\helium"), "File not installed\n");
5385     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5386     ok(pf_exists("msitest"), "File not installed\n");
5387
5388     r = MsiInstallProductA(msifile, "REMOVE=ALL");
5389     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5390     ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
5391     ok(delete_pf("msitest\\helium", TRUE), "File deleted\n");
5392     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
5393     ok(delete_pf("msitest", FALSE), "File deleted\n");
5394
5395     create_pf("msitest", FALSE);
5396     create_pf("msitest\\furlong", TRUE);
5397     create_pf("msitest\\firkin", TRUE);
5398     create_pf("msitest\\fortnight", TRUE);
5399     create_pf("msitest\\becquerel", TRUE);
5400     create_pf("msitest\\dioptre", TRUE);
5401     create_pf("msitest\\attoparsec", TRUE);
5402     create_pf("msitest\\storeys", TRUE);
5403     create_pf("msitest\\block", TRUE);
5404     create_pf("msitest\\siriometer", TRUE);
5405     create_pf("msitest\\cabout", FALSE);
5406     create_pf("msitest\\cabout\\blocker", TRUE);
5407
5408     r = MsiInstallProductA(msifile, NULL);
5409     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5410     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5411     ok(!pf_exists("msitest\\helium"), "File installed\n");
5412     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5413     ok(!pf_exists("msitest\\furlong"), "File not deleted\n");
5414     ok(!pf_exists("msitest\\firkin"), "File not deleted\n");
5415     ok(!pf_exists("msitest\\fortnight"), "File not deleted\n");
5416     ok(pf_exists("msitest\\becquerel"), "File not installed\n");
5417     ok(pf_exists("msitest\\dioptre"), "File not installed\n");
5418     ok(pf_exists("msitest\\attoparsec"), "File not installed\n");
5419     ok(!pf_exists("msitest\\storeys"), "File not deleted\n");
5420     ok(!pf_exists("msitest\\block"), "File not deleted\n");
5421     ok(!pf_exists("msitest\\siriometer"), "File not deleted\n");
5422     ok(pf_exists("msitest\\cabout"), "Directory removed\n");
5423     ok(pf_exists("msitest"), "File not installed\n");
5424
5425     create_pf("msitest\\furlong", TRUE);
5426     create_pf("msitest\\firkin", TRUE);
5427     create_pf("msitest\\fortnight", TRUE);
5428     create_pf("msitest\\storeys", TRUE);
5429     create_pf("msitest\\block", TRUE);
5430     create_pf("msitest\\siriometer", TRUE);
5431
5432     r = MsiInstallProductA(msifile, "REMOVE=ALL");
5433     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5434     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not deleted\n");
5435     ok(!delete_pf("msitest\\helium", TRUE), "File not deleted\n");
5436     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
5437     ok(delete_pf("msitest\\furlong", TRUE), "File deleted\n");
5438     ok(delete_pf("msitest\\firkin", TRUE), "File deleted\n");
5439     ok(delete_pf("msitest\\fortnight", TRUE), "File deleted\n");
5440     ok(!delete_pf("msitest\\becquerel", TRUE), "File not deleted\n");
5441     ok(!delete_pf("msitest\\dioptre", TRUE), "File not deleted\n");
5442     ok(delete_pf("msitest\\attoparsec", TRUE), "File deleted\n");
5443     ok(!delete_pf("msitest\\storeys", TRUE), "File not deleted\n");
5444     ok(!delete_pf("msitest\\block", TRUE), "File not deleted\n");
5445     ok(delete_pf("msitest\\siriometer", TRUE), "File deleted\n");
5446     ok(pf_exists("msitest\\cabout"), "Directory deleted\n");
5447     ok(pf_exists("msitest"), "Directory deleted\n");
5448
5449     r = MsiInstallProductA(msifile, NULL);
5450     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5451     ok(delete_pf("msitest\\hydrogen", TRUE), "File not installed\n");
5452     ok(!delete_pf("msitest\\helium", TRUE), "File installed\n");
5453     ok(delete_pf("msitest\\lithium", TRUE), "File not installed\n");
5454     ok(pf_exists("msitest\\cabout"), "Directory deleted\n");
5455     ok(pf_exists("msitest"), "Directory deleted\n");
5456
5457     delete_pf("msitest\\cabout\\blocker", TRUE);
5458
5459     r = MsiInstallProductA(msifile, "REMOVE=ALL");
5460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5461     ok(!delete_pf("msitest\\cabout", FALSE), "Directory not deleted\n");
5462     ok(delete_pf("msitest", FALSE), "Directory deleted\n");
5463
5464     DeleteFile(msifile);
5465     DeleteFile("msitest\\hydrogen");
5466     DeleteFile("msitest\\helium");
5467     DeleteFile("msitest\\lithium");
5468     RemoveDirectory("msitest");
5469 }
5470
5471 static void test_movefiles(void)
5472 {
5473     UINT r;
5474     char props[MAX_PATH];
5475
5476     CreateDirectoryA("msitest", NULL);
5477     create_file("msitest\\augustus", 100);
5478     create_file("cameroon", 100);
5479     create_file("djibouti", 100);
5480     create_file("egypt", 100);
5481     create_file("finland", 100);
5482     create_file("gambai", 100);
5483     create_file("honduras", 100);
5484     create_file("msitest\\india", 100);
5485     create_file("japan", 100);
5486     create_file("kenya", 100);
5487     CreateDirectoryA("latvia", NULL);
5488     create_file("nauru", 100);
5489     create_file("peru", 100);
5490     create_file("apple", 100);
5491     create_file("application", 100);
5492     create_file("ape", 100);
5493     create_file("foo", 100);
5494     create_file("fao", 100);
5495     create_file("fbod", 100);
5496     create_file("budding", 100);
5497     create_file("buddy", 100);
5498     create_file("bud", 100);
5499     create_file("bar", 100);
5500     create_file("bur", 100);
5501     create_file("bird", 100);
5502
5503     create_database(msifile, mov_tables, sizeof(mov_tables) / sizeof(msi_table));
5504
5505     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
5506
5507     /* if the source or dest property is not a full path,
5508      * windows tries to access it as a network resource
5509      */
5510
5511     sprintf(props, "SOURCEFULL=\"%s\\\" DESTFULL=\"%s\\msitest\" "
5512             "FILEPATHBAD=\"%s\\japan\" FILEPATHGOOD=\"%s\\kenya\"",
5513             CURR_DIR, PROG_FILES_DIR, CURR_DIR, CURR_DIR);
5514
5515     r = MsiInstallProductA(msifile, props);
5516     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5517     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
5518     ok(!delete_pf("msitest\\dest", TRUE), "File copied\n");
5519     ok(delete_pf("msitest\\canada", TRUE), "File not copied\n");
5520     ok(delete_pf("msitest\\dominica", TRUE), "File not moved\n");
5521     ok(!delete_pf("msitest\\elsalvador", TRUE), "File moved\n");
5522     ok(!delete_pf("msitest\\france", TRUE), "File moved\n");
5523     ok(!delete_pf("msitest\\georgia", TRUE), "File moved\n");
5524     ok(delete_pf("msitest\\hungary", TRUE), "File not moved\n");
5525     ok(!delete_pf("msitest\\indonesia", TRUE), "File moved\n");
5526     ok(!delete_pf("msitest\\jordan", TRUE), "File moved\n");
5527     ok(delete_pf("msitest\\kiribati", TRUE), "File not moved\n");
5528     ok(!delete_pf("msitest\\lebanon", TRUE), "File moved\n");
5529     ok(!delete_pf("msitest\\lebanon", FALSE), "Directory moved\n");
5530     ok(delete_pf("msitest\\poland", TRUE), "File not moved\n");
5531     /* either apple or application will be moved depending on directory order */
5532     if (!delete_pf("msitest\\apple", TRUE))
5533         ok(delete_pf("msitest\\application", TRUE), "File not moved\n");
5534     else
5535         ok(!delete_pf("msitest\\application", TRUE), "File should not exist\n");
5536     ok(delete_pf("msitest\\wildcard", TRUE), "File not moved\n");
5537     ok(!delete_pf("msitest\\ape", TRUE), "File moved\n");
5538     /* either fao or foo will be moved depending on directory order */
5539     if (delete_pf("msitest\\foo", TRUE))
5540         ok(!delete_pf("msitest\\fao", TRUE), "File should not exist\n");
5541     else
5542         ok(delete_pf("msitest\\fao", TRUE), "File not moved\n");
5543     ok(delete_pf("msitest\\single", TRUE), "File not moved\n");
5544     ok(!delete_pf("msitest\\fbod", TRUE), "File moved\n");
5545     ok(delete_pf("msitest\\budding", TRUE), "File not moved\n");
5546     ok(delete_pf("msitest\\buddy", TRUE), "File not moved\n");
5547     ok(!delete_pf("msitest\\bud", TRUE), "File moved\n");
5548     ok(delete_pf("msitest\\bar", TRUE), "File not moved\n");
5549     ok(delete_pf("msitest\\bur", TRUE), "File not moved\n");
5550     ok(!delete_pf("msitest\\bird", TRUE), "File moved\n");
5551     ok(delete_pf("msitest", FALSE), "File not installed\n");
5552     ok(DeleteFileA("cameroon"), "File moved\n");
5553     ok(!DeleteFileA("djibouti"), "File not moved\n");
5554     ok(DeleteFileA("egypt"), "File moved\n");
5555     ok(DeleteFileA("finland"), "File moved\n");
5556     ok(DeleteFileA("gambai"), "File moved\n");
5557     ok(!DeleteFileA("honduras"), "File not moved\n");
5558     ok(DeleteFileA("msitest\\india"), "File moved\n");
5559     ok(DeleteFileA("japan"), "File moved\n");
5560     ok(!DeleteFileA("kenya"), "File not moved\n");
5561     ok(RemoveDirectoryA("latvia"), "Directory moved\n");
5562     ok(!DeleteFileA("nauru"), "File not moved\n");
5563     ok(!DeleteFileA("peru"), "File not moved\n");
5564     ok(!DeleteFileA("apple"), "File not moved\n");
5565     ok(!DeleteFileA("application"), "File not moved\n");
5566     ok(DeleteFileA("ape"), "File moved\n");
5567     ok(!DeleteFileA("foo"), "File not moved\n");
5568     ok(!DeleteFileA("fao"), "File not moved\n");
5569     ok(DeleteFileA("fbod"), "File moved\n");
5570     ok(!DeleteFileA("budding"), "File not moved\n");
5571     ok(!DeleteFileA("buddy"), "File not moved\n");
5572     ok(DeleteFileA("bud"), "File moved\n");
5573     ok(!DeleteFileA("bar"), "File not moved\n");
5574     ok(!DeleteFileA("bur"), "File not moved\n");
5575     ok(DeleteFileA("bird"), "File moved\n");
5576
5577     DeleteFile("msitest\\augustus");
5578     RemoveDirectory("msitest");
5579     DeleteFile(msifile);
5580 }
5581
5582 static void test_missingcab(void)
5583 {
5584     UINT r;
5585
5586     CreateDirectoryA("msitest", NULL);
5587     create_file("msitest\\augustus", 500);
5588     create_file("maximus", 500);
5589
5590     create_database(msifile, mc_tables, sizeof(mc_tables) / sizeof(msi_table));
5591
5592     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5593
5594     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
5595
5596     create_pf("msitest", FALSE);
5597     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
5598
5599     r = MsiInstallProductA(msifile, NULL);
5600     ok(r == ERROR_SUCCESS ||
5601        broken(r == ERROR_INSTALL_FAILURE), /* win9x */
5602        "Expected ERROR_SUCCESS, got %u\n", r);
5603     if (r == ERROR_SUCCESS)
5604     {
5605       ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
5606       ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
5607     }
5608     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
5609     ok(!delete_pf("msitest\\gaius", TRUE), "File installed\n");
5610     ok(delete_pf("msitest", FALSE), "File not installed\n");
5611
5612     create_pf("msitest", FALSE);
5613     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
5614     create_pf("msitest\\gaius", TRUE);
5615
5616     r = MsiInstallProductA(msifile, "GAIUS=1");
5617     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
5618     todo_wine
5619     {
5620         ok(!delete_pf("msitest\\maximus", TRUE), "File installed\n");
5621         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
5622     }
5623     ok(delete_pf("msitest\\caesar", TRUE), "File removed\n");
5624     ok(delete_pf("msitest\\gaius", TRUE), "File removed\n");
5625     ok(delete_pf("msitest", FALSE), "File not installed\n");
5626
5627     DeleteFile("msitest\\augustus");
5628     RemoveDirectory("msitest");
5629     DeleteFile("maximus");
5630     DeleteFile("test1.cab");
5631     DeleteFile(msifile);
5632 }
5633
5634 static void test_duplicatefiles(void)
5635 {
5636     UINT r;
5637
5638     CreateDirectoryA("msitest", NULL);
5639     create_file("msitest\\maximus", 500);
5640     create_database(msifile, df_tables, sizeof(df_tables) / sizeof(msi_table));
5641
5642     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5643
5644     /* fails if the destination folder is not a valid property */
5645
5646     r = MsiInstallProductA(msifile, NULL);
5647     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5648     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
5649     ok(delete_pf("msitest\\augustus", TRUE), "File not duplicated\n");
5650     ok(delete_pf("msitest\\this\\doesnot\\exist\\maximus", TRUE), "File not duplicated\n");
5651     ok(delete_pf("msitest\\this\\doesnot\\exist", FALSE), "File not duplicated\n");
5652     ok(delete_pf("msitest\\this\\doesnot", FALSE), "File not duplicated\n");
5653     ok(delete_pf("msitest\\this", FALSE), "File not duplicated\n");
5654     ok(delete_pf("msitest", FALSE), "File not installed\n");
5655
5656     DeleteFile("msitest\\maximus");
5657     RemoveDirectory("msitest");
5658     DeleteFile(msifile);
5659 }
5660
5661 static void test_writeregistryvalues(void)
5662 {
5663     UINT r;
5664     LONG res;
5665     HKEY hkey;
5666     DWORD type, size;
5667     CHAR path[MAX_PATH];
5668
5669     CreateDirectoryA("msitest", NULL);
5670     create_file("msitest\\augustus", 500);
5671
5672     create_database(msifile, wrv_tables, sizeof(wrv_tables) / sizeof(msi_table));
5673
5674     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5675
5676     r = MsiInstallProductA(msifile, NULL);
5677     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5678     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
5679     ok(delete_pf("msitest", FALSE), "File installed\n");
5680
5681     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
5682     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5683
5684     size = MAX_PATH;
5685     type = REG_MULTI_SZ;
5686     memset(path, 'a', MAX_PATH);
5687     res = RegQueryValueExA(hkey, "Value", NULL, &type, (LPBYTE)path, &size);
5688     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5689     ok(!memcmp(path, "one\0two\0three\0\0", size), "Wrong multi-sz data\n");
5690     ok(size == 15, "Expected 15, got %d\n", size);
5691     ok(type == REG_MULTI_SZ, "Expected REG_MULTI_SZ, got %d\n", type);
5692
5693     DeleteFile(msifile);
5694     DeleteFile("msitest\\augustus");
5695     RemoveDirectory("msitest");
5696
5697     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
5698     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine");
5699 }
5700
5701 static void test_sourcefolder(void)
5702 {
5703     UINT r;
5704
5705     CreateDirectoryA("msitest", NULL);
5706     create_file("augustus", 500);
5707
5708     create_database(msifile, sf_tables, sizeof(sf_tables) / sizeof(msi_table));
5709
5710     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5711
5712     r = MsiInstallProductA(msifile, NULL);
5713     ok(r == ERROR_INSTALL_FAILURE,
5714        "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
5715     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
5716     todo_wine
5717     {
5718         ok(!delete_pf("msitest", FALSE), "File installed\n");
5719     }
5720
5721     RemoveDirectoryA("msitest");
5722
5723     r = MsiInstallProductA(msifile, NULL);
5724     ok(r == ERROR_INSTALL_FAILURE,
5725        "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
5726     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
5727     todo_wine
5728     {
5729         ok(!delete_pf("msitest", FALSE), "File installed\n");
5730     }
5731
5732     DeleteFile(msifile);
5733     DeleteFile("augustus");
5734 }
5735
5736 static void test_customaction51(void)
5737 {
5738     UINT r;
5739
5740     CreateDirectoryA("msitest", NULL);
5741     create_file("msitest\\augustus", 500);
5742
5743     create_database(msifile, ca51_tables, sizeof(ca51_tables) / sizeof(msi_table));
5744
5745     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5746
5747     r = MsiInstallProductA(msifile, NULL);
5748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5749     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
5750     ok(delete_pf("msitest", FALSE), "File installed\n");
5751
5752     DeleteFile(msifile);
5753     DeleteFile("msitest\\augustus");
5754     RemoveDirectory("msitest");
5755 }
5756
5757 static void test_installstate(void)
5758 {
5759     UINT r;
5760
5761     CreateDirectoryA("msitest", NULL);
5762     create_file("msitest\\alpha", 500);
5763     create_file("msitest\\beta", 500);
5764     create_file("msitest\\gamma", 500);
5765     create_file("msitest\\theta", 500);
5766     create_file("msitest\\delta", 500);
5767     create_file("msitest\\epsilon", 500);
5768     create_file("msitest\\zeta", 500);
5769     create_file("msitest\\iota", 500);
5770     create_file("msitest\\eta", 500);
5771     create_file("msitest\\kappa", 500);
5772     create_file("msitest\\lambda", 500);
5773     create_file("msitest\\mu", 500);
5774
5775     create_database(msifile, is_tables, sizeof(is_tables) / sizeof(msi_table));
5776
5777     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5778
5779     r = MsiInstallProductA(msifile, NULL);
5780     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5781     ok(delete_pf("msitest\\alpha", TRUE), "File not installed\n");
5782     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
5783     ok(delete_pf("msitest\\gamma", TRUE), "File not installed\n");
5784     ok(delete_pf("msitest\\theta", TRUE), "File not installed\n");
5785     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
5786     ok(!delete_pf("msitest\\epsilon", TRUE), "File installed\n");
5787     ok(!delete_pf("msitest\\zeta", TRUE), "File installed\n");
5788     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
5789     ok(!delete_pf("msitest\\eta", TRUE), "File installed\n");
5790     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
5791     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
5792     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
5793     ok(delete_pf("msitest", FALSE), "File not installed\n");
5794
5795     r = MsiInstallProductA(msifile, "ADDLOCAL=\"one,two,three,four\"");
5796     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5797     ok(delete_pf("msitest\\alpha", TRUE), "File not installed\n");
5798     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
5799     ok(delete_pf("msitest\\gamma", TRUE), "File not installed\n");
5800     ok(delete_pf("msitest\\theta", TRUE), "File not installed\n");
5801     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
5802     ok(delete_pf("msitest\\epsilon", TRUE), "File not installed\n");
5803     ok(delete_pf("msitest\\zeta", TRUE), "File not installed\n");
5804     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
5805     ok(delete_pf("msitest\\eta", TRUE), "File not installed\n");
5806     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
5807     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
5808     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
5809     ok(delete_pf("msitest", FALSE), "File not installed\n");
5810
5811     r = MsiInstallProductA(msifile, "ADDSOURCE=\"one,two,three,four\"");
5812     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5813     ok(delete_pf("msitest\\alpha", TRUE), "File not installed\n");
5814     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
5815     ok(!delete_pf("msitest\\gamma", TRUE), "File installed\n");
5816     ok(delete_pf("msitest\\theta", TRUE), "File not installed\n");
5817     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
5818     ok(!delete_pf("msitest\\epsilon", TRUE), "File installed\n");
5819     ok(delete_pf("msitest\\zeta", TRUE), "File not installed\n");
5820     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
5821     ok(!delete_pf("msitest\\eta", TRUE), "File installed\n");
5822     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
5823     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
5824     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
5825     ok(delete_pf("msitest", FALSE), "File not installed\n");
5826
5827     r = MsiInstallProductA(msifile, "REMOVE=\"one,two,three,four\"");
5828     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5829     ok(!delete_pf("msitest\\alpha", TRUE), "File installed\n");
5830     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
5831     ok(!delete_pf("msitest\\gamma", TRUE), "File installed\n");
5832     ok(!delete_pf("msitest\\theta", TRUE), "File installed\n");
5833     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
5834     ok(!delete_pf("msitest\\epsilon", TRUE), "File installed\n");
5835     ok(!delete_pf("msitest\\zeta", TRUE), "File installed\n");
5836     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
5837     ok(!delete_pf("msitest\\eta", TRUE), "File installed\n");
5838     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
5839     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
5840     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
5841     ok(!delete_pf("msitest", FALSE), "File installed\n");
5842
5843     DeleteFile(msifile);
5844     DeleteFile("msitest\\alpha");
5845     DeleteFile("msitest\\beta");
5846     DeleteFile("msitest\\gamma");
5847     DeleteFile("msitest\\theta");
5848     DeleteFile("msitest\\delta");
5849     DeleteFile("msitest\\epsilon");
5850     DeleteFile("msitest\\zeta");
5851     DeleteFile("msitest\\iota");
5852     DeleteFile("msitest\\eta");
5853     DeleteFile("msitest\\kappa");
5854     DeleteFile("msitest\\lambda");
5855     DeleteFile("msitest\\mu");
5856     RemoveDirectory("msitest");
5857 }
5858
5859 struct sourcepathmap
5860 {
5861     BOOL sost; /* shortone\shorttwo */
5862     BOOL solt; /* shortone\longtwo */
5863     BOOL lost; /* longone\shorttwo */
5864     BOOL lolt; /* longone\longtwo */
5865     BOOL soste; /* shortone\shorttwo source exists */
5866     BOOL solte; /* shortone\longtwo source exists */
5867     BOOL loste; /* longone\shorttwo source exists */
5868     BOOL lolte; /* longone\longtwo source exists */
5869     UINT err;
5870     DWORD size;
5871 } spmap[256] =
5872 {
5873     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5874     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5875     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5876     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5877     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5878     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5879     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5880     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5881     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5882     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5883     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5884     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5885     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5886     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5887     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5888     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5889     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5890     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5891     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5892     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5893     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5894     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5895     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5896     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5897     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5898     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5899     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5900     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5901     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5902     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5903     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5904     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5905     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5906     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5907     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5908     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5909     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5910     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5911     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5912     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5913     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5914     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5915     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5916     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5917     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5918     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5919     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5920     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5921     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5922     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5923     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5924     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5925     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5926     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5927     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5928     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5929     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5930     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5931     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5932     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5933     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5934     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5935     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5936     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5937     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5938     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5939     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5940     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5941     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5942     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5943     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5944     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5945     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5946     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5947     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5948     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5949     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5950     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5951     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5952     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5953     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5954     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5955     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5956     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5957     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5958     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5959     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5960     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5961     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5962     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5963     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5964     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5965     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5966     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5967     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5968     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5969     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5970     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5971     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5972     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5973     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5974     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5975     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5976     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5977     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5978     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5979     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5980     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5981     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5982     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5983     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5984     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5985     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5986     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5987     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5988     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5989     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5990     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5991     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5992     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5993     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5994     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5995     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5996     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5997     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5998     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5999     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6000     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6001     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
6002     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6003     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
6004     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6005     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
6006     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6007     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
6008     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6009     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
6010     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6011     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
6012     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6013     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
6014     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6015     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
6016     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6017     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6018     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6019     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6020     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6021     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6022     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6023     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6024     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6025     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6026     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6027     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6028     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6029     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6030     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6031     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6032     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6033     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
6034     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6035     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
6036     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6037     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
6038     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6039     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
6040     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6041     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
6042     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6043     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
6044     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6045     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
6046     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6047     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
6048     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6049     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6050     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6051     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6052     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6053     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6054     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6055     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6056     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6057     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6058     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6059     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6060     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6061     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6062     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6063     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6064     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6065     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
6066     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6067     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
6068     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6069     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
6070     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6071     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
6072     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6073     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
6074     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6075     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
6076     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6077     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
6078     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6079     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
6080     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6081     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6082     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6083     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6084     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6085     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6086     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6087     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6088     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6089     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6090     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6091     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6092     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6093     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6094     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6095     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6096     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6097     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
6098     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6099     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
6100     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6101     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
6102     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6103     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
6104     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6105     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
6106     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6107     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
6108     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6109     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
6110     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6111     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
6112     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6113     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6114     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6115     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6116     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6117     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6118     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6119     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6120     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6121     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6122     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6123     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6124     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6125     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
6126     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
6127     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
6128     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
6129 };
6130
6131 static DWORD get_pf_file_size(LPCSTR file)
6132 {
6133     CHAR path[MAX_PATH];
6134     HANDLE hfile;
6135     DWORD size;
6136
6137     lstrcpyA(path, PROG_FILES_DIR);
6138     lstrcatA(path, "\\");
6139     lstrcatA(path, file);
6140
6141     hfile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
6142     if (hfile == INVALID_HANDLE_VALUE)
6143         return 0;
6144
6145     size = GetFileSize(hfile, NULL);
6146     CloseHandle(hfile);
6147     return size;
6148 }
6149
6150 static void test_sourcepath(void)
6151 {
6152     UINT r, i;
6153
6154     if (!winetest_interactive)
6155     {
6156         skip("Run in interactive mode to run source path tests.\n");
6157         return;
6158     }
6159
6160     create_database(msifile, sp_tables, sizeof(sp_tables) / sizeof(msi_table));
6161
6162     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6163
6164     for (i = 0; i < sizeof(spmap) / sizeof(spmap[0]); i++)
6165     {
6166         if (spmap[i].sost)
6167         {
6168             CreateDirectoryA("shortone", NULL);
6169             CreateDirectoryA("shortone\\shorttwo", NULL);
6170         }
6171
6172         if (spmap[i].solt)
6173         {
6174             CreateDirectoryA("shortone", NULL);
6175             CreateDirectoryA("shortone\\longtwo", NULL);
6176         }
6177
6178         if (spmap[i].lost)
6179         {
6180             CreateDirectoryA("longone", NULL);
6181             CreateDirectoryA("longone\\shorttwo", NULL);
6182         }
6183
6184         if (spmap[i].lolt)
6185         {
6186             CreateDirectoryA("longone", NULL);
6187             CreateDirectoryA("longone\\longtwo", NULL);
6188         }
6189
6190         if (spmap[i].soste)
6191             create_file("shortone\\shorttwo\\augustus", 50);
6192         if (spmap[i].solte)
6193             create_file("shortone\\longtwo\\augustus", 100);
6194         if (spmap[i].loste)
6195             create_file("longone\\shorttwo\\augustus", 150);
6196         if (spmap[i].lolte)
6197             create_file("longone\\longtwo\\augustus", 200);
6198
6199         r = MsiInstallProductA(msifile, NULL);
6200         ok(r == spmap[i].err, "%d: Expected %d, got %d\n", i, spmap[i].err, r);
6201         ok(get_pf_file_size("msitest\\augustus") == spmap[i].size,
6202            "%d: Expected %d, got %d\n", i, spmap[i].size,
6203            get_pf_file_size("msitest\\augustus"));
6204
6205         if (r == ERROR_SUCCESS)
6206         {
6207             ok(delete_pf("msitest\\augustus", TRUE), "%d: File not installed\n", i);
6208             ok(delete_pf("msitest", FALSE), "%d: File not installed\n", i);
6209         }
6210         else
6211         {
6212             ok(!delete_pf("msitest\\augustus", TRUE), "%d: File installed\n", i);
6213             todo_wine ok(!delete_pf("msitest", FALSE), "%d: File installed\n", i);
6214         }
6215
6216         DeleteFileA("shortone\\shorttwo\\augustus");
6217         DeleteFileA("shortone\\longtwo\\augustus");
6218         DeleteFileA("longone\\shorttwo\\augustus");
6219         DeleteFileA("longone\\longtwo\\augustus");
6220         RemoveDirectoryA("shortone\\shorttwo");
6221         RemoveDirectoryA("shortone\\longtwo");
6222         RemoveDirectoryA("longone\\shorttwo");
6223         RemoveDirectoryA("longone\\longtwo");
6224         RemoveDirectoryA("shortone");
6225         RemoveDirectoryA("longone");
6226     }
6227
6228     DeleteFileA(msifile);
6229 }
6230
6231 static void test_MsiConfigureProductEx(void)
6232 {
6233     UINT r;
6234     LONG res;
6235     DWORD type, size;
6236     HKEY props, source;
6237     CHAR keypath[MAX_PATH * 2];
6238     CHAR localpack[MAX_PATH];
6239
6240     if (on_win9x)
6241     {
6242         win_skip("Different registry keys on Win9x and WinMe\n");
6243         return;
6244     }
6245
6246     CreateDirectoryA("msitest", NULL);
6247     create_file("msitest\\hydrogen", 500);
6248     create_file("msitest\\helium", 500);
6249     create_file("msitest\\lithium", 500);
6250
6251     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
6252
6253     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6254
6255     /* NULL szProduct */
6256     r = MsiConfigureProductExA(NULL, INSTALLLEVEL_DEFAULT,
6257                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
6258     ok(r == ERROR_INVALID_PARAMETER,
6259        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6260
6261     /* empty szProduct */
6262     r = MsiConfigureProductExA("", INSTALLLEVEL_DEFAULT,
6263                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
6264     ok(r == ERROR_INVALID_PARAMETER,
6265        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6266
6267     /* garbage szProduct */
6268     r = MsiConfigureProductExA("garbage", INSTALLLEVEL_DEFAULT,
6269                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
6270     ok(r == ERROR_INVALID_PARAMETER,
6271        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6272
6273     /* guid without brackets */
6274     r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
6275                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
6276                                "PROPVAR=42");
6277     ok(r == ERROR_INVALID_PARAMETER,
6278        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6279
6280     /* guid with brackets */
6281     r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
6282                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
6283                                "PROPVAR=42");
6284     ok(r == ERROR_UNKNOWN_PRODUCT,
6285        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6286
6287     /* same length as guid, but random */
6288     r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
6289                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
6290                                "PROPVAR=42");
6291     ok(r == ERROR_UNKNOWN_PRODUCT,
6292        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6293
6294     /* product not installed yet */
6295     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
6296                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
6297                                "PROPVAR=42");
6298     ok(r == ERROR_UNKNOWN_PRODUCT,
6299        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
6300
6301     /* install the product, per-user unmanaged */
6302     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
6303     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6304     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
6305     ok(pf_exists("msitest\\helium"), "File not installed\n");
6306     ok(pf_exists("msitest\\lithium"), "File not installed\n");
6307     ok(pf_exists("msitest"), "File not installed\n");
6308
6309     /* product is installed per-user managed, remove it */
6310     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
6311                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
6312                                "PROPVAR=42");
6313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6314     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
6315     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
6316     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
6317     todo_wine
6318     {
6319         ok(!delete_pf("msitest", FALSE), "File not removed\n");
6320     }
6321
6322     /* product has been removed */
6323     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
6324                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
6325                                "PROPVAR=42");
6326     ok(r == ERROR_UNKNOWN_PRODUCT,
6327        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
6328
6329     /* install the product, machine */
6330     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
6331     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6332     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
6333     ok(pf_exists("msitest\\helium"), "File not installed\n");
6334     ok(pf_exists("msitest\\lithium"), "File not installed\n");
6335     ok(pf_exists("msitest"), "File not installed\n");
6336
6337     /* product is installed machine, remove it */
6338     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
6339                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
6340                                "PROPVAR=42");
6341     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6342     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
6343     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
6344     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
6345     todo_wine
6346     {
6347         ok(!delete_pf("msitest", FALSE), "File not removed\n");
6348     }
6349
6350     /* product has been removed */
6351     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
6352                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
6353                                "PROPVAR=42");
6354     ok(r == ERROR_UNKNOWN_PRODUCT,
6355        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
6356
6357     /* install the product, machine */
6358     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
6359     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6360     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
6361     ok(pf_exists("msitest\\helium"), "File not installed\n");
6362     ok(pf_exists("msitest\\lithium"), "File not installed\n");
6363     ok(pf_exists("msitest"), "File not installed\n");
6364
6365     DeleteFileA(msifile);
6366
6367     /* local msifile is removed */
6368     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
6369                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
6370                                "PROPVAR=42");
6371     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6372     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
6373     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
6374     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
6375     todo_wine
6376     {
6377         ok(!delete_pf("msitest", FALSE), "File not removed\n");
6378     }
6379
6380     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
6381
6382     /* install the product, machine */
6383     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
6384     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6385     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
6386     ok(pf_exists("msitest\\helium"), "File not installed\n");
6387     ok(pf_exists("msitest\\lithium"), "File not installed\n");
6388     ok(pf_exists("msitest"), "File not installed\n");
6389
6390     DeleteFileA(msifile);
6391
6392     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
6393     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
6394     lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties");
6395
6396     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
6397     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6398
6399     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
6400                          (const BYTE *)"C:\\idontexist.msi", 18);
6401     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6402
6403     /* LocalPackage is used to find the cached msi package */
6404     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
6405                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
6406                                "PROPVAR=42");
6407     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
6408        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
6409     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
6410     ok(pf_exists("msitest\\helium"), "File not installed\n");
6411     ok(pf_exists("msitest\\lithium"), "File not installed\n");
6412     ok(pf_exists("msitest"), "File not installed\n");
6413
6414     RegCloseKey(props);
6415     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
6416
6417     /* LastUsedSource (local msi package) can be used as a last resort */
6418     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
6419                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
6420                                "PROPVAR=42");
6421     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6422     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
6423     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
6424     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
6425     todo_wine
6426     {
6427         ok(!delete_pf("msitest", FALSE), "File not removed\n");
6428     }
6429
6430     /* install the product, machine */
6431     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
6432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6433     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
6434     ok(pf_exists("msitest\\helium"), "File not installed\n");
6435     ok(pf_exists("msitest\\lithium"), "File not installed\n");
6436     ok(pf_exists("msitest"), "File not installed\n");
6437
6438     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
6439     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
6440     lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties");
6441
6442     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
6443     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6444
6445     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
6446                          (const BYTE *)"C:\\idontexist.msi", 18);
6447     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6448
6449     lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\");
6450     lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\SourceList");
6451
6452     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &source);
6453     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6454
6455     type = REG_SZ;
6456     size = MAX_PATH;
6457     res = RegQueryValueExA(source, "PackageName", NULL, &type,
6458                            (LPBYTE)localpack, &size);
6459     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6460
6461     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
6462                          (const BYTE *)"idontexist.msi", 15);
6463     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6464
6465     /* SourceList is altered */
6466     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
6467                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
6468                                "PROPVAR=42");
6469     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
6470        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
6471     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
6472     ok(pf_exists("msitest\\helium"), "File not installed\n");
6473     ok(pf_exists("msitest\\lithium"), "File not installed\n");
6474     ok(pf_exists("msitest"), "File not installed\n");
6475
6476     /* restore the SourceList */
6477     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
6478                          (const BYTE *)localpack, lstrlenA(localpack) + 1);
6479     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6480
6481     /* finally remove the product */
6482     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
6483                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
6484                                "PROPVAR=42");
6485     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6486     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
6487     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
6488     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
6489     todo_wine
6490     {
6491         ok(!delete_pf("msitest", FALSE), "File not removed\n");
6492     }
6493
6494     DeleteFileA(msifile);
6495     RegCloseKey(source);
6496     RegCloseKey(props);
6497     DeleteFileA("msitest\\hydrogen");
6498     DeleteFileA("msitest\\helium");
6499     DeleteFileA("msitest\\lithium");
6500     RemoveDirectoryA("msitest");
6501 }
6502
6503 static void test_missingcomponent(void)
6504 {
6505     UINT r;
6506
6507     CreateDirectoryA("msitest", NULL);
6508     create_file("msitest\\hydrogen", 500);
6509     create_file("msitest\\helium", 500);
6510     create_file("msitest\\lithium", 500);
6511     create_file("beryllium", 500);
6512
6513     create_database(msifile, mcomp_tables, sizeof(mcomp_tables) / sizeof(msi_table));
6514
6515     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6516
6517     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
6518     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6519     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
6520     ok(pf_exists("msitest\\helium"), "File not installed\n");
6521     ok(pf_exists("msitest\\lithium"), "File not installed\n");
6522     ok(!pf_exists("msitest\\beryllium"), "File installed\n");
6523     ok(pf_exists("msitest"), "File not installed\n");
6524
6525     r = MsiInstallProductA(msifile, "REMOVE=ALL INSTALLLEVEL=10 PROPVAR=42");
6526     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6527     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
6528     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
6529     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
6530     ok(!pf_exists("msitest\\beryllium"), "File installed\n");
6531     todo_wine
6532     {
6533         ok(!delete_pf("msitest", FALSE), "File not removed\n");
6534     }
6535
6536     DeleteFileA(msifile);
6537     DeleteFileA("msitest\\hydrogen");
6538     DeleteFileA("msitest\\helium");
6539     DeleteFileA("msitest\\lithium");
6540     DeleteFileA("beryllium");
6541     RemoveDirectoryA("msitest");
6542 }
6543
6544 static void test_sourcedirprop(void)
6545 {
6546     UINT r;
6547     CHAR props[MAX_PATH];
6548
6549     CreateDirectoryA("msitest", NULL);
6550     create_file("msitest\\augustus", 500);
6551
6552     create_database(msifile, ca51_tables, sizeof(ca51_tables) / sizeof(msi_table));
6553
6554     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6555
6556     r = MsiInstallProductA(msifile, NULL);
6557     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6558     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
6559     ok(delete_pf("msitest", FALSE), "File installed\n");
6560
6561     DeleteFile("msitest\\augustus");
6562     RemoveDirectory("msitest");
6563
6564     CreateDirectoryA("altsource", NULL);
6565     CreateDirectoryA("altsource\\msitest", NULL);
6566     create_file("altsource\\msitest\\augustus", 500);
6567
6568     sprintf(props, "SRCDIR=%s\\altsource\\", CURR_DIR);
6569
6570     r = MsiInstallProductA(msifile, props);
6571     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6572     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
6573     ok(delete_pf("msitest", FALSE), "File installed\n");
6574
6575     DeleteFile(msifile);
6576     DeleteFile("altsource\\msitest\\augustus");
6577     RemoveDirectory("altsource\\msitest");
6578     RemoveDirectory("altsource");
6579 }
6580
6581 static void test_adminimage(void)
6582 {
6583     UINT r;
6584
6585     CreateDirectoryA("msitest", NULL);
6586     CreateDirectoryA("msitest\\first", NULL);
6587     CreateDirectoryA("msitest\\second", NULL);
6588     CreateDirectoryA("msitest\\cabout", NULL);
6589     CreateDirectoryA("msitest\\cabout\\new", NULL);
6590     create_file("msitest\\one.txt", 100);
6591     create_file("msitest\\first\\two.txt", 100);
6592     create_file("msitest\\second\\three.txt", 100);
6593     create_file("msitest\\cabout\\four.txt", 100);
6594     create_file("msitest\\cabout\\new\\five.txt", 100);
6595     create_file("msitest\\filename", 100);
6596     create_file("msitest\\service.exe", 100);
6597
6598     create_database_wordcount(msifile, ai_tables,
6599                               sizeof(ai_tables) / sizeof(msi_table),
6600                               msidbSumInfoSourceTypeAdminImage);
6601
6602     r = MsiInstallProductA(msifile, NULL);
6603     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6604
6605     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
6606     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
6607     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
6608     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
6609     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
6610     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
6611     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
6612     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
6613     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
6614     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
6615     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
6616     ok(delete_pf("msitest", FALSE), "File not installed\n");
6617
6618     DeleteFileA("msitest.msi");
6619     DeleteFileA("msitest\\cabout\\new\\five.txt");
6620     DeleteFileA("msitest\\cabout\\four.txt");
6621     DeleteFileA("msitest\\second\\three.txt");
6622     DeleteFileA("msitest\\first\\two.txt");
6623     DeleteFileA("msitest\\one.txt");
6624     DeleteFileA("msitest\\service.exe");
6625     DeleteFileA("msitest\\filename");
6626     RemoveDirectoryA("msitest\\cabout\\new");
6627     RemoveDirectoryA("msitest\\cabout");
6628     RemoveDirectoryA("msitest\\second");
6629     RemoveDirectoryA("msitest\\first");
6630     RemoveDirectoryA("msitest");
6631 }
6632
6633 static void test_propcase(void)
6634 {
6635     UINT r;
6636
6637     CreateDirectoryA("msitest", NULL);
6638     create_file("msitest\\augustus", 500);
6639
6640     create_database(msifile, pc_tables, sizeof(pc_tables) / sizeof(msi_table));
6641
6642     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6643
6644     r = MsiInstallProductA(msifile, "MyProp=42");
6645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6646     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
6647     ok(delete_pf("msitest", FALSE), "File not installed\n");
6648
6649     DeleteFile(msifile);
6650     DeleteFile("msitest\\augustus");
6651     RemoveDirectory("msitest");
6652 }
6653
6654 static void test_int_widths( void )
6655 {
6656     static const char int0[] = "int0\ni0\nint0\tint0\n1";
6657     static const char int1[] = "int1\ni1\nint1\tint1\n1";
6658     static const char int2[] = "int2\ni2\nint2\tint2\n1";
6659     static const char int3[] = "int3\ni3\nint3\tint3\n1";
6660     static const char int4[] = "int4\ni4\nint4\tint4\n1";
6661     static const char int5[] = "int5\ni5\nint5\tint5\n1";
6662     static const char int8[] = "int8\ni8\nint8\tint8\n1";
6663
6664     static const struct
6665     {
6666         const char  *data;
6667         unsigned int size;
6668         UINT         ret;
6669     }
6670     tests[] =
6671     {
6672         { int0, sizeof(int0) - 1, ERROR_SUCCESS },
6673         { int1, sizeof(int1) - 1, ERROR_SUCCESS },
6674         { int2, sizeof(int2) - 1, ERROR_SUCCESS },
6675         { int3, sizeof(int3) - 1, ERROR_FUNCTION_FAILED },
6676         { int4, sizeof(int4) - 1, ERROR_SUCCESS },
6677         { int5, sizeof(int5) - 1, ERROR_FUNCTION_FAILED },
6678         { int8, sizeof(int8) - 1, ERROR_FUNCTION_FAILED }
6679     };
6680
6681     char tmpdir[MAX_PATH], msitable[MAX_PATH], msidb[MAX_PATH];
6682     MSIHANDLE db;
6683     UINT r, i;
6684
6685     GetTempPathA(MAX_PATH, tmpdir);
6686     CreateDirectoryA(tmpdir, NULL);
6687
6688     strcpy(msitable, tmpdir);
6689     strcat(msitable, "\\msitable.idt");
6690
6691     strcpy(msidb, tmpdir);
6692     strcat(msidb, "\\msitest.msi");
6693
6694     r = MsiOpenDatabaseA(msidb, MSIDBOPEN_CREATE, &db);
6695     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6696
6697     for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
6698     {
6699         write_file(msitable, tests[i].data, tests[i].size);
6700
6701         r = MsiDatabaseImportA(db, tmpdir, "msitable.idt");
6702         ok(r == tests[i].ret, " %u expected %u, got %u\n", i, tests[i].ret, r);
6703
6704         r = MsiDatabaseCommit(db);
6705         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6706         DeleteFileA(msitable);
6707     }
6708
6709     MsiCloseHandle(db);
6710     DeleteFileA(msidb);
6711     RemoveDirectoryA(tmpdir);
6712 }
6713
6714 static void test_shortcut(void)
6715 {
6716     UINT r;
6717     HRESULT hr;
6718
6719     create_test_files();
6720     create_database(msifile, sc_tables, sizeof(sc_tables) / sizeof(msi_table));
6721
6722     r = MsiInstallProductA(msifile, NULL);
6723     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6724
6725     hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
6726     ok(SUCCEEDED(hr), "CoInitialize failed 0x%08x\n", hr);
6727
6728     r = MsiInstallProductA(msifile, NULL);
6729     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6730
6731     CoUninitialize();
6732
6733     hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
6734     ok(SUCCEEDED(hr), "CoInitialize failed 0x%08x\n", hr);
6735
6736     r = MsiInstallProductA(msifile, NULL);
6737     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6738
6739     CoUninitialize();
6740
6741     delete_pf("msitest\\cabout\\new\\five.txt", TRUE);
6742     delete_pf("msitest\\cabout\\new", FALSE);
6743     delete_pf("msitest\\cabout\\four.txt", TRUE);
6744     delete_pf("msitest\\cabout", FALSE);
6745     delete_pf("msitest\\changed\\three.txt", TRUE);
6746     delete_pf("msitest\\changed", FALSE);
6747     delete_pf("msitest\\first\\two.txt", TRUE);
6748     delete_pf("msitest\\first", FALSE);
6749     delete_pf("msitest\\filename", TRUE);
6750     delete_pf("msitest\\one.txt", TRUE);
6751     delete_pf("msitest\\service.exe", TRUE);
6752     delete_pf("msitest\\Shortcut.lnk", TRUE);
6753     delete_pf("msitest", FALSE);
6754     delete_test_files();
6755 }
6756
6757 static void test_envvar(void)
6758 {
6759     UINT r;
6760     HKEY env;
6761     LONG res;
6762     DWORD type, size;
6763     char buffer[16];
6764     UINT i;
6765
6766     if (on_win9x)
6767     {
6768         win_skip("Environment variables are handled differently on Win9x and WinMe\n");
6769         return;
6770     }
6771
6772     create_test_files();
6773     create_database(msifile, env_tables, sizeof(env_tables) / sizeof(msi_table));
6774
6775     res = RegCreateKeyExA(HKEY_CURRENT_USER, "Environment", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &env, NULL);
6776     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6777
6778     res = RegSetValueExA(env, "MSITESTVAR1", 0, REG_SZ, (const BYTE *)"0", 2);
6779     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6780
6781     res = RegSetValueExA(env, "MSITESTVAR2", 0, REG_SZ, (const BYTE *)"0", 2);
6782     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6783
6784     r = MsiInstallProductA(msifile, NULL);
6785     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6786
6787     type = REG_NONE;
6788     size = sizeof(buffer);
6789     buffer[0] = 0;
6790     res = RegQueryValueExA(env, "MSITESTVAR1", NULL, &type, (LPBYTE)buffer, &size);
6791     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6792     ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type);
6793     ok(!lstrcmp(buffer, "1"), "Expected \"1\", got %s\n", buffer);
6794
6795     res = RegDeleteValueA(env, "MSITESTVAR1");
6796     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6797
6798     type = REG_NONE;
6799     size = sizeof(buffer);
6800     buffer[0] = 0;
6801     res = RegQueryValueExA(env, "MSITESTVAR2", NULL, &type, (LPBYTE)buffer, &size);
6802     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6803     ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type);
6804     ok(!lstrcmp(buffer, "1"), "Expected \"1\", got %s\n", buffer);
6805
6806     res = RegDeleteValueA(env, "MSITESTVAR2");
6807     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6808
6809     res = RegDeleteValueA(env, "MSITESTVAR3");
6810     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6811
6812     res = RegDeleteValueA(env, "MSITESTVAR4");
6813     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
6814
6815     res = RegDeleteValueA(env, "MSITESTVAR5");
6816     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
6817
6818     res = RegDeleteValueA(env, "MSITESTVAR6");
6819     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
6820
6821     res = RegDeleteValueA(env, "MSITESTVAR7");
6822     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
6823
6824     res = RegDeleteValueA(env, "MSITESTVAR8");
6825     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
6826
6827     res = RegDeleteValueA(env, "MSITESTVAR9");
6828     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
6829
6830     res = RegDeleteValueA(env, "MSITESTVAR10");
6831     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
6832
6833     i = 11;
6834     while (environment_dat_results[(i-11)]) {
6835         char name[20];
6836         sprintf(name, "MSITESTVAR%d", i);
6837
6838         type = REG_NONE;
6839         size = sizeof(buffer);
6840         buffer[0] = 0;
6841         res = RegQueryValueExA(env, name, NULL, &type, (LPBYTE)buffer, &size);
6842         ok(res == ERROR_SUCCESS, "%d: Expected ERROR_SUCCESS, got %d\n", i, res);
6843         ok(type == REG_SZ, "%d: Expected REG_SZ, got %u\n", i, type);
6844         ok(!lstrcmp(buffer, environment_dat_results[(i-11)]), "%d: Expected %s, got %s\n",
6845            i, environment_dat_results[(i-11)], buffer);
6846
6847         res = RegDeleteValueA(env, name);
6848         ok(res == ERROR_SUCCESS, "%d: Expected ERROR_SUCCESS, got %d\n", i, res);
6849         i++;
6850     }
6851
6852
6853     RegCloseKey(env);
6854     delete_pf("msitest\\cabout\\new\\five.txt", TRUE);
6855     delete_pf("msitest\\cabout\\new", FALSE);
6856     delete_pf("msitest\\cabout\\four.txt", TRUE);
6857     delete_pf("msitest\\cabout", FALSE);
6858     delete_pf("msitest\\changed\\three.txt", TRUE);
6859     delete_pf("msitest\\changed", FALSE);
6860     delete_pf("msitest\\first\\two.txt", TRUE);
6861     delete_pf("msitest\\first", FALSE);
6862     delete_pf("msitest\\filename", TRUE);
6863     delete_pf("msitest\\one.txt", TRUE);
6864     delete_pf("msitest\\service.exe", TRUE);
6865     delete_pf("msitest", FALSE);
6866     delete_test_files();
6867 }
6868
6869 static void test_preselected(void)
6870 {
6871     UINT r;
6872
6873     create_test_files();
6874     create_database(msifile, ps_tables, sizeof(ps_tables) / sizeof(msi_table));
6875
6876     r = MsiInstallProductA(msifile, "ADDLOCAL=One");
6877     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6878
6879     ok(!delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File installed\n");
6880     ok(!delete_pf("msitest\\cabout\\new", FALSE), "File installed\n");
6881     ok(!delete_pf("msitest\\cabout\\four.txt", TRUE), "File installed\n");
6882     ok(!delete_pf("msitest\\cabout", FALSE), "File installed\n");
6883     ok(!delete_pf("msitest\\changed\\three.txt", TRUE), "File installed\n");
6884     ok(!delete_pf("msitest\\changed", FALSE), "File installed\n");
6885     ok(!delete_pf("msitest\\first\\two.txt", TRUE), "File installed\n");
6886     ok(!delete_pf("msitest\\first", FALSE), "File installed\n");
6887     ok(!delete_pf("msitest\\filename", TRUE), "File installed\n");
6888     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
6889     ok(!delete_pf("msitest\\service.exe", TRUE), "File installed\n");
6890     ok(delete_pf("msitest", FALSE), "File not installed\n");
6891
6892     r = MsiInstallProductA(msifile, NULL);
6893     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6894
6895     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
6896     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
6897     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
6898     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
6899     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
6900     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
6901     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
6902     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
6903     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
6904     ok(!delete_pf("msitest\\one.txt", TRUE), "File installed\n");
6905     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
6906     ok(delete_pf("msitest", FALSE), "File not installed\n");
6907     delete_test_files();
6908 }
6909
6910 static void test_installed_prop(void)
6911 {
6912     static char prodcode[] = "{7df88a48-996f-4ec8-a022-bf956f9b2cbb}";
6913     UINT r;
6914
6915     create_test_files();
6916     create_database(msifile, ip_tables, sizeof(ip_tables) / sizeof(msi_table));
6917
6918     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6919
6920     r = MsiInstallProductA(msifile, "FULL=1");
6921     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6922
6923     r = MsiInstallProductA(msifile, "FULL=1");
6924     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
6925
6926     r = MsiConfigureProductExA(prodcode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, "FULL=1");
6927     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
6928
6929     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
6930     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
6931     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
6932     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
6933     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
6934     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
6935     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
6936     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
6937     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
6938     ok(delete_pf("msitest\\one.txt", TRUE), "File installed\n");
6939     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
6940     ok(delete_pf("msitest", FALSE), "File not installed\n");
6941
6942     r = MsiInstallProductA(msifile, "REMOVE=ALL");
6943     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6944
6945     delete_test_files();
6946 }
6947
6948 static void test_allusers_prop(void)
6949 {
6950     UINT r;
6951
6952     create_test_files();
6953     create_database(msifile, aup_tables, sizeof(aup_tables) / sizeof(msi_table));
6954
6955     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6956
6957     /* ALLUSERS property unset */
6958     r = MsiInstallProductA(msifile, "FULL=1");
6959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6960
6961     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
6962     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
6963     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
6964     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
6965     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
6966     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
6967     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
6968     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
6969     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
6970     ok(delete_pf("msitest\\one.txt", TRUE), "File installed\n");
6971     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
6972     ok(delete_pf("msitest", FALSE), "File not installed\n");
6973
6974     r = MsiInstallProductA(msifile, "REMOVE=ALL");
6975     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6976
6977     delete_test_files();
6978
6979     create_test_files();
6980     create_database(msifile, aup2_tables, sizeof(aup2_tables) / sizeof(msi_table));
6981
6982     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6983
6984     /* ALLUSERS property set to 1 */
6985     r = MsiInstallProductA(msifile, "FULL=1");
6986     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6987
6988     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
6989     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
6990     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
6991     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
6992     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
6993     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
6994     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
6995     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
6996     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
6997     ok(delete_pf("msitest\\one.txt", TRUE), "File installed\n");
6998     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
6999     ok(delete_pf("msitest", FALSE), "File not installed\n");
7000
7001     r = MsiInstallProductA(msifile, "REMOVE=ALL");
7002     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
7003
7004     delete_test_files();
7005
7006     create_test_files();
7007     create_database(msifile, aup3_tables, sizeof(aup3_tables) / sizeof(msi_table));
7008
7009     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7010
7011     /* ALLUSERS property set to 2 */
7012     r = MsiInstallProductA(msifile, "FULL=1");
7013     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
7014
7015     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
7016     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
7017     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
7018     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
7019     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
7020     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
7021     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
7022     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
7023     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
7024     ok(delete_pf("msitest\\one.txt", TRUE), "File installed\n");
7025     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
7026     ok(delete_pf("msitest", FALSE), "File not installed\n");
7027
7028     r = MsiInstallProductA(msifile, "REMOVE=ALL");
7029     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
7030
7031     delete_test_files();
7032
7033     create_test_files();
7034     create_database(msifile, aup4_tables, sizeof(aup4_tables) / sizeof(msi_table));
7035
7036     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7037
7038     /* ALLUSERS property set to 2, conditioned on ALLUSERS = 1 */
7039     r = MsiInstallProductA(msifile, "FULL=1");
7040     if (r == ERROR_SUCCESS)
7041     {
7042         /* Win9x/WinMe */
7043         win_skip("Win9x and WinMe act differently with respect to ALLUSERS\n");
7044
7045         ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
7046         ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
7047         ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
7048         ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
7049         ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
7050         ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
7051         ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
7052         ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
7053         ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
7054         ok(delete_pf("msitest\\one.txt", TRUE), "File installed\n");
7055         ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
7056         ok(delete_pf("msitest", FALSE), "File not installed\n");
7057
7058         r = MsiInstallProductA(msifile, "REMOVE=ALL");
7059         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
7060
7061         delete_test_files();
7062     }
7063     else
7064         ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
7065 }
7066
7067 static char session_manager[] = "System\\CurrentControlSet\\Control\\Session Manager";
7068 static char rename_ops[]      = "PendingFileRenameOperations";
7069
7070 static void process_pending_renames(HKEY hkey)
7071 {
7072     char *buf, *src, *dst;
7073     DWORD size;
7074     LONG ret;
7075
7076     ret = RegQueryValueExA(hkey, rename_ops, NULL, NULL, NULL, &size);
7077     buf = HeapAlloc(GetProcessHeap(), 0, size);
7078     buf[0] = 0;
7079
7080     ret = RegQueryValueExA(hkey, rename_ops, NULL, NULL, (LPBYTE)buf, &size);
7081     ok(!ret, "RegQueryValueExA failed %d (%u)\n", ret, GetLastError());
7082     ok(strstr(buf, "msitest\\maximus") != NULL, "Unexpected value \"%s\"\n", buf);
7083
7084     for (src = buf; *src; src = dst + strlen(dst) + 1)
7085     {
7086         DWORD flags = MOVEFILE_COPY_ALLOWED;
7087
7088         dst = src + strlen(src) + 1;
7089         if (*dst == '!')
7090         {
7091             flags |= MOVEFILE_REPLACE_EXISTING;
7092             dst++;
7093         }
7094         if (src[0] == '\\' && src[1] == '?' && src[2] == '?' && src[3] == '\\') src += 4;
7095         if (*dst)
7096         {
7097             if (dst[0] == '\\' && dst[1] == '?' && dst[2] == '?' && dst[3] == '\\') dst += 4;
7098             ok(MoveFileExA(src, dst, flags), "Failed to move file %s -> %s (%u)\n", src, dst, GetLastError());
7099         }
7100         else
7101             ok(DeleteFileA(src), "Failed to delete file %s (%u)\n", src, GetLastError());
7102     }
7103     HeapFree(GetProcessHeap(), 0, buf);
7104     RegDeleteValueA(hkey, rename_ops);
7105 }
7106
7107 static BOOL file_matches_data(LPCSTR file, LPCSTR data)
7108 {
7109     DWORD len, data_len = strlen(data);
7110     HANDLE handle;
7111     char buf[128];
7112
7113     handle = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
7114     ok(handle != INVALID_HANDLE_VALUE, "failed to open %s (%u)\n", file, GetLastError());
7115
7116     if (ReadFile(handle, buf, sizeof(buf), &len, NULL) && len >= data_len)
7117     {
7118         CloseHandle(handle);
7119         return !memcmp(buf, data, data_len);
7120     }
7121     CloseHandle(handle);
7122     return FALSE;
7123 }
7124
7125 static void test_file_in_use(void)
7126 {
7127     UINT r;
7128     DWORD size;
7129     HANDLE file;
7130     HKEY hkey;
7131     char path[MAX_PATH];
7132
7133     if (on_win9x)
7134     {
7135         win_skip("Pending file renaming is implemented differently on Win9x and WinMe\n");
7136         return;
7137     }
7138
7139     RegOpenKeyExA(HKEY_LOCAL_MACHINE, session_manager, 0, KEY_ALL_ACCESS, &hkey);
7140     if (!RegQueryValueExA(hkey, rename_ops, NULL, NULL, NULL, &size))
7141     {
7142         skip("Pending file rename operations, skipping test\n");
7143         return;
7144     }
7145
7146     CreateDirectoryA("msitest", NULL);
7147     create_file("msitest\\maximus", 500);
7148     create_database(msifile, fiu_tables, sizeof(fiu_tables) / sizeof(msi_table));
7149
7150     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7151
7152     lstrcpy(path, PROG_FILES_DIR);
7153     lstrcat(path, "\\msitest");
7154     CreateDirectoryA(path, NULL);
7155
7156     lstrcat(path, "\\maximus");
7157     file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
7158
7159     r = MsiInstallProductA(msifile, "REBOOT=ReallySuppress FULL=1");
7160     ok(r == ERROR_SUCCESS_REBOOT_REQUIRED, "Expected ERROR_SUCCESS_REBOOT_REQUIRED got %u\n", r);
7161     ok(!file_matches_data(path, "msitest\\maximus"), "Expected file not to match\n");
7162     CloseHandle(file);
7163     ok(!file_matches_data(path, "msitest\\maximus"), "Expected file not to match\n");
7164
7165     process_pending_renames(hkey);
7166     RegCloseKey(hkey);
7167
7168     ok(file_matches_data(path, "msitest\\maximus"), "Expected file to match\n");
7169     ok(delete_pf("msitest\\maximus", TRUE), "File not present\n");
7170     ok(delete_pf("msitest", FALSE), "Directory not present or not empty\n");
7171
7172     r = MsiInstallProductA(msifile, "REMOVE=ALL");
7173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
7174
7175     delete_test_files();
7176 }
7177
7178 static void test_file_in_use_cab(void)
7179 {
7180     UINT r;
7181     DWORD size;
7182     HANDLE file;
7183     HKEY hkey;
7184     char path[MAX_PATH];
7185
7186     if (on_win9x)
7187     {
7188         win_skip("Pending file renaming is implemented differently on Win9x and WinMe\n");
7189         return;
7190     }
7191
7192     RegOpenKeyExA(HKEY_LOCAL_MACHINE, session_manager, 0, KEY_ALL_ACCESS, &hkey);
7193     if (!RegQueryValueExA(hkey, rename_ops, NULL, NULL, NULL, &size))
7194     {
7195         skip("Pending file rename operations, skipping test\n");
7196         return;
7197     }
7198
7199     CreateDirectoryA("msitest", NULL);
7200     create_file("maximus", 500);
7201     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
7202     DeleteFile("maximus");
7203
7204     create_database(msifile, fiuc_tables, sizeof(fiuc_tables) / sizeof(msi_table));
7205
7206     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7207
7208     lstrcpy(path, PROG_FILES_DIR);
7209     lstrcat(path, "\\msitest");
7210     CreateDirectoryA(path, NULL);
7211
7212     lstrcat(path, "\\maximus");
7213     file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
7214
7215     r = MsiInstallProductA(msifile, "REBOOT=ReallySuppress FULL=1");
7216     ok(r == ERROR_SUCCESS_REBOOT_REQUIRED, "Expected ERROR_SUCCESS_REBOOT_REQUIRED got %u\n", r);
7217     ok(!file_matches_data(path, "maximus"), "Expected file not to match\n");
7218     CloseHandle(file);
7219     ok(!file_matches_data(path, "maximus"), "Expected file not to match\n");
7220
7221     process_pending_renames(hkey);
7222     RegCloseKey(hkey);
7223
7224     ok(file_matches_data(path, "maximus"), "Expected file to match\n");
7225     ok(delete_pf("msitest\\maximus", TRUE), "File not present\n");
7226     ok(delete_pf("msitest", FALSE), "Directory not present or not empty\n");
7227
7228     r = MsiInstallProductA(msifile, "REMOVE=ALL");
7229     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
7230
7231     delete_cab_files();
7232     delete_test_files();
7233 }
7234
7235 static INT CALLBACK handler_a(LPVOID context, UINT type, LPCSTR msg)
7236 {
7237     return IDOK;
7238 }
7239
7240 static INT CALLBACK handler_w(LPVOID context, UINT type, LPCWSTR msg)
7241 {
7242     return IDOK;
7243 }
7244
7245 static INT CALLBACK handler_record(LPVOID context, UINT type, MSIHANDLE record)
7246 {
7247     return IDOK;
7248 }
7249
7250 static void test_MsiSetExternalUI(void)
7251 {
7252     INSTALLUI_HANDLERA ret_a;
7253     INSTALLUI_HANDLERW ret_w;
7254     INSTALLUI_HANDLER_RECORD prev;
7255     UINT error;
7256
7257     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
7258     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
7259
7260     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
7261     ok(ret_a == handler_a, "expected %p, got %p\n", handler_a, ret_a);
7262
7263     /* Not present before Installer 3.1 */
7264     if (!pMsiSetExternalUIRecord) {
7265         win_skip("MsiSetExternalUIRecord is not available\n");
7266         return;
7267     }
7268
7269     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
7270     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
7271     ok(prev == NULL, "expected NULL, got %p\n", prev);
7272
7273     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
7274     error = pMsiSetExternalUIRecord(NULL, INSTALLLOGMODE_ERROR, NULL, &prev);
7275     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
7276     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
7277
7278     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
7279     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
7280
7281     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
7282     ok(ret_w == handler_w, "expected %p, got %p\n", handler_w, ret_w);
7283
7284     ret_a = MsiSetExternalUIA(handler_a, INSTALLLOGMODE_ERROR, NULL);
7285     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
7286
7287     ret_w = MsiSetExternalUIW(handler_w, INSTALLLOGMODE_ERROR, NULL);
7288     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
7289
7290     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
7291     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, &prev);
7292     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
7293     ok(prev == NULL, "expected NULL, got %p\n", prev);
7294
7295     ret_a = MsiSetExternalUIA(NULL, 0, NULL);
7296     ok(ret_a == NULL, "expected NULL, got %p\n", ret_a);
7297
7298     ret_w = MsiSetExternalUIW(NULL, 0, NULL);
7299     ok(ret_w == NULL, "expected NULL, got %p\n", ret_w);
7300
7301     prev = (INSTALLUI_HANDLER_RECORD)0xdeadbeef;
7302     error = pMsiSetExternalUIRecord(NULL, 0, NULL, &prev);
7303     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
7304     ok(prev == handler_record, "expected %p, got %p\n", handler_record, prev);
7305
7306     error = pMsiSetExternalUIRecord(handler_record, INSTALLLOGMODE_ERROR, NULL, NULL);
7307     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
7308
7309     error = pMsiSetExternalUIRecord(NULL, 0, NULL, NULL);
7310     ok(!error, "MsiSetExternalUIRecord failed %u\n", error);
7311 }
7312
7313 static void test_feature_override(void)
7314 {
7315     UINT r;
7316
7317     create_test_files();
7318     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
7319
7320     r = MsiInstallProductA(msifile, "ADDLOCAL=One");
7321     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
7322
7323     ok(!delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File installed\n");
7324     ok(!delete_pf("msitest\\cabout\\new", FALSE), "File installed\n");
7325     ok(!delete_pf("msitest\\cabout\\four.txt", TRUE), "File installed\n");
7326     ok(!delete_pf("msitest\\cabout", FALSE), "File installed\n");
7327     ok(!delete_pf("msitest\\changed\\three.txt", TRUE), "File installed\n");
7328     ok(!delete_pf("msitest\\changed", FALSE), "File installed\n");
7329     ok(!delete_pf("msitest\\first\\two.txt", TRUE), "File installed\n");
7330     ok(!delete_pf("msitest\\first", FALSE), "File installed\n");
7331     ok(!delete_pf("msitest\\filename", TRUE), "File installed\n");
7332     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
7333     ok(!delete_pf("msitest\\service.exe", TRUE), "File installed\n");
7334     ok(delete_pf("msitest", FALSE), "File not installed\n");
7335
7336     delete_test_files();
7337 }
7338
7339 START_TEST(install)
7340 {
7341     DWORD len;
7342     char temp_path[MAX_PATH], prev_path[MAX_PATH], log_file[MAX_PATH];
7343     STATEMGRSTATUS status;
7344     BOOL ret = FALSE;
7345
7346     init_functionpointers();
7347
7348     on_win9x = check_win9x();
7349
7350     GetCurrentDirectoryA(MAX_PATH, prev_path);
7351     GetTempPath(MAX_PATH, temp_path);
7352     SetCurrentDirectoryA(temp_path);
7353
7354     lstrcpyA(CURR_DIR, temp_path);
7355     len = lstrlenA(CURR_DIR);
7356
7357     if(len && (CURR_DIR[len - 1] == '\\'))
7358         CURR_DIR[len - 1] = 0;
7359
7360     get_program_files_dir(PROG_FILES_DIR, COMMON_FILES_DIR);
7361
7362     /* Create a restore point ourselves so we circumvent the multitude of restore points
7363      * that would have been created by all the installation and removal tests.
7364      */
7365     if (pSRSetRestorePointA)
7366     {
7367         memset(&status, 0, sizeof(status));
7368         ret = notify_system_change(BEGIN_NESTED_SYSTEM_CHANGE, &status);
7369     }
7370
7371     /* Create only one log file and don't append. We have to pass something
7372      * for the log mode for this to work. The logfile needs to have an absolute
7373      * path otherwise we still end up with some extra logfiles as some tests
7374      * change the current directory.
7375      */
7376     lstrcpyA(log_file, temp_path);
7377     lstrcatA(log_file, "\\msitest.log");
7378     MsiEnableLogA(INSTALLLOGMODE_FATALEXIT, log_file, 0);
7379
7380     test_MsiInstallProduct();
7381     test_MsiSetComponentState();
7382     test_packagecoltypes();
7383     test_continuouscabs();
7384     test_caborder();
7385     test_mixedmedia();
7386     test_samesequence();
7387     test_uiLevelFlags();
7388     test_readonlyfile();
7389     test_readonlyfile_cab();
7390     test_setdirproperty();
7391     test_cabisextracted();
7392     test_concurrentinstall();
7393     test_setpropertyfolder();
7394     test_publish_registerproduct();
7395     test_publish_publishproduct();
7396     test_publish_publishfeatures();
7397     test_publish_registeruser();
7398     test_publish_processcomponents();
7399     test_publish();
7400     test_publishsourcelist();
7401     test_transformprop();
7402     test_currentworkingdir();
7403     test_admin();
7404     test_adminprops();
7405     test_removefiles();
7406     test_movefiles();
7407     test_missingcab();
7408     test_duplicatefiles();
7409     test_writeregistryvalues();
7410     test_sourcefolder();
7411     test_customaction51();
7412     test_installstate();
7413     test_sourcepath();
7414     test_MsiConfigureProductEx();
7415     test_missingcomponent();
7416     test_sourcedirprop();
7417     test_adminimage();
7418     test_propcase();
7419     test_int_widths();
7420     test_shortcut();
7421     test_envvar();
7422     test_lastusedsource();
7423     test_preselected();
7424     test_installed_prop();
7425     test_file_in_use();
7426     test_file_in_use_cab();
7427     test_MsiSetExternalUI();
7428     test_allusers_prop();
7429     test_feature_override();
7430
7431     DeleteFileA(log_file);
7432
7433     if (pSRSetRestorePointA && ret)
7434     {
7435         ret = notify_system_change(END_NESTED_SYSTEM_CHANGE, &status);
7436         if (ret)
7437             remove_restore_point(status.llSequenceNumber);
7438     }
7439     FreeLibrary(hsrclient);
7440
7441     SetCurrentDirectoryA(prev_path);
7442 }