msi: Properly register features.
[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
33 #include "wine/test.h"
34
35 static UINT (WINAPI *pMsiQueryComponentStateA)
36     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
37 static UINT (WINAPI *pMsiSourceListGetInfoA)
38     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
39
40 static const char *msifile = "msitest.msi";
41 static const char *msifile2 = "winetest2.msi";
42 static const char *mstfile = "winetest.mst";
43 static CHAR CURR_DIR[MAX_PATH];
44 static CHAR PROG_FILES_DIR[MAX_PATH];
45 static CHAR COMMON_FILES_DIR[MAX_PATH];
46
47 /* msi database data */
48
49 static const CHAR component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
50                                     "s72\tS38\ts72\ti2\tS255\tS72\n"
51                                     "Component\tComponent\n"
52                                     "Five\t{8CC92E9D-14B2-4CA4-B2AA-B11D02078087}\tNEWDIR\t2\t\tfive.txt\n"
53                                     "Four\t{FD37B4EA-7209-45C0-8917-535F35A2F080}\tCABOUTDIR\t2\t\tfour.txt\n"
54                                     "One\t{783B242E-E185-4A56-AF86-C09815EC053C}\tMSITESTDIR\t2\t\tone.txt\n"
55                                     "Three\t{010B6ADD-B27D-4EDD-9B3D-34C4F7D61684}\tCHANGEDDIR\t2\t\tthree.txt\n"
56                                     "Two\t{BF03D1A6-20DA-4A65-82F3-6CAC995915CE}\tFIRSTDIR\t2\t\ttwo.txt\n"
57                                     "dangler\t{6091DF25-EF96-45F1-B8E9-A9B1420C7A3C}\tTARGETDIR\t4\t\tregdata\n"
58                                     "component\t\tMSITESTDIR\t0\t1\tfile\n"
59                                     "service_comp\t\tMSITESTDIR\t0\t1\tservice_file";
60
61 static const CHAR directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
62                                     "s72\tS72\tl255\n"
63                                     "Directory\tDirectory\n"
64                                     "CABOUTDIR\tMSITESTDIR\tcabout\n"
65                                     "CHANGEDDIR\tMSITESTDIR\tchanged:second\n"
66                                     "FIRSTDIR\tMSITESTDIR\tfirst\n"
67                                     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
68                                     "NEWDIR\tCABOUTDIR\tnew\n"
69                                     "ProgramFilesFolder\tTARGETDIR\t.\n"
70                                     "TARGETDIR\t\tSourceDir";
71
72 static const CHAR feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
73                                   "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
74                                   "Feature\tFeature\n"
75                                   "Five\t\tFive\tThe Five Feature\t5\t3\tNEWDIR\t0\n"
76                                   "Four\t\tFour\tThe Four Feature\t4\t3\tCABOUTDIR\t0\n"
77                                   "One\t\tOne\tThe One Feature\t1\t3\tMSITESTDIR\t0\n"
78                                   "Three\t\tThree\tThe Three Feature\t3\t3\tCHANGEDDIR\t0\n"
79                                   "Two\t\tTwo\tThe Two Feature\t2\t3\tFIRSTDIR\t0\n"
80                                   "feature\t\t\t\t2\t1\tTARGETDIR\t0\n"
81                                   "service_feature\t\t\t\t2\t1\tTARGETDIR\t0";
82
83 static const CHAR feature_comp_dat[] = "Feature_\tComponent_\n"
84                                        "s38\ts72\n"
85                                        "FeatureComponents\tFeature_\tComponent_\n"
86                                        "Five\tFive\n"
87                                        "Four\tFour\n"
88                                        "One\tOne\n"
89                                        "Three\tThree\n"
90                                        "Two\tTwo\n"
91                                        "feature\tcomponent\n"
92                                        "service_feature\tservice_comp\n";
93
94 static const CHAR file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
95                                "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
96                                "File\tFile\n"
97                                "five.txt\tFive\tfive.txt\t1000\t\t\t16384\t5\n"
98                                "four.txt\tFour\tfour.txt\t1000\t\t\t16384\t4\n"
99                                "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n"
100                                "three.txt\tThree\tthree.txt\t1000\t\t\t0\t3\n"
101                                "two.txt\tTwo\ttwo.txt\t1000\t\t\t0\t2\n"
102                                "file\tcomponent\tfilename\t100\t\t\t8192\t1\n"
103                                "service_file\tservice_comp\tservice.exe\t100\t\t\t8192\t1";
104
105 static const CHAR install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
106                                            "s72\tS255\tI2\n"
107                                            "InstallExecuteSequence\tAction\n"
108                                            "AllocateRegistrySpace\tNOT Installed\t1550\n"
109                                            "CostFinalize\t\t1000\n"
110                                            "CostInitialize\t\t800\n"
111                                            "FileCost\t\t900\n"
112                                            "ResolveSource\t\t950\n"
113                                            "MoveFiles\t\t1700\n"
114                                            "InstallFiles\t\t4000\n"
115                                            "InstallServices\t\t5000\n"
116                                            "InstallFinalize\t\t6600\n"
117                                            "InstallInitialize\t\t1500\n"
118                                            "InstallValidate\t\t1400\n"
119                                            "LaunchConditions\t\t100\n"
120                                            "WriteRegistryValues\tSourceDir And SOURCEDIR\t5000";
121
122 static const CHAR media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
123                                 "i2\ti4\tL64\tS255\tS32\tS72\n"
124                                 "Media\tDiskId\n"
125                                 "1\t3\t\t\tDISK1\t\n"
126                                 "2\t5\t\tmsitest.cab\tDISK2\t\n";
127
128 static const CHAR property_dat[] = "Property\tValue\n"
129                                    "s72\tl0\n"
130                                    "Property\tProperty\n"
131                                    "DefaultUIFont\tDlgFont8\n"
132                                    "HASUIRUN\t0\n"
133                                    "INSTALLLEVEL\t3\n"
134                                    "InstallMode\tTypical\n"
135                                    "Manufacturer\tWine\n"
136                                    "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
137                                    "ProductCode\t{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}\n"
138                                    "ProductID\tnone\n"
139                                    "ProductLanguage\t1033\n"
140                                    "ProductName\tMSITEST\n"
141                                    "ProductVersion\t1.1.1\n"
142                                    "PROMPTROLLBACKCOST\tP\n"
143                                    "Setup\tSetup\n"
144                                    "UpgradeCode\t{4C0EAA15-0264-4E5A-8758-609EF142B92D}\n"
145                                    "AdminProperties\tPOSTADMIN\n"
146                                    "ROOTDRIVE\tC:\\\n";
147
148 static const CHAR registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
149                                    "s72\ti2\tl255\tL255\tL0\ts72\n"
150                                    "Registry\tRegistry\n"
151                                    "Apples\t2\tSOFTWARE\\Wine\\msitest\tName\timaname\tOne\n"
152                                    "Oranges\t2\tSOFTWARE\\Wine\\msitest\tnumber\t#314\tTwo\n"
153                                    "regdata\t2\tSOFTWARE\\Wine\\msitest\tblah\tbad\tdangler\n"
154                                    "OrderTest\t2\tSOFTWARE\\Wine\\msitest\tOrderTestName\tOrderTestValue\tcomponent";
155
156 static const CHAR service_install_dat[] = "ServiceInstall\tName\tDisplayName\tServiceType\tStartType\tErrorControl\t"
157                                           "LoadOrderGroup\tDependencies\tStartName\tPassword\tArguments\tComponent_\tDescription\n"
158                                           "s72\ts255\tL255\ti4\ti4\ti4\tS255\tS255\tS255\tS255\tS255\ts72\tL255\n"
159                                           "ServiceInstall\tServiceInstall\n"
160                                           "TestService\tTestService\tTestService\t2\t3\t0\t\t\tTestService\t\t\tservice_comp\t\t";
161
162 static const CHAR service_control_dat[] = "ServiceControl\tName\tEvent\tArguments\tWait\tComponent_\n"
163                                           "s72\tl255\ti2\tL255\tI2\ts72\n"
164                                           "ServiceControl\tServiceControl\n"
165                                           "ServiceControl\tTestService\t8\t\t0\tservice_comp";
166
167 /* tables for test_continuouscabs */
168 static const CHAR cc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
169                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
170                                        "Component\tComponent\n"
171                                        "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
172                                        "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
173                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
174
175 static const CHAR cc_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
176                                      "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
177                                      "Feature\tFeature\n"
178                                      "feature\t\t\t\t2\t1\tTARGETDIR\t0";
179
180 static const CHAR cc_feature_comp_dat[] = "Feature_\tComponent_\n"
181                                           "s38\ts72\n"
182                                           "FeatureComponents\tFeature_\tComponent_\n"
183                                           "feature\tmaximus\n"
184                                           "feature\taugustus\n"
185                                           "feature\tcaesar";
186
187 static const CHAR cc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
188                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
189                                   "File\tFile\n"
190                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
191                                   "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
192                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12";
193
194 static const CHAR cc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
195                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
196                                    "Media\tDiskId\n"
197                                    "1\t10\t\ttest1.cab\tDISK1\t\n"
198                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
199                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
200
201 static const CHAR co_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
202                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
203                                   "File\tFile\n"
204                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
205                                   "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
206                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
207
208 static const CHAR co_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
209                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
210                                    "Media\tDiskId\n"
211                                    "1\t10\t\ttest1.cab\tDISK1\t\n"
212                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
213                                    "3\t3\t\ttest3.cab\tDISK3\t\n";
214
215 static const CHAR co2_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
216                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
217                                     "Media\tDiskId\n"
218                                     "1\t10\t\ttest1.cab\tDISK1\t\n"
219                                     "2\t12\t\ttest3.cab\tDISK3\t\n"
220                                     "3\t2\t\ttest2.cab\tDISK2\t\n";
221
222 static const CHAR mm_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
223                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
224                                   "File\tFile\n"
225                                   "maximus\tmaximus\tmaximus\t500\t\t\t512\t1\n"
226                                   "augustus\taugustus\taugustus\t500\t\t\t512\t2\n"
227                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
228
229 static const CHAR mm_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
230                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
231                                    "Media\tDiskId\n"
232                                    "1\t3\t\ttest1.cab\tDISK1\t\n";
233
234 static const CHAR ss_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
235                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
236                                    "Media\tDiskId\n"
237                                    "1\t2\t\ttest1.cab\tDISK1\t\n"
238                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
239                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
240
241 /* tables for test_uiLevelFlags */
242 static const CHAR ui_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
243                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
244                                        "Component\tComponent\n"
245                                        "maximus\t\tMSITESTDIR\t0\tHASUIRUN=1\tmaximus\n"
246                                        "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
247                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
248
249 static const CHAR ui_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
250                                            "s72\tS255\tI2\n"
251                                            "InstallUISequence\tAction\n"
252                                            "SetUIProperty\t\t5\n"
253                                            "ExecuteAction\t\t1100\n";
254
255 static const CHAR ui_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
256                                            "s72\ti2\tS64\tS0\tS255\n"
257                                            "CustomAction\tAction\n"
258                                            "SetUIProperty\t51\tHASUIRUN\t1\t\n";
259
260 static const CHAR rof_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
261                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
262                                         "Component\tComponent\n"
263                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n";
264
265 static const CHAR rof_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
266                                       "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
267                                       "Feature\tFeature\n"
268                                       "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
269                                       "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
270
271 static const CHAR rof_feature_comp_dat[] = "Feature_\tComponent_\n"
272                                            "s38\ts72\n"
273                                            "FeatureComponents\tFeature_\tComponent_\n"
274                                            "feature\tmaximus\n"
275                                            "montecristo\tmaximus";
276
277 static const CHAR rof_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
278                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
279                                    "File\tFile\n"
280                                    "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
281
282 static const CHAR rof_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
283                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
284                                     "Media\tDiskId\n"
285                                     "1\t1\t\t\tDISK1\t\n";
286
287 static const CHAR sdp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
288                                                "s72\tS255\tI2\n"
289                                                "InstallExecuteSequence\tAction\n"
290                                                "AllocateRegistrySpace\tNOT Installed\t1550\n"
291                                                "CostFinalize\t\t1000\n"
292                                                "CostInitialize\t\t800\n"
293                                                "FileCost\t\t900\n"
294                                                "InstallFiles\t\t4000\n"
295                                                "InstallFinalize\t\t6600\n"
296                                                "InstallInitialize\t\t1500\n"
297                                                "InstallValidate\t\t1400\n"
298                                                "LaunchConditions\t\t100\n"
299                                                "SetDirProperty\t\t950";
300
301 static const CHAR sdp_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
302                                             "s72\ti2\tS64\tS0\tS255\n"
303                                             "CustomAction\tAction\n"
304                                             "SetDirProperty\t51\tMSITESTDIR\t[CommonFilesFolder]msitest\\\t\n";
305
306 static const CHAR cie_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
307                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
308                                         "Component\tComponent\n"
309                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
310                                         "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
311                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n"
312                                         "gaius\t\tMSITESTDIR\t0\t1\tgaius\n";
313
314 static const CHAR cie_feature_comp_dat[] = "Feature_\tComponent_\n"
315                                            "s38\ts72\n"
316                                            "FeatureComponents\tFeature_\tComponent_\n"
317                                            "feature\tmaximus\n"
318                                            "feature\taugustus\n"
319                                            "feature\tcaesar\n"
320                                            "feature\tgaius";
321
322 static const CHAR cie_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
323                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
324                                    "File\tFile\n"
325                                    "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
326                                    "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
327                                    "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12\n"
328                                    "gaius\tgaius\tgaius\t500\t\t\t8192\t11";
329
330 static const CHAR cie_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
331                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
332                                     "Media\tDiskId\n"
333                                     "1\t1\t\ttest1.cab\tDISK1\t\n"
334                                     "2\t2\t\ttest2.cab\tDISK2\t\n"
335                                     "3\t12\t\ttest3.cab\tDISK3\t\n";
336
337 static const CHAR ci_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
338                                               "s72\tS255\tI2\n"
339                                               "InstallExecuteSequence\tAction\n"
340                                               "CostFinalize\t\t1000\n"
341                                               "CostInitialize\t\t800\n"
342                                               "FileCost\t\t900\n"
343                                               "InstallFiles\t\t4000\n"
344                                               "InstallServices\t\t5000\n"
345                                               "InstallFinalize\t\t6600\n"
346                                               "InstallInitialize\t\t1500\n"
347                                               "RunInstall\t\t1600\n"
348                                               "InstallValidate\t\t1400\n"
349                                               "LaunchConditions\t\t100";
350
351 static const CHAR ci_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
352                                             "s72\ti2\tS64\tS0\tS255\n"
353                                             "CustomAction\tAction\n"
354                                             "RunInstall\t23\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
355
356 static const CHAR ci_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
357                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
358                                        "Component\tComponent\n"
359                                        "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
360
361 static const CHAR ci2_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
362                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
363                                         "Component\tComponent\n"
364                                         "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
365
366 static const CHAR ci2_feature_comp_dat[] = "Feature_\tComponent_\n"
367                                            "s38\ts72\n"
368                                            "FeatureComponents\tFeature_\tComponent_\n"
369                                            "feature\taugustus";
370
371 static const CHAR ci2_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
372                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
373                                    "File\tFile\n"
374                                    "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
375
376 static const CHAR spf_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
377                                             "s72\ti2\tS64\tS0\tS255\n"
378                                             "CustomAction\tAction\n"
379                                             "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n";
380
381 static const CHAR spf_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
382                                                "s72\tS255\tI2\n"
383                                                "InstallExecuteSequence\tAction\n"
384                                                "CostFinalize\t\t1000\n"
385                                                "CostInitialize\t\t800\n"
386                                                "FileCost\t\t900\n"
387                                                "SetFolderProp\t\t950\n"
388                                                "InstallFiles\t\t4000\n"
389                                                "InstallServices\t\t5000\n"
390                                                "InstallFinalize\t\t6600\n"
391                                                "InstallInitialize\t\t1500\n"
392                                                "InstallValidate\t\t1400\n"
393                                                "LaunchConditions\t\t100";
394
395 static const CHAR spf_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
396                                              "s72\tS255\tI2\n"
397                                              "InstallUISequence\tAction\n"
398                                              "CostInitialize\t\t800\n"
399                                              "FileCost\t\t900\n"
400                                              "CostFinalize\t\t1000\n"
401                                              "ExecuteAction\t\t1100\n";
402
403 static const CHAR pp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
404                                               "s72\tS255\tI2\n"
405                                               "InstallExecuteSequence\tAction\n"
406                                               "ValidateProductID\t\t700\n"
407                                               "CostInitialize\t\t800\n"
408                                               "FileCost\t\t900\n"
409                                               "CostFinalize\t\t1000\n"
410                                               "InstallValidate\t\t1400\n"
411                                               "InstallInitialize\t\t1500\n"
412                                               "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
413                                               "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
414                                               "RemoveFiles\t\t3500\n"
415                                               "InstallFiles\t\t4000\n"
416                                               "RegisterUser\t\t6000\n"
417                                               "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
418                                               "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
419                                               "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
420                                               "InstallFinalize\t\t6600";
421
422 static const CHAR tp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
423                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
424                                        "Component\tComponent\n"
425                                        "augustus\t\tMSITESTDIR\t0\tprop=\"val\"\taugustus\n";
426
427 static const CHAR cwd_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
428                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
429                                         "Component\tComponent\n"
430                                         "augustus\t\tMSITESTDIR\t0\t\taugustus\n";
431
432 static const CHAR adm_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
433                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
434                                         "Component\tComponent\n"
435                                         "augustus\t\tMSITESTDIR\t0\tPOSTADMIN=1\taugustus";
436
437 static const CHAR adm_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
438                                             "s72\ti2\tS64\tS0\tS255\n"
439                                             "CustomAction\tAction\n"
440                                             "SetPOSTADMIN\t51\tPOSTADMIN\t1\t\n";
441
442 static const CHAR adm_admin_exec_seq_dat[] = "Action\tCondition\tSequence\n"
443                                              "s72\tS255\tI2\n"
444                                              "AdminExecuteSequence\tAction\n"
445                                              "CostFinalize\t\t1000\n"
446                                              "CostInitialize\t\t800\n"
447                                              "FileCost\t\t900\n"
448                                              "SetPOSTADMIN\t\t950\n"
449                                              "InstallFiles\t\t4000\n"
450                                              "InstallFinalize\t\t6600\n"
451                                              "InstallInitialize\t\t1500\n"
452                                              "InstallValidate\t\t1400\n"
453                                              "LaunchConditions\t\t100";
454
455 static const CHAR amp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
456                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
457                                         "Component\tComponent\n"
458                                         "augustus\t\tMSITESTDIR\t0\tMYPROP=2718\taugustus\n";
459
460 static const CHAR rem_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
461                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
462                                         "Component\tComponent\n"
463                                         "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t0\t\thydrogen\n"
464                                         "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t1\t\thelium\n"
465                                         "lithium\t\tMSITESTDIR\t2\t\tlithium\n";
466
467 static const CHAR rem_feature_comp_dat[] = "Feature_\tComponent_\n"
468                                            "s38\ts72\n"
469                                            "FeatureComponents\tFeature_\tComponent_\n"
470                                            "feature\thydrogen\n"
471                                            "feature\thelium\n"
472                                            "feature\tlithium";
473
474 static const CHAR rem_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
475                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
476                                    "File\tFile\n"
477                                    "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
478                                    "helium\thelium\thelium\t0\t\t\t8192\t1\n"
479                                    "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
480
481 static const CHAR rem_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
482                                                "s72\tS255\tI2\n"
483                                                "InstallExecuteSequence\tAction\n"
484                                                "ValidateProductID\t\t700\n"
485                                                "CostInitialize\t\t800\n"
486                                                "FileCost\t\t900\n"
487                                                "CostFinalize\t\t1000\n"
488                                                "InstallValidate\t\t1400\n"
489                                                "InstallInitialize\t\t1500\n"
490                                                "ProcessComponents\t\t1600\n"
491                                                "UnpublishFeatures\t\t1800\n"
492                                                "RemoveFiles\t\t3500\n"
493                                                "InstallFiles\t\t4000\n"
494                                                "RegisterUser\t\t6000\n"
495                                                "RegisterProduct\t\t6100\n"
496                                                "PublishFeatures\t\t6300\n"
497                                                "PublishProduct\t\t6400\n"
498                                                "InstallFinalize\t\t6600";
499
500 static const CHAR rem_remove_files_dat[] = "FileKey\tComponent_\tFileName\tDirProperty\tInstallMode\n"
501                                            "s72\ts72\tS255\ts72\tI2\n"
502                                            "RemoveFile\tFileKey\n"
503                                            "furlong\thydrogen\tfurlong\tMSITESTDIR\t1\n"
504                                            "firkin\thelium\tfirkin\tMSITESTDIR\t1\n"
505                                            "fortnight\tlithium\tfortnight\tMSITESTDIR\t1\n"
506                                            "becquerel\thydrogen\tbecquerel\tMSITESTDIR\t2\n"
507                                            "dioptre\thelium\tdioptre\tMSITESTDIR\t2\n"
508                                            "attoparsec\tlithium\tattoparsec\tMSITESTDIR\t2\n"
509                                            "storeys\thydrogen\tstoreys\tMSITESTDIR\t3\n"
510                                            "block\thelium\tblock\tMSITESTDIR\t3\n"
511                                            "siriometer\tlithium\tsiriometer\tMSITESTDIR\t3\n";
512
513 static const CHAR mov_move_file_dat[] = "FileKey\tComponent_\tSourceName\tDestName\tSourceFolder\tDestFolder\tOptions\n"
514                                         "s72\ts72\tS255\tS255\tS72\ts72\ti2\n"
515                                         "MoveFile\tFileKey\n"
516                                         "abkhazia\taugustus\tnonexistent\tdest\tSourceDir\tMSITESTDIR\t0\n"
517                                         "bahamas\taugustus\tnonexistent\tdest\tSourceDir\tMSITESTDIR\t1\n"
518                                         "cambodia\taugustus\tcameroon\tcanada\tSourceDir\tMSITESTDIR\t0\n"
519                                         "denmark\taugustus\tdjibouti\tdominica\tSourceDir\tMSITESTDIR\t1\n"
520                                         "ecuador\taugustus\tegypt\telsalvador\tNotAProp\tMSITESTDIR\t1\n"
521                                         "fiji\taugustus\tfinland\tfrance\tSourceDir\tNotAProp\t1\n"
522                                         "gabon\taugustus\tgambia\tgeorgia\tSOURCEFULL\tMSITESTDIR\t1\n"
523                                         "haiti\taugustus\thonduras\thungary\tSourceDir\tDESTFULL\t1\n"
524                                         "iceland\taugustus\tindia\tindonesia\tMSITESTDIR\tMSITESTDIR\t1\n"
525                                         "jamaica\taugustus\tjapan\tjordan\tFILEPATHBAD\tMSITESTDIR\t1\n"
526                                         "kazakhstan\taugustus\t\tkiribati\tFILEPATHGOOD\tMSITESTDIR\t1\n"
527                                         "laos\taugustus\tlatvia\tlebanon\tSourceDir\tMSITESTDIR\t1\n"
528                                         "namibia\taugustus\tnauru\tkiribati\tSourceDir\tMSITESTDIR\t1\n"
529                                         "wildcard\taugustus\tapp*\twildcard\tSourceDir\tMSITESTDIR\t1\n"
530                                         "single\taugustus\tf?o\tsingle\tSourceDir\tMSITESTDIR\t1\n"
531                                         "wildcardnodest\taugustus\tbudd*\t\tSourceDir\tMSITESTDIR\t1\n"
532                                         "singlenodest\taugustus\tb?r\t\tSourceDir\tMSITESTDIR\t1\n";
533
534 typedef struct _msi_table
535 {
536     const CHAR *filename;
537     const CHAR *data;
538     int size;
539 } msi_table;
540
541 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
542
543 static const msi_table tables[] =
544 {
545     ADD_TABLE(component),
546     ADD_TABLE(directory),
547     ADD_TABLE(feature),
548     ADD_TABLE(feature_comp),
549     ADD_TABLE(file),
550     ADD_TABLE(install_exec_seq),
551     ADD_TABLE(media),
552     ADD_TABLE(property),
553     ADD_TABLE(registry),
554     ADD_TABLE(service_install),
555     ADD_TABLE(service_control)
556 };
557
558 static const msi_table cc_tables[] =
559 {
560     ADD_TABLE(cc_component),
561     ADD_TABLE(directory),
562     ADD_TABLE(cc_feature),
563     ADD_TABLE(cc_feature_comp),
564     ADD_TABLE(cc_file),
565     ADD_TABLE(install_exec_seq),
566     ADD_TABLE(cc_media),
567     ADD_TABLE(property),
568 };
569
570 static const msi_table co_tables[] =
571 {
572     ADD_TABLE(cc_component),
573     ADD_TABLE(directory),
574     ADD_TABLE(cc_feature),
575     ADD_TABLE(cc_feature_comp),
576     ADD_TABLE(co_file),
577     ADD_TABLE(install_exec_seq),
578     ADD_TABLE(co_media),
579     ADD_TABLE(property),
580 };
581
582 static const msi_table co2_tables[] =
583 {
584     ADD_TABLE(cc_component),
585     ADD_TABLE(directory),
586     ADD_TABLE(cc_feature),
587     ADD_TABLE(cc_feature_comp),
588     ADD_TABLE(cc_file),
589     ADD_TABLE(install_exec_seq),
590     ADD_TABLE(co2_media),
591     ADD_TABLE(property),
592 };
593
594 static const msi_table mm_tables[] =
595 {
596     ADD_TABLE(cc_component),
597     ADD_TABLE(directory),
598     ADD_TABLE(cc_feature),
599     ADD_TABLE(cc_feature_comp),
600     ADD_TABLE(mm_file),
601     ADD_TABLE(install_exec_seq),
602     ADD_TABLE(mm_media),
603     ADD_TABLE(property),
604 };
605
606 static const msi_table ss_tables[] =
607 {
608     ADD_TABLE(cc_component),
609     ADD_TABLE(directory),
610     ADD_TABLE(cc_feature),
611     ADD_TABLE(cc_feature_comp),
612     ADD_TABLE(cc_file),
613     ADD_TABLE(install_exec_seq),
614     ADD_TABLE(ss_media),
615     ADD_TABLE(property),
616 };
617
618 static const msi_table ui_tables[] =
619 {
620     ADD_TABLE(ui_component),
621     ADD_TABLE(directory),
622     ADD_TABLE(cc_feature),
623     ADD_TABLE(cc_feature_comp),
624     ADD_TABLE(cc_file),
625     ADD_TABLE(install_exec_seq),
626     ADD_TABLE(ui_install_ui_seq),
627     ADD_TABLE(ui_custom_action),
628     ADD_TABLE(cc_media),
629     ADD_TABLE(property),
630 };
631
632 static const msi_table rof_tables[] =
633 {
634     ADD_TABLE(rof_component),
635     ADD_TABLE(directory),
636     ADD_TABLE(rof_feature),
637     ADD_TABLE(rof_feature_comp),
638     ADD_TABLE(rof_file),
639     ADD_TABLE(install_exec_seq),
640     ADD_TABLE(rof_media),
641     ADD_TABLE(property),
642 };
643
644 static const msi_table sdp_tables[] =
645 {
646     ADD_TABLE(rof_component),
647     ADD_TABLE(directory),
648     ADD_TABLE(rof_feature),
649     ADD_TABLE(rof_feature_comp),
650     ADD_TABLE(rof_file),
651     ADD_TABLE(sdp_install_exec_seq),
652     ADD_TABLE(sdp_custom_action),
653     ADD_TABLE(rof_media),
654     ADD_TABLE(property),
655 };
656
657 static const msi_table cie_tables[] =
658 {
659     ADD_TABLE(cie_component),
660     ADD_TABLE(directory),
661     ADD_TABLE(cc_feature),
662     ADD_TABLE(cie_feature_comp),
663     ADD_TABLE(cie_file),
664     ADD_TABLE(install_exec_seq),
665     ADD_TABLE(cie_media),
666     ADD_TABLE(property),
667 };
668
669 static const msi_table ci_tables[] =
670 {
671     ADD_TABLE(ci_component),
672     ADD_TABLE(directory),
673     ADD_TABLE(rof_feature),
674     ADD_TABLE(rof_feature_comp),
675     ADD_TABLE(rof_file),
676     ADD_TABLE(ci_install_exec_seq),
677     ADD_TABLE(rof_media),
678     ADD_TABLE(property),
679     ADD_TABLE(ci_custom_action),
680 };
681
682 static const msi_table ci2_tables[] =
683 {
684     ADD_TABLE(ci2_component),
685     ADD_TABLE(directory),
686     ADD_TABLE(rof_feature),
687     ADD_TABLE(ci2_feature_comp),
688     ADD_TABLE(ci2_file),
689     ADD_TABLE(install_exec_seq),
690     ADD_TABLE(rof_media),
691     ADD_TABLE(property),
692 };
693
694 static const msi_table spf_tables[] =
695 {
696     ADD_TABLE(ci_component),
697     ADD_TABLE(directory),
698     ADD_TABLE(rof_feature),
699     ADD_TABLE(rof_feature_comp),
700     ADD_TABLE(rof_file),
701     ADD_TABLE(spf_install_exec_seq),
702     ADD_TABLE(rof_media),
703     ADD_TABLE(property),
704     ADD_TABLE(spf_custom_action),
705     ADD_TABLE(spf_install_ui_seq),
706 };
707
708 static const msi_table pp_tables[] =
709 {
710     ADD_TABLE(ci_component),
711     ADD_TABLE(directory),
712     ADD_TABLE(rof_feature),
713     ADD_TABLE(rof_feature_comp),
714     ADD_TABLE(rof_file),
715     ADD_TABLE(pp_install_exec_seq),
716     ADD_TABLE(rof_media),
717     ADD_TABLE(property),
718 };
719
720 static const msi_table tp_tables[] =
721 {
722     ADD_TABLE(tp_component),
723     ADD_TABLE(directory),
724     ADD_TABLE(rof_feature),
725     ADD_TABLE(ci2_feature_comp),
726     ADD_TABLE(ci2_file),
727     ADD_TABLE(install_exec_seq),
728     ADD_TABLE(rof_media),
729     ADD_TABLE(property),
730 };
731
732 static const msi_table cwd_tables[] =
733 {
734     ADD_TABLE(cwd_component),
735     ADD_TABLE(directory),
736     ADD_TABLE(rof_feature),
737     ADD_TABLE(ci2_feature_comp),
738     ADD_TABLE(ci2_file),
739     ADD_TABLE(install_exec_seq),
740     ADD_TABLE(rof_media),
741     ADD_TABLE(property),
742 };
743
744 static const msi_table adm_tables[] =
745 {
746     ADD_TABLE(adm_component),
747     ADD_TABLE(directory),
748     ADD_TABLE(rof_feature),
749     ADD_TABLE(ci2_feature_comp),
750     ADD_TABLE(ci2_file),
751     ADD_TABLE(install_exec_seq),
752     ADD_TABLE(rof_media),
753     ADD_TABLE(property),
754     ADD_TABLE(adm_custom_action),
755     ADD_TABLE(adm_admin_exec_seq),
756 };
757
758 static const msi_table amp_tables[] =
759 {
760     ADD_TABLE(amp_component),
761     ADD_TABLE(directory),
762     ADD_TABLE(rof_feature),
763     ADD_TABLE(ci2_feature_comp),
764     ADD_TABLE(ci2_file),
765     ADD_TABLE(install_exec_seq),
766     ADD_TABLE(rof_media),
767     ADD_TABLE(property),
768 };
769
770 static const msi_table rem_tables[] =
771 {
772     ADD_TABLE(rem_component),
773     ADD_TABLE(directory),
774     ADD_TABLE(rof_feature),
775     ADD_TABLE(rem_feature_comp),
776     ADD_TABLE(rem_file),
777     ADD_TABLE(rem_install_exec_seq),
778     ADD_TABLE(rof_media),
779     ADD_TABLE(property),
780     ADD_TABLE(rem_remove_files),
781 };
782
783 static const msi_table mov_tables[] =
784 {
785     ADD_TABLE(cwd_component),
786     ADD_TABLE(directory),
787     ADD_TABLE(rof_feature),
788     ADD_TABLE(ci2_feature_comp),
789     ADD_TABLE(ci2_file),
790     ADD_TABLE(install_exec_seq),
791     ADD_TABLE(rof_media),
792     ADD_TABLE(property),
793     ADD_TABLE(mov_move_file),
794     ADD_TABLE(registry),
795 };
796
797 /* cabinet definitions */
798
799 /* make the max size large so there is only one cab file */
800 #define MEDIA_SIZE          0x7FFFFFFF
801 #define FOLDER_THRESHOLD    900000
802
803 /* the FCI callbacks */
804
805 static void *mem_alloc(ULONG cb)
806 {
807     return HeapAlloc(GetProcessHeap(), 0, cb);
808 }
809
810 static void mem_free(void *memory)
811 {
812     HeapFree(GetProcessHeap(), 0, memory);
813 }
814
815 static BOOL get_next_cabinet(PCCAB pccab, ULONG  cbPrevCab, void *pv)
816 {
817     sprintf(pccab->szCab, pv, pccab->iCab);
818     return TRUE;
819 }
820
821 static long progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
822 {
823     return 0;
824 }
825
826 static int file_placed(PCCAB pccab, char *pszFile, long cbFile,
827                        BOOL fContinuation, void *pv)
828 {
829     return 0;
830 }
831
832 static INT_PTR fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
833 {
834     HANDLE handle;
835     DWORD dwAccess = 0;
836     DWORD dwShareMode = 0;
837     DWORD dwCreateDisposition = OPEN_EXISTING;
838     
839     dwAccess = GENERIC_READ | GENERIC_WRITE;
840     /* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
841     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
842
843     if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
844         dwCreateDisposition = OPEN_EXISTING;
845     else
846         dwCreateDisposition = CREATE_NEW;
847
848     handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
849                          dwCreateDisposition, 0, NULL);
850
851     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
852
853     return (INT_PTR)handle;
854 }
855
856 static UINT fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
857 {
858     HANDLE handle = (HANDLE)hf;
859     DWORD dwRead;
860     BOOL res;
861     
862     res = ReadFile(handle, memory, cb, &dwRead, NULL);
863     ok(res, "Failed to ReadFile\n");
864
865     return dwRead;
866 }
867
868 static UINT fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
869 {
870     HANDLE handle = (HANDLE)hf;
871     DWORD dwWritten;
872     BOOL res;
873
874     res = WriteFile(handle, memory, cb, &dwWritten, NULL);
875     ok(res, "Failed to WriteFile\n");
876
877     return dwWritten;
878 }
879
880 static int fci_close(INT_PTR hf, int *err, void *pv)
881 {
882     HANDLE handle = (HANDLE)hf;
883     ok(CloseHandle(handle), "Failed to CloseHandle\n");
884
885     return 0;
886 }
887
888 static long fci_seek(INT_PTR hf, long dist, int seektype, int *err, void *pv)
889 {
890     HANDLE handle = (HANDLE)hf;
891     DWORD ret;
892     
893     ret = SetFilePointer(handle, dist, NULL, seektype);
894     ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
895
896     return ret;
897 }
898
899 static int fci_delete(char *pszFile, int *err, void *pv)
900 {
901     BOOL ret = DeleteFileA(pszFile);
902     ok(ret, "Failed to DeleteFile %s\n", pszFile);
903
904     return 0;
905 }
906
907 static void init_functionpointers(void)
908 {
909     HMODULE hmsi = GetModuleHandleA("msi.dll");
910
911 #define GET_PROC(func) \
912     p ## func = (void*)GetProcAddress(hmsi, #func); \
913     if(!p ## func) \
914       trace("GetProcAddress(%s) failed\n", #func);
915
916     GET_PROC(MsiQueryComponentStateA);
917     GET_PROC(MsiSourceListGetInfoA);
918
919 #undef GET_PROC
920 }
921
922 static BOOL check_record(MSIHANDLE rec, UINT field, LPCSTR val)
923 {
924     CHAR buffer[0x20];
925     UINT r;
926     DWORD sz;
927
928     sz = sizeof buffer;
929     r = MsiRecordGetString(rec, field, buffer, &sz);
930     return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
931 }
932
933 static BOOL get_temp_file(char *pszTempName, int cbTempName, void *pv)
934 {
935     LPSTR tempname;
936
937     tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
938     GetTempFileNameA(".", "xx", 0, tempname);
939
940     if (tempname && (strlen(tempname) < (unsigned)cbTempName))
941     {
942         lstrcpyA(pszTempName, tempname);
943         HeapFree(GetProcessHeap(), 0, tempname);
944         return TRUE;
945     }
946
947     HeapFree(GetProcessHeap(), 0, tempname);
948
949     return FALSE;
950 }
951
952 static INT_PTR get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
953                              USHORT *pattribs, int *err, void *pv)
954 {
955     BY_HANDLE_FILE_INFORMATION finfo;
956     FILETIME filetime;
957     HANDLE handle;
958     DWORD attrs;
959     BOOL res;
960
961     handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
962                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
963
964     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
965
966     res = GetFileInformationByHandle(handle, &finfo);
967     ok(res, "Expected GetFileInformationByHandle to succeed\n");
968    
969     FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
970     FileTimeToDosDateTime(&filetime, pdate, ptime);
971
972     attrs = GetFileAttributes(pszName);
973     ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
974
975     return (INT_PTR)handle;
976 }
977
978 static BOOL add_file(HFCI hfci, const char *file, TCOMP compress)
979 {
980     char path[MAX_PATH];
981     char filename[MAX_PATH];
982
983     lstrcpyA(path, CURR_DIR);
984     lstrcatA(path, "\\");
985     lstrcatA(path, file);
986
987     lstrcpyA(filename, file);
988
989     return FCIAddFile(hfci, path, filename, FALSE, get_next_cabinet,
990                       progress, get_open_info, compress);
991 }
992
993 static void set_cab_parameters(PCCAB pCabParams, const CHAR *name, DWORD max_size)
994 {
995     ZeroMemory(pCabParams, sizeof(CCAB));
996
997     pCabParams->cb = max_size;
998     pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
999     pCabParams->setID = 0xbeef;
1000     pCabParams->iCab = 1;
1001     lstrcpyA(pCabParams->szCabPath, CURR_DIR);
1002     lstrcatA(pCabParams->szCabPath, "\\");
1003     lstrcpyA(pCabParams->szCab, name);
1004 }
1005
1006 static void create_cab_file(const CHAR *name, DWORD max_size, const CHAR *files)
1007 {
1008     CCAB cabParams;
1009     LPCSTR ptr;
1010     HFCI hfci;
1011     ERF erf;
1012     BOOL res;
1013
1014     set_cab_parameters(&cabParams, name, max_size);
1015
1016     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1017                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1018                       get_temp_file, &cabParams, NULL);
1019
1020     ok(hfci != NULL, "Failed to create an FCI context\n");
1021
1022     ptr = files;
1023     while (*ptr)
1024     {
1025         res = add_file(hfci, ptr, tcompTYPE_MSZIP);
1026         ok(res, "Failed to add file: %s\n", ptr);
1027         ptr += lstrlen(ptr) + 1;
1028     }
1029
1030     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1031     ok(res, "Failed to flush the cabinet\n");
1032
1033     res = FCIDestroy(hfci);
1034     ok(res, "Failed to destroy the cabinet\n");
1035 }
1036
1037 static BOOL get_program_files_dir(LPSTR buf, LPSTR buf2)
1038 {
1039     HKEY hkey;
1040     DWORD type, size;
1041
1042     if (RegOpenKey(HKEY_LOCAL_MACHINE,
1043                    "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
1044         return FALSE;
1045
1046     size = MAX_PATH;
1047     if (RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)buf, &size)) {
1048         RegCloseKey(hkey);
1049         return FALSE;
1050     }
1051
1052     size = MAX_PATH;
1053     if (RegQueryValueExA(hkey, "CommonFilesDir", 0, &type, (LPBYTE)buf2, &size)) {
1054         RegCloseKey(hkey);
1055         return FALSE;
1056     }
1057
1058     RegCloseKey(hkey);
1059     return TRUE;
1060 }
1061
1062 static void create_file(const CHAR *name, DWORD size)
1063 {
1064     HANDLE file;
1065     DWORD written, left;
1066
1067     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1068     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
1069     WriteFile(file, name, strlen(name), &written, NULL);
1070     WriteFile(file, "\n", strlen("\n"), &written, NULL);
1071
1072     left = size - lstrlen(name) - 1;
1073
1074     SetFilePointer(file, left, NULL, FILE_CURRENT);
1075     SetEndOfFile(file);
1076     
1077     CloseHandle(file);
1078 }
1079
1080 static void create_test_files(void)
1081 {
1082     CreateDirectoryA("msitest", NULL);
1083     create_file("msitest\\one.txt", 100);
1084     CreateDirectoryA("msitest\\first", NULL);
1085     create_file("msitest\\first\\two.txt", 100);
1086     CreateDirectoryA("msitest\\second", NULL);
1087     create_file("msitest\\second\\three.txt", 100);
1088
1089     create_file("four.txt", 100);
1090     create_file("five.txt", 100);
1091     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1092
1093     create_file("msitest\\filename", 100);
1094     create_file("msitest\\service.exe", 100);
1095
1096     DeleteFileA("four.txt");
1097     DeleteFileA("five.txt");
1098 }
1099
1100 static BOOL delete_pf(const CHAR *rel_path, BOOL is_file)
1101 {
1102     CHAR path[MAX_PATH];
1103
1104     lstrcpyA(path, PROG_FILES_DIR);
1105     lstrcatA(path, "\\");
1106     lstrcatA(path, rel_path);
1107
1108     if (is_file)
1109         return DeleteFileA(path);
1110     else
1111         return RemoveDirectoryA(path);
1112 }
1113
1114 static BOOL delete_cf(const CHAR *rel_path, BOOL is_file)
1115 {
1116     CHAR path[MAX_PATH];
1117
1118     lstrcpyA(path, COMMON_FILES_DIR);
1119     lstrcatA(path, "\\");
1120     lstrcatA(path, rel_path);
1121
1122     if (is_file)
1123         return DeleteFileA(path);
1124     else
1125         return RemoveDirectoryA(path);
1126 }
1127
1128 static void delete_test_files(void)
1129 {
1130     DeleteFileA("msitest.msi");
1131     DeleteFileA("msitest.cab");
1132     DeleteFileA("msitest\\second\\three.txt");
1133     DeleteFileA("msitest\\first\\two.txt");
1134     DeleteFileA("msitest\\one.txt");
1135     DeleteFileA("msitest\\service.exe");
1136     DeleteFileA("msitest\\filename");
1137     RemoveDirectoryA("msitest\\second");
1138     RemoveDirectoryA("msitest\\first");
1139     RemoveDirectoryA("msitest");
1140 }
1141
1142 static void write_file(const CHAR *filename, const char *data, int data_size)
1143 {
1144     DWORD size;
1145
1146     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
1147                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1148
1149     WriteFile(hf, data, data_size, &size, NULL);
1150     CloseHandle(hf);
1151 }
1152
1153 static void write_msi_summary_info(MSIHANDLE db)
1154 {
1155     MSIHANDLE summary;
1156     UINT r;
1157
1158     r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
1159     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1160
1161     r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, ";1033");
1162     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1163
1164     r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1165                                    "{004757CA-5092-49c2-AD20-28E1CE0DF5F2}");
1166     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1167
1168     r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
1169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1170
1171     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 0, NULL, NULL);
1172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1173
1174     r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
1175     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1176
1177     /* write the summary changes back to the stream */
1178     r = MsiSummaryInfoPersist(summary);
1179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1180
1181     MsiCloseHandle(summary);
1182 }
1183
1184 static void create_database(const CHAR *name, const msi_table *tables, int num_tables)
1185 {
1186     MSIHANDLE db;
1187     UINT r;
1188     int j;
1189
1190     r = MsiOpenDatabaseA(name, MSIDBOPEN_CREATE, &db);
1191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1192
1193     /* import the tables into the database */
1194     for (j = 0; j < num_tables; j++)
1195     {
1196         const msi_table *table = &tables[j];
1197
1198         write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
1199
1200         r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
1201         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1202
1203         DeleteFileA(table->filename);
1204     }
1205
1206     write_msi_summary_info(db);
1207
1208     r = MsiDatabaseCommit(db);
1209     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1210
1211     MsiCloseHandle(db);
1212 }
1213
1214 static void check_service_is_installed(void)
1215 {
1216     SC_HANDLE scm, service;
1217     BOOL res;
1218
1219     scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1220     ok(scm != NULL, "Failed to open the SC Manager\n");
1221
1222     service = OpenService(scm, "TestService", SC_MANAGER_ALL_ACCESS);
1223     ok(service != NULL, "Failed to open TestService\n");
1224
1225     res = DeleteService(service);
1226     ok(res, "Failed to delete TestService\n");
1227 }
1228
1229 static void test_MsiInstallProduct(void)
1230 {
1231     UINT r;
1232     CHAR path[MAX_PATH];
1233     LONG res;
1234     HKEY hkey;
1235     DWORD num, size, type;
1236
1237     create_test_files();
1238     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1239
1240     r = MsiInstallProductA(msifile, NULL);
1241     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1242
1243     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
1244     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
1245     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
1246     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
1247     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
1248     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
1249     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
1250     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
1251     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
1252     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
1253     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
1254     ok(delete_pf("msitest", FALSE), "File not installed\n");
1255
1256     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
1257     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1258
1259     size = MAX_PATH;
1260     type = REG_SZ;
1261     res = RegQueryValueExA(hkey, "Name", NULL, &type, (LPBYTE)path, &size);
1262     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1263     ok(!lstrcmpA(path, "imaname"), "Expected imaname, got %s\n", path);
1264
1265     size = MAX_PATH;
1266     type = REG_SZ;
1267     res = RegQueryValueExA(hkey, "blah", NULL, &type, (LPBYTE)path, &size);
1268     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
1269
1270     size = sizeof(num);
1271     type = REG_DWORD;
1272     res = RegQueryValueExA(hkey, "number", NULL, &type, (LPBYTE)&num, &size);
1273     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1274     ok(num == 314, "Expected 314, got %d\n", num);
1275
1276     size = MAX_PATH;
1277     type = REG_SZ;
1278     res = RegQueryValueExA(hkey, "OrderTestName", NULL, &type, (LPBYTE)path, &size);
1279     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1280     ok(!lstrcmpA(path, "OrderTestValue"), "Expected imaname, got %s\n", path);
1281
1282     check_service_is_installed();
1283
1284     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
1285
1286     delete_test_files();
1287 }
1288
1289 static void test_MsiSetComponentState(void)
1290 {
1291     INSTALLSTATE installed, action;
1292     MSIHANDLE package;
1293     char path[MAX_PATH];
1294     UINT r;
1295
1296     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1297
1298     CoInitialize(NULL);
1299
1300     lstrcpy(path, CURR_DIR);
1301     lstrcat(path, "\\");
1302     lstrcat(path, msifile);
1303
1304     r = MsiOpenPackage(path, &package);
1305     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1306
1307     r = MsiDoAction(package, "CostInitialize");
1308     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1309
1310     r = MsiDoAction(package, "FileCost");
1311     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1312
1313     r = MsiDoAction(package, "CostFinalize");
1314     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1315
1316     r = MsiGetComponentState(package, "dangler", &installed, &action);
1317     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1318     ok(installed == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", installed);
1319     ok(action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1320
1321     r = MsiSetComponentState(package, "dangler", INSTALLSTATE_SOURCE);
1322     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1323
1324     MsiCloseHandle(package);
1325     CoUninitialize();
1326
1327     DeleteFileA(msifile);
1328 }
1329
1330 static void test_packagecoltypes(void)
1331 {
1332     MSIHANDLE hdb, view, rec;
1333     char path[MAX_PATH];
1334     LPCSTR query;
1335     UINT r, count;
1336
1337     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1338
1339     CoInitialize(NULL);
1340
1341     lstrcpy(path, CURR_DIR);
1342     lstrcat(path, "\\");
1343     lstrcat(path, msifile);
1344
1345     r = MsiOpenDatabase(path, MSIDBOPEN_READONLY, &hdb);
1346     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1347
1348     query = "SELECT * FROM `Media`";
1349     r = MsiDatabaseOpenView( hdb, query, &view );
1350     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1351
1352     r = MsiViewGetColumnInfo( view, MSICOLINFO_NAMES, &rec );
1353     count = MsiRecordGetFieldCount( rec );
1354     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1355     ok(count == 6, "Expected 6, got %d\n", count);
1356     ok(check_record(rec, 1, "DiskId"), "wrong column label\n");
1357     ok(check_record(rec, 2, "LastSequence"), "wrong column label\n");
1358     ok(check_record(rec, 3, "DiskPrompt"), "wrong column label\n");
1359     ok(check_record(rec, 4, "Cabinet"), "wrong column label\n");
1360     ok(check_record(rec, 5, "VolumeLabel"), "wrong column label\n");
1361     ok(check_record(rec, 6, "Source"), "wrong column label\n");
1362     MsiCloseHandle(rec);
1363
1364     r = MsiViewGetColumnInfo( view, MSICOLINFO_TYPES, &rec );
1365     count = MsiRecordGetFieldCount( rec );
1366     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1367     ok(count == 6, "Expected 6, got %d\n", count);
1368     ok(check_record(rec, 1, "i2"), "wrong column label\n");
1369     ok(check_record(rec, 2, "i4"), "wrong column label\n");
1370     ok(check_record(rec, 3, "L64"), "wrong column label\n");
1371     ok(check_record(rec, 4, "S255"), "wrong column label\n");
1372     ok(check_record(rec, 5, "S32"), "wrong column label\n");
1373     ok(check_record(rec, 6, "S72"), "wrong column label\n");
1374
1375     MsiCloseHandle(rec);
1376     MsiCloseHandle(view);
1377     MsiCloseHandle(hdb);
1378     DeleteFile(msifile);
1379 }
1380
1381 static void create_cc_test_files(void)
1382 {
1383     CCAB cabParams;
1384     HFCI hfci;
1385     ERF erf;
1386     static CHAR cab_context[] = "test%d.cab";
1387     BOOL res;
1388
1389     create_file("maximus", 500);
1390     create_file("augustus", 50000);
1391     create_file("caesar", 500);
1392
1393     set_cab_parameters(&cabParams, "test1.cab", 200);
1394
1395     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1396                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1397                       get_temp_file, &cabParams, cab_context);
1398     ok(hfci != NULL, "Failed to create an FCI context\n");
1399
1400     res = add_file(hfci, "maximus", tcompTYPE_MSZIP);
1401     ok(res, "Failed to add file maximus\n");
1402
1403     res = add_file(hfci, "augustus", tcompTYPE_MSZIP);
1404     ok(res, "Failed to add file augustus\n");
1405
1406     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1407     ok(res, "Failed to flush the cabinet\n");
1408
1409     res = FCIDestroy(hfci);
1410     ok(res, "Failed to destroy the cabinet\n");
1411
1412     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1413
1414     DeleteFile("maximus");
1415     DeleteFile("augustus");
1416     DeleteFile("caesar");
1417 }
1418
1419 static void delete_cab_files(void)
1420 {
1421     SHFILEOPSTRUCT shfl;
1422     CHAR path[MAX_PATH+10];
1423
1424     lstrcpyA(path, CURR_DIR);
1425     lstrcatA(path, "\\*.cab");
1426     path[strlen(path) + 1] = '\0';
1427
1428     shfl.hwnd = NULL;
1429     shfl.wFunc = FO_DELETE;
1430     shfl.pFrom = path;
1431     shfl.pTo = NULL;
1432     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
1433
1434     SHFileOperation(&shfl);
1435 }
1436
1437 static void test_continuouscabs(void)
1438 {
1439     UINT r;
1440
1441     create_cc_test_files();
1442     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1443
1444     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1445
1446     r = MsiInstallProductA(msifile, NULL);
1447     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1448     todo_wine
1449     {
1450         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1451         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1452         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1453     }
1454     ok(delete_pf("msitest", FALSE), "File not installed\n");
1455
1456     delete_cab_files();
1457     DeleteFile(msifile);
1458 }
1459
1460 static void test_caborder(void)
1461 {
1462     UINT r;
1463
1464     create_file("imperator", 100);
1465     create_file("maximus", 500);
1466     create_file("augustus", 50000);
1467     create_file("caesar", 500);
1468
1469     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1470
1471     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1472
1473     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
1474     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
1475     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1476
1477     r = MsiInstallProductA(msifile, NULL);
1478     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1479     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1480     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1481     todo_wine
1482     {
1483         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1484         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1485     }
1486
1487     delete_cab_files();
1488
1489     create_cab_file("test1.cab", MEDIA_SIZE, "imperator\0");
1490     create_cab_file("test2.cab", MEDIA_SIZE, "maximus\0augustus\0");
1491     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1492
1493     r = MsiInstallProductA(msifile, NULL);
1494     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1495     ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1496     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1497     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1498     todo_wine
1499     {
1500         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1501     }
1502
1503     delete_cab_files();
1504     DeleteFile(msifile);
1505
1506     create_cc_test_files();
1507     create_database(msifile, co_tables, sizeof(co_tables) / sizeof(msi_table));
1508
1509     r = MsiInstallProductA(msifile, NULL);
1510     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1511     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1512     ok(!delete_pf("msitest", FALSE), "File is installed\n");
1513     todo_wine
1514     {
1515         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1516         ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1517     }
1518
1519     delete_cab_files();
1520     DeleteFile(msifile);
1521
1522     create_cc_test_files();
1523     create_database(msifile, co2_tables, sizeof(co2_tables) / sizeof(msi_table));
1524
1525     r = MsiInstallProductA(msifile, NULL);
1526     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1527     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1528     todo_wine
1529     {
1530         ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1531         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1532         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1533     }
1534
1535     delete_cab_files();
1536     DeleteFile("imperator");
1537     DeleteFile("maximus");
1538     DeleteFile("augustus");
1539     DeleteFile("caesar");
1540     DeleteFile(msifile);
1541 }
1542
1543 static void test_mixedmedia(void)
1544 {
1545     UINT r;
1546
1547     CreateDirectoryA("msitest", NULL);
1548     create_file("msitest\\maximus", 500);
1549     create_file("msitest\\augustus", 500);
1550     create_file("caesar", 500);
1551
1552     create_database(msifile, mm_tables, sizeof(mm_tables) / sizeof(msi_table));
1553
1554     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1555
1556     create_cab_file("test1.cab", MEDIA_SIZE, "caesar\0");
1557
1558     r = MsiInstallProductA(msifile, NULL);
1559     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1560     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1561     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1562     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1563     ok(delete_pf("msitest", FALSE), "File not installed\n");
1564
1565     /* Delete the files in the temp (current) folder */
1566     DeleteFile("msitest\\maximus");
1567     DeleteFile("msitest\\augustus");
1568     RemoveDirectory("msitest");
1569     DeleteFile("caesar");
1570     DeleteFile("test1.cab");
1571     DeleteFile(msifile);
1572 }
1573
1574 static void test_samesequence(void)
1575 {
1576     UINT r;
1577
1578     create_cc_test_files();
1579     create_database(msifile, ss_tables, sizeof(ss_tables) / sizeof(msi_table));
1580
1581     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1582
1583     r = MsiInstallProductA(msifile, NULL);
1584     todo_wine
1585     {
1586         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1587         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1588         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1589     }
1590     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1591     ok(delete_pf("msitest", FALSE), "File not installed\n");
1592
1593     delete_cab_files();
1594     DeleteFile(msifile);
1595 }
1596
1597 static void test_uiLevelFlags(void)
1598 {
1599     UINT r;
1600
1601     create_cc_test_files();
1602     create_database(msifile, ui_tables, sizeof(ui_tables) / sizeof(msi_table));
1603
1604     MsiSetInternalUI(INSTALLUILEVEL_NONE | INSTALLUILEVEL_SOURCERESONLY, NULL);
1605
1606     r = MsiInstallProductA(msifile, NULL);
1607     ok(!delete_pf("msitest\\maximus", TRUE), "UI install occurred, but execute-only was requested.\n");
1608     todo_wine
1609     {
1610         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1611         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1612     }
1613     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1614     ok(delete_pf("msitest", FALSE), "File not installed\n");
1615
1616     delete_cab_files();
1617     DeleteFile(msifile);
1618 }
1619
1620 static BOOL file_matches(LPSTR path)
1621 {
1622     CHAR buf[MAX_PATH];
1623     HANDLE file;
1624     DWORD size;
1625
1626     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1627                       NULL, OPEN_EXISTING, 0, NULL);
1628
1629     ZeroMemory(buf, MAX_PATH);
1630     ReadFile(file, buf, 15, &size, NULL);
1631     CloseHandle(file);
1632
1633     return !lstrcmp(buf, "msitest\\maximus");
1634 }
1635
1636 static void test_readonlyfile(void)
1637 {
1638     UINT r;
1639     DWORD size;
1640     HANDLE file;
1641     CHAR path[MAX_PATH];
1642
1643     CreateDirectoryA("msitest", NULL);
1644     create_file("msitest\\maximus", 500);
1645     create_database(msifile, rof_tables, sizeof(rof_tables) / sizeof(msi_table));
1646
1647     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1648
1649     lstrcpy(path, PROG_FILES_DIR);
1650     lstrcat(path, "\\msitest");
1651     CreateDirectory(path, NULL);
1652
1653     lstrcat(path, "\\maximus");
1654     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1655                       NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
1656
1657     WriteFile(file, "readonlyfile", 20, &size, NULL);
1658     CloseHandle(file);
1659
1660     r = MsiInstallProductA(msifile, NULL);
1661     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1662     ok(file_matches(path), "Expected file to be overwritten\n");
1663     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1664     ok(delete_pf("msitest", FALSE), "File not installed\n");
1665
1666     /* Delete the files in the temp (current) folder */
1667     DeleteFile("msitest\\maximus");
1668     RemoveDirectory("msitest");
1669     DeleteFile(msifile);
1670 }
1671
1672 static void test_setdirproperty(void)
1673 {
1674     UINT r;
1675
1676     CreateDirectoryA("msitest", NULL);
1677     create_file("msitest\\maximus", 500);
1678     create_database(msifile, sdp_tables, sizeof(sdp_tables) / sizeof(msi_table));
1679
1680     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1681
1682     r = MsiInstallProductA(msifile, NULL);
1683     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1684     ok(delete_cf("msitest\\maximus", TRUE), "File not installed\n");
1685     ok(delete_cf("msitest", FALSE), "File not installed\n");
1686
1687     /* Delete the files in the temp (current) folder */
1688     DeleteFile(msifile);
1689     DeleteFile("msitest\\maximus");
1690     RemoveDirectory("msitest");
1691 }
1692
1693 static void test_cabisextracted(void)
1694 {
1695     UINT r;
1696
1697     CreateDirectoryA("msitest", NULL);
1698     create_file("msitest\\gaius", 500);
1699     create_file("maximus", 500);
1700     create_file("augustus", 500);
1701     create_file("caesar", 500);
1702
1703     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
1704     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
1705     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1706
1707     create_database(msifile, cie_tables, sizeof(cie_tables) / sizeof(msi_table));
1708
1709     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1710
1711     r = MsiInstallProductA(msifile, NULL);
1712     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1713     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1714     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1715     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1716     ok(delete_pf("msitest\\gaius", TRUE), "File not installed\n");
1717     ok(delete_pf("msitest", FALSE), "File not installed\n");
1718
1719     /* Delete the files in the temp (current) folder */
1720     delete_cab_files();
1721     DeleteFile(msifile);
1722     DeleteFile("maximus");
1723     DeleteFile("augustus");
1724     DeleteFile("caesar");
1725     DeleteFile("msitest\\gaius");
1726     RemoveDirectory("msitest");
1727 }
1728
1729 static void test_concurrentinstall(void)
1730 {
1731     UINT r;
1732     CHAR path[MAX_PATH];
1733
1734     CreateDirectoryA("msitest", NULL);
1735     CreateDirectoryA("msitest\\msitest", NULL);
1736     create_file("msitest\\maximus", 500);
1737     create_file("msitest\\msitest\\augustus", 500);
1738
1739     create_database(msifile, ci_tables, sizeof(ci_tables) / sizeof(msi_table));
1740
1741     lstrcpyA(path, CURR_DIR);
1742     lstrcatA(path, "\\msitest\\concurrent.msi");
1743     create_database(path, ci2_tables, sizeof(ci2_tables) / sizeof(msi_table));
1744
1745     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
1746
1747     r = MsiInstallProductA(msifile, NULL);
1748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1749     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1750     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1751     ok(delete_pf("msitest", FALSE), "File not installed\n");
1752
1753     /* Delete the files in the temp (current) folder */
1754     DeleteFile(msifile);
1755     DeleteFile(path);
1756     DeleteFile("msitest\\msitest\\augustus");
1757     DeleteFile("msitest\\maximus");
1758     RemoveDirectory("msitest\\msitest");
1759     RemoveDirectory("msitest");
1760 }
1761
1762 static void test_setpropertyfolder(void)
1763 {
1764     UINT r;
1765
1766     CreateDirectoryA("msitest", NULL);
1767     create_file("msitest\\maximus", 500);
1768
1769     create_database(msifile, spf_tables, sizeof(spf_tables) / sizeof(msi_table));
1770
1771     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
1772
1773     r = MsiInstallProductA(msifile, NULL);
1774     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1775     ok(delete_pf("msitest\\added\\maximus", TRUE), "File not installed\n");
1776     ok(delete_pf("msitest\\added", FALSE), "File not installed\n");
1777     ok(delete_pf("msitest", FALSE), "File not installed\n");
1778
1779     /* Delete the files in the temp (current) folder */
1780     DeleteFile(msifile);
1781     DeleteFile("msitest\\maximus");
1782     RemoveDirectory("msitest");
1783 }
1784
1785 static BOOL file_exists(LPCSTR file)
1786 {
1787     return GetFileAttributes(file) != INVALID_FILE_ATTRIBUTES;
1788 }
1789
1790 static BOOL pf_exists(LPCSTR file)
1791 {
1792     CHAR path[MAX_PATH];
1793
1794     lstrcpyA(path, PROG_FILES_DIR);
1795     lstrcatA(path, "\\");
1796     lstrcatA(path, file);
1797
1798     return file_exists(path);
1799 }
1800
1801 static void delete_pfmsitest_files(void)
1802 {
1803     SHFILEOPSTRUCT shfl;
1804     CHAR path[MAX_PATH+11];
1805
1806     lstrcpyA(path, PROG_FILES_DIR);
1807     lstrcatA(path, "\\msitest\\*");
1808     path[strlen(path) + 1] = '\0';
1809
1810     shfl.hwnd = NULL;
1811     shfl.wFunc = FO_DELETE;
1812     shfl.pFrom = path;
1813     shfl.pTo = NULL;
1814     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
1815
1816     SHFileOperation(&shfl);
1817
1818     lstrcpyA(path, PROG_FILES_DIR);
1819     lstrcatA(path, "\\msitest");
1820     RemoveDirectoryA(path);
1821 }
1822
1823 static void test_publish(void)
1824 {
1825     UINT r;
1826     INSTALLSTATE state;
1827     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
1828
1829     CreateDirectoryA("msitest", NULL);
1830     create_file("msitest\\maximus", 500);
1831
1832     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
1833
1834     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
1835
1836     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1837     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1838
1839     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1840     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1841
1842     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1843     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1844
1845     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1846                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1847     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1848     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1849
1850     /* nothing published */
1851     r = MsiInstallProductA(msifile, NULL);
1852     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1853     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1854     ok(pf_exists("msitest"), "File not installed\n");
1855
1856     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1857     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1858
1859     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1860     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1861
1862     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1863     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1864
1865     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1866                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1867     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1868     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1869
1870     /* install again */
1871     r = MsiInstallProductA(msifile, NULL);
1872     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1873     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1874     ok(pf_exists("msitest"), "File not installed\n");
1875
1876     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1877     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1878
1879     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1880     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1881
1882     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1883     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1884
1885     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1886                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1887     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1888     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1889
1890     /* try to uninstall */
1891     r = MsiInstallProductA(msifile, "REMOVE=ALL");
1892     todo_wine
1893     {
1894         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1895     }
1896     ok(pf_exists("msitest\\maximus"), "File deleted\n");
1897     ok(pf_exists("msitest"), "File deleted\n");
1898
1899     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1900     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1901
1902     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1903     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1904
1905     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1906     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1907
1908     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1909                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1910     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1911     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1912
1913     /* PublishProduct */
1914     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
1915     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1916     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1917     ok(pf_exists("msitest"), "File not installed\n");
1918
1919     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1920     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1921
1922     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1923     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1924
1925     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1926                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1927     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1928     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1929
1930     /* try to uninstall after PublishProduct */
1931     r = MsiInstallProductA(msifile, "REMOVE=ALL");
1932     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1933     ok(pf_exists("msitest\\maximus"), "File deleted\n");
1934     ok(pf_exists("msitest"), "File deleted\n");
1935
1936     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1937     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1938
1939     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1940     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1941
1942     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1943     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1944
1945     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1946                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1947     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1948     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1949
1950     /* PublishProduct and RegisterProduct */
1951     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1");
1952     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1953     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1954     ok(pf_exists("msitest"), "File not installed\n");
1955
1956     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1957     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1958
1959     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1960     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1961
1962     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1963     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1964
1965     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1966                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1967     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1968     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1969
1970     /* try it again */
1971     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1");
1972     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1973     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1974     ok(pf_exists("msitest"), "File not installed\n");
1975
1976     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1977     todo_wine
1978     {
1979         ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1980     }
1981
1982     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1983     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1984
1985     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1986     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1987
1988     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1989                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1990     todo_wine
1991     {
1992         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1993     }
1994     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1995
1996     /* uninstall has a problem with this */
1997     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
1998     todo_wine
1999     {
2000         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2001     }
2002     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2003     ok(pf_exists("msitest"), "File deleted\n");
2004
2005     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2006     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2007
2008     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2009     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2010
2011     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2012                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2013     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2014     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2015
2016     /* PublishProduct and RegisterProduct and ProcessComponents */
2017     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1 PROCESS_COMPONENTS=1");
2018     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2019     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2020     ok(pf_exists("msitest"), "File not installed\n");
2021
2022     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2023     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2024
2025     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2026     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2027
2028     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2029     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2030
2031     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2032                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2033     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2034     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2035
2036     /* complete uninstall */
2037     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2039     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2040     ok(pf_exists("msitest"), "File deleted\n");
2041
2042     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2043     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2044
2045     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2046     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2047
2048     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2049     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2050
2051     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2052                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2053     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2054     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2055
2056     /* PublishProduct, RegisterProduct, ProcessComponents, PublishFeatures */
2057     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1 PROCESS_COMPONENTS=1 PUBLISH_FEATURES=1");
2058     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2059     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2060     ok(pf_exists("msitest"), "File not installed\n");
2061
2062     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2063     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2064
2065     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2066     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2067
2068     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2069     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2070
2071     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2072                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2073     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2074     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2075
2076     /* complete uninstall */
2077     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2078     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2079     todo_wine
2080     {
2081         ok(!pf_exists("msitest\\maximus"), "File deleted\n");
2082         ok(!pf_exists("msitest"), "File deleted\n");
2083     }
2084
2085     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2086     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2087
2088     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");\
2089     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2090
2091     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2092     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2093
2094     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2095                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2096     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2097     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2098
2099     /* complete install */
2100     r = MsiInstallProductA(msifile, "FULL=1");
2101     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2102     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2103     ok(pf_exists("msitest"), "File not installed\n");
2104
2105     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2106     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2107
2108     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2109     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2110
2111     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2112     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2113
2114     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2115                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2116     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2117     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2118
2119     /* no UnpublishFeatures */
2120     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2121     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2122     todo_wine
2123     {
2124         ok(!pf_exists("msitest\\maximus"), "File deleted\n");
2125         ok(!pf_exists("msitest"), "File deleted\n");
2126     }
2127
2128     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2129     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2130
2131     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2132     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2133
2134     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2135     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2136
2137     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2138                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2139     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2140     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2141
2142     /* complete install */
2143     r = MsiInstallProductA(msifile, "FULL=1");
2144     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2145     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2146     ok(pf_exists("msitest"), "File not installed\n");
2147
2148     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2149     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2150
2151     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2152     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2153
2154     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2155     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2156
2157     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2158                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2159     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2160     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2161
2162     /* UnpublishFeatures, only feature removed.  Only works when entire product is removed */
2163     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature");
2164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2165     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2166     ok(pf_exists("msitest"), "File deleted\n");
2167
2168     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2169     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2170
2171     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2172     todo_wine
2173     {
2174         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2175     }
2176
2177     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2178     todo_wine
2179     {
2180         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2181     }
2182
2183     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2184                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2185     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2186     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2187
2188     /* complete install */
2189     r = MsiInstallProductA(msifile, "FULL=1");
2190     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2191     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2192     ok(pf_exists("msitest"), "File not installed\n");
2193
2194     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2195     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2196
2197     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2198     todo_wine
2199     {
2200         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2201     }
2202
2203     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2204     todo_wine
2205     {
2206         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2207     }
2208
2209     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2210                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2211     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2212     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2213
2214     /* UnpublishFeatures, both features removed */
2215     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature,montecristo");
2216     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2217     todo_wine
2218     {
2219         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
2220         ok(!pf_exists("msitest"), "File not deleted\n");
2221     }
2222
2223     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2224     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2225
2226     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2227     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2228
2229     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2230     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2231
2232     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2233                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2234     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2235     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2236
2237     /* complete install */
2238     r = MsiInstallProductA(msifile, "FULL=1");
2239     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2240     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2241     ok(pf_exists("msitest"), "File not installed\n");
2242
2243     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2244     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2245
2246     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2247     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2248
2249     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2250     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2251
2252     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2253                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2254     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2255     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2256
2257     /* complete uninstall */
2258     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2260     todo_wine
2261     {
2262         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
2263         ok(!pf_exists("msitest"), "File not deleted\n");
2264     }
2265
2266     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2267     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2268
2269     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2270     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2271
2272     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2273     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2274
2275     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2276                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2277     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2278     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2279
2280     /* make sure 'Program Files\msitest' is removed */
2281     delete_pfmsitest_files();
2282
2283     DeleteFile(msifile);
2284     DeleteFile("msitest\\maximus");
2285     RemoveDirectory("msitest");
2286 }
2287
2288 static void test_publishsourcelist(void)
2289 {
2290     UINT r;
2291     DWORD size;
2292     CHAR value[MAX_PATH];
2293     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2294
2295     CreateDirectoryA("msitest", NULL);
2296     create_file("msitest\\maximus", 500);
2297
2298     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2299
2300     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2301
2302     r = MsiInstallProductA(msifile, NULL);
2303     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2304     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2305     ok(pf_exists("msitest"), "File not installed\n");
2306
2307     /* nothing published */
2308     size = 0xdeadbeef;
2309     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2310                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
2311     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2312     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
2313
2314     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
2315     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2316     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2317     ok(pf_exists("msitest"), "File not installed\n");
2318
2319     /* after RegisterProduct */
2320     size = 0xdeadbeef;
2321     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2322                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
2323     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2324     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
2325
2326     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
2327     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2328     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2329     ok(pf_exists("msitest"), "File not installed\n");
2330
2331     /* after ProcessComponents */
2332     size = 0xdeadbeef;
2333     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2334                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
2335     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2336     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
2337
2338     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
2339     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2340     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2341     ok(pf_exists("msitest"), "File not installed\n");
2342
2343     /* after PublishFeatures */
2344     size = 0xdeadbeef;
2345     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2346                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
2347     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2348     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
2349
2350     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
2351     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2352     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2353     ok(pf_exists("msitest"), "File not installed\n");
2354
2355     /* after PublishProduct */
2356     size = MAX_PATH;
2357     lstrcpyA(value, "aaa");
2358     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2359                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
2360     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2361     ok(!lstrcmpA(value, "msitest.msi"), "Expected 'msitest.msi', got %s\n", value);
2362     ok(size == 11, "Expected 11, got %d\n", size);
2363
2364     /* complete uninstall */
2365     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2366     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2367     todo_wine
2368     {
2369         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
2370         ok(!pf_exists("msitest"), "File not deleted\n");
2371     }
2372
2373     /* make sure 'Program Files\msitest' is removed */
2374     delete_pfmsitest_files();
2375
2376     DeleteFile(msifile);
2377     DeleteFile("msitest\\maximus");
2378     RemoveDirectory("msitest");
2379 }
2380
2381 static UINT run_query(MSIHANDLE hdb, MSIHANDLE hrec, const char *query)
2382 {
2383     MSIHANDLE hview = 0;
2384     UINT r;
2385
2386     r = MsiDatabaseOpenView(hdb, query, &hview);
2387     if(r != ERROR_SUCCESS)
2388         return r;
2389
2390     r = MsiViewExecute(hview, hrec);
2391     if(r == ERROR_SUCCESS)
2392         r = MsiViewClose(hview);
2393     MsiCloseHandle(hview);
2394     return r;
2395 }
2396
2397 static void set_transform_summary_info(void)
2398 {
2399     UINT r;
2400     MSIHANDLE suminfo;
2401
2402     /* build summmary info */
2403     r = MsiGetSummaryInformation(0, mstfile, 3, &suminfo);
2404     todo_wine
2405     {
2406         ok(r == ERROR_SUCCESS , "Failed to open summaryinfo\n");
2407     }
2408
2409     r = MsiSummaryInfoSetProperty(suminfo, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
2410     todo_wine
2411     {
2412         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
2413     }
2414
2415     r = MsiSummaryInfoSetProperty(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
2416                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
2417                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
2418                         "{4C0EAA15-0264-4E5A-8758-609EF142B92D}");
2419     todo_wine
2420     {
2421         ok(r == ERROR_SUCCESS , "Failed to set summary info\n");
2422     }
2423
2424     r = MsiSummaryInfoSetProperty(suminfo, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
2425     todo_wine
2426     {
2427         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
2428     }
2429
2430     r = MsiSummaryInfoPersist(suminfo);
2431     todo_wine
2432     {
2433         ok(r == ERROR_SUCCESS , "Failed to make summary info persist\n");
2434     }
2435
2436     r = MsiCloseHandle(suminfo);
2437     todo_wine
2438     {
2439         ok(r == ERROR_SUCCESS , "Failed to close suminfo\n");
2440     }
2441 }
2442
2443 static void generate_transform(void)
2444 {
2445     MSIHANDLE hdb1, hdb2;
2446     LPCSTR query;
2447     UINT r;
2448
2449     /* start with two identical databases */
2450     CopyFile(msifile, msifile2, FALSE);
2451
2452     r = MsiOpenDatabase(msifile2, MSIDBOPEN_TRANSACT, &hdb1);
2453     ok(r == ERROR_SUCCESS , "Failed to create database\n");
2454
2455     r = MsiDatabaseCommit(hdb1);
2456     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
2457
2458     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb2);
2459     ok(r == ERROR_SUCCESS , "Failed to create database\n");
2460
2461     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
2462     r = run_query(hdb1, 0, query);
2463     ok(r == ERROR_SUCCESS, "failed to add property\n");
2464
2465     /* database needs to be committed */
2466     MsiDatabaseCommit(hdb1);
2467
2468     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
2469     ok(r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r);
2470
2471 #if 0  /* not implemented in wine yet */
2472     r = MsiCreateTransformSummaryInfo(hdb2, hdb2, mstfile, 0, 0);
2473     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2474 #endif
2475
2476     MsiCloseHandle(hdb1);
2477     MsiCloseHandle(hdb2);
2478 }
2479
2480 /* data for generating a transform */
2481
2482 /* tables transform names - encoded as they would be in an msi database file */
2483 static const WCHAR name1[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
2484 static const WCHAR name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
2485 static const WCHAR name3[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
2486
2487 /* data in each table */
2488 static const char data1[] = /* _StringData */
2489     "propval";  /* all the strings squashed together */
2490
2491 static const WCHAR data2[] = { /* _StringPool */
2492 /*  len, refs */
2493     0,   0,    /* string 0 ''     */
2494     4,   1,    /* string 1 'prop' */
2495     3,   1,    /* string 2 'val'  */
2496 };
2497
2498 static const WCHAR data3[] = { /* Property */
2499     0x0201, 0x0001, 0x0002,
2500 };
2501
2502 static const struct {
2503     LPCWSTR name;
2504     const void *data;
2505     DWORD size;
2506 } table_transform_data[] =
2507 {
2508     { name1, data1, sizeof data1 - 1 },
2509     { name2, data2, sizeof data2 },
2510     { name3, data3, sizeof data3 },
2511 };
2512
2513 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
2514
2515 static void generate_transform_manual(void)
2516 {
2517     IStorage *stg = NULL;
2518     IStream *stm;
2519     WCHAR name[0x20];
2520     HRESULT r;
2521     DWORD i, count;
2522     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
2523
2524     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
2525
2526     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
2527
2528     r = StgCreateDocfile(name, mode, 0, &stg);
2529     ok(r == S_OK, "failed to create storage\n");
2530     if (!stg)
2531         return;
2532
2533     r = IStorage_SetClass(stg, &CLSID_MsiTransform);
2534     ok(r == S_OK, "failed to set storage type\n");
2535
2536     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
2537     {
2538         r = IStorage_CreateStream(stg, table_transform_data[i].name,
2539                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
2540         if (FAILED(r))
2541         {
2542             ok(0, "failed to create stream %08x\n", r);
2543             continue;
2544         }
2545
2546         r = IStream_Write(stm, table_transform_data[i].data,
2547                           table_transform_data[i].size, &count);
2548         if (FAILED(r) || count != table_transform_data[i].size)
2549             ok(0, "failed to write stream\n");
2550         IStream_Release(stm);
2551     }
2552
2553     IStorage_Release(stg);
2554
2555     set_transform_summary_info();
2556 }
2557
2558 static void test_transformprop(void)
2559 {
2560     UINT r;
2561
2562     CreateDirectoryA("msitest", NULL);
2563     create_file("msitest\\augustus", 500);
2564
2565     create_database(msifile, tp_tables, sizeof(tp_tables) / sizeof(msi_table));
2566
2567     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2568
2569     r = MsiInstallProductA(msifile, NULL);
2570     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2571     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2572     ok(!delete_pf("msitest", FALSE), "File installed\n");
2573
2574     if (0)
2575         generate_transform();
2576     else
2577         generate_transform_manual();
2578
2579     r = MsiInstallProductA(msifile, "TRANSFORMS=winetest.mst");
2580     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2581     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2582     ok(delete_pf("msitest", FALSE), "File not installed\n");
2583
2584     /* Delete the files in the temp (current) folder */
2585     DeleteFile(msifile);
2586     DeleteFile(msifile2);
2587     DeleteFile(mstfile);
2588     DeleteFile("msitest\\augustus");
2589     RemoveDirectory("msitest");
2590 }
2591
2592 static void test_currentworkingdir(void)
2593 {
2594     UINT r;
2595     CHAR path[MAX_PATH];
2596     LPSTR ptr, ptr2;
2597
2598     CreateDirectoryA("msitest", NULL);
2599     create_file("msitest\\augustus", 500);
2600
2601     create_database(msifile, cwd_tables, sizeof(cwd_tables) / sizeof(msi_table));
2602
2603     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2604
2605     CreateDirectoryA("diffdir", NULL);
2606     SetCurrentDirectoryA("diffdir");
2607
2608     sprintf(path, "..\\%s", msifile);
2609     r = MsiInstallProductA(path, NULL);
2610     todo_wine
2611     {
2612         ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
2613         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2614         ok(!delete_pf("msitest", FALSE), "File installed\n");
2615     }
2616
2617     sprintf(path, "%s\\%s", CURR_DIR, msifile);
2618     r = MsiInstallProductA(path, NULL);
2619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2620     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2621     ok(delete_pf("msitest", FALSE), "File not installed\n");
2622
2623     lstrcpyA(path, CURR_DIR);
2624     if (path[lstrlenA(path) - 1] != '\\')
2625         lstrcatA(path, "\\");
2626     lstrcatA(path, "msitest.msi");
2627
2628     ptr2 = strrchr(path, '\\');
2629     *ptr2 = '\0';
2630     ptr = strrchr(path, '\\');
2631     *ptr2 = '\\';
2632     *(ptr++) = '\0';
2633
2634     SetCurrentDirectoryA(path);
2635
2636     r = MsiInstallProductA(ptr, NULL);
2637     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2638     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2639     ok(delete_pf("msitest", FALSE), "File not installed\n");
2640
2641     SetCurrentDirectoryA(CURR_DIR);
2642
2643     DeleteFile(msifile);
2644     DeleteFile("msitest\\augustus");
2645     RemoveDirectory("msitest");
2646     RemoveDirectory("diffdir");
2647 }
2648
2649 static void set_admin_summary_info(const CHAR *name)
2650 {
2651     MSIHANDLE db, summary;
2652     UINT r;
2653
2654     r = MsiOpenDatabaseA(name, MSIDBOPEN_DIRECT, &db);
2655     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2656
2657     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
2658     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2659
2660     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 5, NULL, NULL);
2661     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2662
2663     /* write the summary changes back to the stream */
2664     r = MsiSummaryInfoPersist(summary);
2665     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2666
2667     MsiCloseHandle(summary);
2668
2669     r = MsiDatabaseCommit(db);
2670     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2671
2672     MsiCloseHandle(db);
2673 }
2674
2675 static void test_admin(void)
2676 {
2677     UINT r;
2678
2679     CreateDirectoryA("msitest", NULL);
2680     create_file("msitest\\augustus", 500);
2681
2682     create_database(msifile, adm_tables, sizeof(adm_tables) / sizeof(msi_table));
2683     set_admin_summary_info(msifile);
2684
2685     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2686
2687     r = MsiInstallProductA(msifile, NULL);
2688     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2689     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2690     ok(!delete_pf("msitest", FALSE), "File installed\n");
2691     ok(!DeleteFile("c:\\msitest\\augustus"), "File installed\n");
2692     ok(!RemoveDirectory("c:\\msitest"), "File installed\n");
2693
2694     r = MsiInstallProductA(msifile, "ACTION=ADMIN");
2695     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2696     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2697     ok(!delete_pf("msitest", FALSE), "File installed\n");
2698     todo_wine
2699     {
2700         ok(DeleteFile("c:\\msitest\\augustus"), "File not installed\n");
2701         ok(RemoveDirectory("c:\\msitest"), "File not installed\n");
2702     }
2703
2704     DeleteFile(msifile);
2705     DeleteFile("msitest\\augustus");
2706     RemoveDirectory("msitest");
2707 }
2708
2709 static void set_admin_property_stream(LPCSTR file)
2710 {
2711     IStorage *stg;
2712     IStream *stm;
2713     WCHAR fileW[MAX_PATH];
2714     HRESULT hr;
2715     DWORD count;
2716     const DWORD mode = STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
2717
2718     /* AdminProperties */
2719     static const WCHAR stmname[] = {0x41ca,0x4330,0x3e71,0x44b5,0x4233,0x45f5,0x422c,0x4836,0};
2720     static const WCHAR data[] = {'M','Y','P','R','O','P','=','2','7','1','8',0};
2721
2722     MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH);
2723
2724     hr = StgOpenStorage(fileW, NULL, mode, NULL, 0, &stg);
2725     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
2726     if (!stg)
2727         return;
2728
2729     hr = IStorage_CreateStream(stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
2730     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
2731
2732     hr = IStream_Write(stm, data, sizeof(data), &count);
2733     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
2734
2735     IStream_Release(stm);
2736     IStorage_Release(stg);
2737 }
2738
2739 static void test_adminprops(void)
2740 {
2741     UINT r;
2742
2743     CreateDirectoryA("msitest", NULL);
2744     create_file("msitest\\augustus", 500);
2745
2746     create_database(msifile, amp_tables, sizeof(amp_tables) / sizeof(msi_table));
2747     set_admin_summary_info(msifile);
2748     set_admin_property_stream(msifile);
2749
2750     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2751
2752     r = MsiInstallProductA(msifile, NULL);
2753     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2754     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
2755     ok(delete_pf("msitest", FALSE), "File installed\n");
2756
2757     DeleteFile(msifile);
2758     DeleteFile("msitest\\augustus");
2759     RemoveDirectory("msitest");
2760 }
2761
2762 static void create_pf(LPCSTR file, BOOL is_file)
2763 {
2764     CHAR path[MAX_PATH];
2765
2766     lstrcpyA(path, PROG_FILES_DIR);
2767     lstrcatA(path, "\\");
2768     lstrcatA(path, file);
2769
2770     if (is_file)
2771         create_file(path, 500);
2772     else
2773         CreateDirectoryA(path, NULL);
2774 }
2775
2776 static void test_removefiles(void)
2777 {
2778     UINT r;
2779
2780     CreateDirectoryA("msitest", NULL);
2781     create_file("msitest\\hydrogen", 500);
2782     create_file("msitest\\helium", 500);
2783     create_file("msitest\\lithium", 500);
2784
2785     create_database(msifile, rem_tables, sizeof(rem_tables) / sizeof(msi_table));
2786
2787     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2788
2789     r = MsiInstallProductA(msifile, NULL);
2790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2791     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
2792     ok(!pf_exists("msitest\\helium"), "File installed\n");
2793     ok(pf_exists("msitest\\lithium"), "File not installed\n");
2794     ok(pf_exists("msitest"), "File not installed\n");
2795
2796     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2797     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2798     ok(!pf_exists("msitest\\helium"), "File not deleted\n");
2799     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
2800     todo_wine
2801     {
2802         ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
2803         ok(delete_pf("msitest", FALSE), "File deleted\n");
2804     }
2805
2806     create_pf("msitest", FALSE);
2807     create_pf("msitest\\hydrogen", TRUE);
2808     create_pf("msitest\\helium", TRUE);
2809     create_pf("msitest\\lithium", TRUE);
2810
2811     r = MsiInstallProductA(msifile, NULL);
2812     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2813     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
2814     ok(pf_exists("msitest\\helium"), "File not installed\n");
2815     ok(pf_exists("msitest\\lithium"), "File not installed\n");
2816     ok(pf_exists("msitest"), "File not installed\n");
2817
2818     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2819     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2820     ok(delete_pf("msitest\\helium", TRUE), "File deleted\n");
2821     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
2822     todo_wine
2823     {
2824         ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
2825         ok(delete_pf("msitest", FALSE), "File deleted\n");
2826     }
2827
2828     create_pf("msitest", FALSE);
2829     create_pf("msitest\\furlong", TRUE);
2830     create_pf("msitest\\firkin", TRUE);
2831     create_pf("msitest\\fortnight", TRUE);
2832     create_pf("msitest\\becquerel", TRUE);
2833     create_pf("msitest\\dioptre", TRUE);
2834     create_pf("msitest\\attoparsec", TRUE);
2835     create_pf("msitest\\storeys", TRUE);
2836     create_pf("msitest\\block", TRUE);
2837     create_pf("msitest\\siriometer", TRUE);
2838
2839     r = MsiInstallProductA(msifile, NULL);
2840     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2841     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
2842     ok(!pf_exists("msitest\\helium"), "File installed\n");
2843     ok(pf_exists("msitest\\lithium"), "File not installed\n");
2844     ok(pf_exists("msitest\\becquerel"), "File not installed\n");
2845     ok(pf_exists("msitest\\dioptre"), "File not installed\n");
2846     ok(pf_exists("msitest\\attoparsec"), "File not installed\n");
2847     ok(pf_exists("msitest"), "File not installed\n");
2848     todo_wine
2849     {
2850         ok(!pf_exists("msitest\\firkin"), "File not deleted\n");
2851         ok(!pf_exists("msitest\\fortnight"), "File not deleted\n");
2852         ok(!pf_exists("msitest\\furlong"), "File not deleted\n");
2853         ok(!pf_exists("msitest\\storeys"), "File not deleted\n");
2854         ok(!pf_exists("msitest\\block"), "File not deleted\n");
2855         ok(!pf_exists("msitest\\siriometer"), "File not deleted\n");
2856     }
2857
2858     create_pf("msitest\\furlong", TRUE);
2859     create_pf("msitest\\firkin", TRUE);
2860     create_pf("msitest\\fortnight", TRUE);
2861     create_pf("msitest\\storeys", TRUE);
2862     create_pf("msitest\\block", TRUE);
2863     create_pf("msitest\\siriometer", TRUE);
2864
2865     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2866     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2867     ok(!delete_pf("msitest\\helium", TRUE), "File not deleted\n");
2868     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
2869     ok(delete_pf("msitest\\furlong", TRUE), "File deleted\n");
2870     ok(delete_pf("msitest\\firkin", TRUE), "File deleted\n");
2871     ok(delete_pf("msitest\\fortnight", TRUE), "File deleted\n");
2872     ok(delete_pf("msitest\\attoparsec", TRUE), "File deleted\n");
2873     ok(delete_pf("msitest\\siriometer", TRUE), "File deleted\n");
2874     todo_wine
2875     {
2876         ok(!delete_pf("msitest\\hydrogen", TRUE), "File not deleted\n");
2877         ok(!delete_pf("msitest\\becquerel", TRUE), "File not deleted\n");
2878         ok(!delete_pf("msitest\\dioptre", TRUE), "File not deleted\n");
2879         ok(!delete_pf("msitest\\storeys", TRUE), "File not deleted\n");
2880         ok(!delete_pf("msitest\\block", TRUE), "File not deleted\n");
2881     }
2882     ok(delete_pf("msitest", FALSE), "File deleted\n");
2883
2884     DeleteFile(msifile);
2885     DeleteFile("msitest\\hydrogen");
2886     DeleteFile("msitest\\helium");
2887     DeleteFile("msitest\\lithium");
2888     RemoveDirectory("msitest");
2889 }
2890
2891 static void test_movefiles(void)
2892 {
2893     UINT r;
2894     char props[MAX_PATH];
2895
2896     CreateDirectoryA("msitest", NULL);
2897     create_file("msitest\\augustus", 100);
2898     create_file("cameroon", 100);
2899     create_file("djibouti", 100);
2900     create_file("egypt", 100);
2901     create_file("finland", 100);
2902     create_file("gambai", 100);
2903     create_file("honduras", 100);
2904     create_file("msitest\\india", 100);
2905     create_file("japan", 100);
2906     create_file("kenya", 100);
2907     CreateDirectoryA("latvia", NULL);
2908     create_file("nauru", 100);
2909     create_file("apple", 100);
2910     create_file("application", 100);
2911     create_file("ape", 100);
2912     create_file("foo", 100);
2913     create_file("fao", 100);
2914     create_file("fbod", 100);
2915     create_file("budding", 100);
2916     create_file("buddy", 100);
2917     create_file("bud", 100);
2918     create_file("bar", 100);
2919     create_file("bur", 100);
2920     create_file("bird", 100);
2921
2922     create_database(msifile, mov_tables, sizeof(mov_tables) / sizeof(msi_table));
2923
2924     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2925     MsiEnableLog(INSTALLLOGMODE_VERBOSE | INSTALLLOGMODE_EXTRADEBUG, "log.txt", 0);
2926
2927     /* if the source or dest property is not a full path,
2928      * windows tries to access it as a network resource
2929      */
2930
2931     sprintf(props, "SOURCEFULL=\"%s\\\" DESTFULL=\"%s\\msitest\" "
2932             "FILEPATHBAD=\"%s\\japan\" FILEPATHGOOD=\"%s\\kenya\"",
2933             CURR_DIR, PROG_FILES_DIR, CURR_DIR, CURR_DIR);
2934
2935     r = MsiInstallProductA(msifile, props);
2936     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2937     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2938     ok(!delete_pf("msitest\\dest", TRUE), "File copied\n");
2939     ok(delete_pf("msitest\\canada", TRUE), "File not copied\n");
2940     ok(delete_pf("msitest\\dominica", TRUE), "File not moved\n");
2941     ok(!delete_pf("msitest\\elsalvador", TRUE), "File moved\n");
2942     ok(!delete_pf("msitest\\france", TRUE), "File moved\n");
2943     ok(!delete_pf("msitest\\georgia", TRUE), "File moved\n");
2944     ok(delete_pf("msitest\\hungary", TRUE), "File not moved\n");
2945     ok(!delete_pf("msitest\\indonesia", TRUE), "File moved\n");
2946     ok(!delete_pf("msitest\\jordan", TRUE), "File moved\n");
2947     ok(delete_pf("msitest\\kiribati", TRUE), "File not moved\n");
2948     ok(!delete_pf("msitest\\lebanon", TRUE), "File moved\n");
2949     ok(!delete_pf("msitest\\lebanon", FALSE), "Directory moved\n");
2950     ok(!delete_pf("msitest\\apple", TRUE), "File should not exist\n");
2951     ok(delete_pf("msitest\\wildcard", TRUE), "File not moved\n");
2952     ok(delete_pf("msitest\\application", TRUE), "File not moved\n");
2953     ok(!delete_pf("msitest\\ape", TRUE), "File moved\n");
2954     ok(delete_pf("msitest\\foo", TRUE), "File not moved\n");
2955     ok(!delete_pf("msitest\\fao", TRUE), "File should not exist\n");
2956     ok(delete_pf("msitest\\single", TRUE), "File not moved\n");
2957     ok(!delete_pf("msitest\\fbod", TRUE), "File moved\n");
2958     ok(delete_pf("msitest\\budding", TRUE), "File not moved\n");
2959     ok(delete_pf("msitest\\buddy", TRUE), "File not moved\n");
2960     ok(!delete_pf("msitest\\bud", TRUE), "File moved\n");
2961     ok(delete_pf("msitest\\bar", TRUE), "File not moved\n");
2962     ok(delete_pf("msitest\\bur", TRUE), "File not moved\n");
2963     ok(!delete_pf("msitest\\bird", TRUE), "File moved\n");
2964     ok(delete_pf("msitest", FALSE), "File not installed\n");
2965     ok(DeleteFileA("cameroon"), "File moved\n");
2966     ok(!DeleteFileA("djibouti"), "File not moved\n");
2967     ok(DeleteFileA("egypt"), "File moved\n");
2968     ok(DeleteFileA("finland"), "File moved\n");
2969     ok(DeleteFileA("gambai"), "File moved\n");
2970     ok(!DeleteFileA("honduras"), "File not moved\n");
2971     ok(DeleteFileA("msitest\\india"), "File moved\n");
2972     ok(DeleteFileA("japan"), "File moved\n");
2973     ok(!DeleteFileA("kenya"), "File not moved\n");
2974     ok(RemoveDirectoryA("latvia"), "Directory moved\n");
2975     ok(!DeleteFileA("nauru"), "File not moved\n");
2976     ok(!DeleteFileA("apple"), "File not moved\n");
2977     ok(!DeleteFileA("application"), "File not moved\n");
2978     ok(DeleteFileA("ape"), "File moved\n");
2979     ok(!DeleteFileA("foo"), "File not moved\n");
2980     ok(!DeleteFileA("fao"), "File not moved\n");
2981     ok(DeleteFileA("fbod"), "File moved\n");
2982     ok(!DeleteFileA("budding"), "File not moved\n");
2983     ok(!DeleteFileA("buddy"), "File not moved\n");
2984     ok(DeleteFileA("bud"), "File moved\n");
2985     ok(!DeleteFileA("bar"), "File not moved\n");
2986     ok(!DeleteFileA("bur"), "File not moved\n");
2987     ok(DeleteFileA("bird"), "File moved\n");
2988
2989     DeleteFile("msitest\\augustus");
2990     RemoveDirectory("msitest");
2991     DeleteFile(msifile);
2992 }
2993 START_TEST(install)
2994 {
2995     DWORD len;
2996     char temp_path[MAX_PATH], prev_path[MAX_PATH];
2997
2998     init_functionpointers();
2999
3000     GetCurrentDirectoryA(MAX_PATH, prev_path);
3001     GetTempPath(MAX_PATH, temp_path);
3002     SetCurrentDirectoryA(temp_path);
3003
3004     lstrcpyA(CURR_DIR, temp_path);
3005     len = lstrlenA(CURR_DIR);
3006
3007     if(len && (CURR_DIR[len - 1] == '\\'))
3008         CURR_DIR[len - 1] = 0;
3009
3010     get_program_files_dir(PROG_FILES_DIR, COMMON_FILES_DIR);
3011
3012     test_MsiInstallProduct();
3013     test_MsiSetComponentState();
3014     test_packagecoltypes();
3015     test_continuouscabs();
3016     test_caborder();
3017     test_mixedmedia();
3018     test_samesequence();
3019     test_uiLevelFlags();
3020     test_readonlyfile();
3021     test_setdirproperty();
3022     test_cabisextracted();
3023     test_concurrentinstall();
3024     test_setpropertyfolder();
3025     test_publish();
3026     test_publishsourcelist();
3027     test_transformprop();
3028     test_currentworkingdir();
3029     test_admin();
3030     test_adminprops();
3031     test_removefiles();
3032     test_movefiles();
3033
3034     SetCurrentDirectoryA(prev_path);
3035 }