msi: Don't publish features to an invalid location.
[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 *pMsiSourceListEnumSourcesA)
38     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPSTR, LPDWORD);
39 static UINT (WINAPI *pMsiSourceListGetInfoA)
40     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
41
42 static const char *msifile = "msitest.msi";
43 static const char *msifile2 = "winetest2.msi";
44 static const char *mstfile = "winetest.mst";
45 static CHAR CURR_DIR[MAX_PATH];
46 static CHAR PROG_FILES_DIR[MAX_PATH];
47 static CHAR COMMON_FILES_DIR[MAX_PATH];
48
49 /* msi database data */
50
51 static const CHAR component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
52                                     "s72\tS38\ts72\ti2\tS255\tS72\n"
53                                     "Component\tComponent\n"
54                                     "Five\t{8CC92E9D-14B2-4CA4-B2AA-B11D02078087}\tNEWDIR\t2\t\tfive.txt\n"
55                                     "Four\t{FD37B4EA-7209-45C0-8917-535F35A2F080}\tCABOUTDIR\t2\t\tfour.txt\n"
56                                     "One\t{783B242E-E185-4A56-AF86-C09815EC053C}\tMSITESTDIR\t2\t\tone.txt\n"
57                                     "Three\t{010B6ADD-B27D-4EDD-9B3D-34C4F7D61684}\tCHANGEDDIR\t2\t\tthree.txt\n"
58                                     "Two\t{BF03D1A6-20DA-4A65-82F3-6CAC995915CE}\tFIRSTDIR\t2\t\ttwo.txt\n"
59                                     "dangler\t{6091DF25-EF96-45F1-B8E9-A9B1420C7A3C}\tTARGETDIR\t4\t\tregdata\n"
60                                     "component\t\tMSITESTDIR\t0\t1\tfile\n"
61                                     "service_comp\t\tMSITESTDIR\t0\t1\tservice_file";
62
63 static const CHAR directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
64                                     "s72\tS72\tl255\n"
65                                     "Directory\tDirectory\n"
66                                     "CABOUTDIR\tMSITESTDIR\tcabout\n"
67                                     "CHANGEDDIR\tMSITESTDIR\tchanged:second\n"
68                                     "FIRSTDIR\tMSITESTDIR\tfirst\n"
69                                     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
70                                     "NEWDIR\tCABOUTDIR\tnew\n"
71                                     "ProgramFilesFolder\tTARGETDIR\t.\n"
72                                     "TARGETDIR\t\tSourceDir";
73
74 static const CHAR feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
75                                   "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
76                                   "Feature\tFeature\n"
77                                   "Five\t\tFive\tThe Five Feature\t5\t3\tNEWDIR\t0\n"
78                                   "Four\t\tFour\tThe Four Feature\t4\t3\tCABOUTDIR\t0\n"
79                                   "One\t\tOne\tThe One Feature\t1\t3\tMSITESTDIR\t0\n"
80                                   "Three\t\tThree\tThe Three Feature\t3\t3\tCHANGEDDIR\t0\n"
81                                   "Two\t\tTwo\tThe Two Feature\t2\t3\tFIRSTDIR\t0\n"
82                                   "feature\t\t\t\t2\t1\tTARGETDIR\t0\n"
83                                   "service_feature\t\t\t\t2\t1\tTARGETDIR\t0";
84
85 static const CHAR feature_comp_dat[] = "Feature_\tComponent_\n"
86                                        "s38\ts72\n"
87                                        "FeatureComponents\tFeature_\tComponent_\n"
88                                        "Five\tFive\n"
89                                        "Four\tFour\n"
90                                        "One\tOne\n"
91                                        "Three\tThree\n"
92                                        "Two\tTwo\n"
93                                        "feature\tcomponent\n"
94                                        "service_feature\tservice_comp\n";
95
96 static const CHAR file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
97                                "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
98                                "File\tFile\n"
99                                "five.txt\tFive\tfive.txt\t1000\t\t\t16384\t5\n"
100                                "four.txt\tFour\tfour.txt\t1000\t\t\t16384\t4\n"
101                                "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n"
102                                "three.txt\tThree\tthree.txt\t1000\t\t\t0\t3\n"
103                                "two.txt\tTwo\ttwo.txt\t1000\t\t\t0\t2\n"
104                                "file\tcomponent\tfilename\t100\t\t\t8192\t1\n"
105                                "service_file\tservice_comp\tservice.exe\t100\t\t\t8192\t1";
106
107 static const CHAR install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
108                                            "s72\tS255\tI2\n"
109                                            "InstallExecuteSequence\tAction\n"
110                                            "AllocateRegistrySpace\tNOT Installed\t1550\n"
111                                            "CostFinalize\t\t1000\n"
112                                            "CostInitialize\t\t800\n"
113                                            "FileCost\t\t900\n"
114                                            "ResolveSource\t\t950\n"
115                                            "MoveFiles\t\t1700\n"
116                                            "InstallFiles\t\t4000\n"
117                                            "DuplicateFiles\t\t4500\n"
118                                            "InstallServices\t\t5000\n"
119                                            "InstallFinalize\t\t6600\n"
120                                            "InstallInitialize\t\t1500\n"
121                                            "InstallValidate\t\t1400\n"
122                                            "LaunchConditions\t\t100\n"
123                                            "WriteRegistryValues\tSourceDir And SOURCEDIR\t5000";
124
125 static const CHAR media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
126                                 "i2\ti4\tL64\tS255\tS32\tS72\n"
127                                 "Media\tDiskId\n"
128                                 "1\t3\t\t\tDISK1\t\n"
129                                 "2\t5\t\tmsitest.cab\tDISK2\t\n";
130
131 static const CHAR property_dat[] = "Property\tValue\n"
132                                    "s72\tl0\n"
133                                    "Property\tProperty\n"
134                                    "DefaultUIFont\tDlgFont8\n"
135                                    "HASUIRUN\t0\n"
136                                    "INSTALLLEVEL\t3\n"
137                                    "InstallMode\tTypical\n"
138                                    "Manufacturer\tWine\n"
139                                    "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
140                                    "ProductCode\t{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}\n"
141                                    "ProductID\tnone\n"
142                                    "ProductLanguage\t1033\n"
143                                    "ProductName\tMSITEST\n"
144                                    "ProductVersion\t1.1.1\n"
145                                    "PROMPTROLLBACKCOST\tP\n"
146                                    "Setup\tSetup\n"
147                                    "UpgradeCode\t{4C0EAA15-0264-4E5A-8758-609EF142B92D}\n"
148                                    "AdminProperties\tPOSTADMIN\n"
149                                    "ROOTDRIVE\tC:\\\n"
150                                    "SERVNAME\tTestService\n"
151                                    "SERVDISP\tTestServiceDisp\n";
152
153 static const CHAR registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
154                                    "s72\ti2\tl255\tL255\tL0\ts72\n"
155                                    "Registry\tRegistry\n"
156                                    "Apples\t2\tSOFTWARE\\Wine\\msitest\tName\timaname\tOne\n"
157                                    "Oranges\t2\tSOFTWARE\\Wine\\msitest\tnumber\t#314\tTwo\n"
158                                    "regdata\t2\tSOFTWARE\\Wine\\msitest\tblah\tbad\tdangler\n"
159                                    "OrderTest\t2\tSOFTWARE\\Wine\\msitest\tOrderTestName\tOrderTestValue\tcomponent";
160
161 static const CHAR service_install_dat[] = "ServiceInstall\tName\tDisplayName\tServiceType\tStartType\tErrorControl\t"
162                                           "LoadOrderGroup\tDependencies\tStartName\tPassword\tArguments\tComponent_\tDescription\n"
163                                           "s72\ts255\tL255\ti4\ti4\ti4\tS255\tS255\tS255\tS255\tS255\ts72\tL255\n"
164                                           "ServiceInstall\tServiceInstall\n"
165                                           "TestService\t[SERVNAME]\t[SERVDISP]\t2\t3\t0\t\t\tTestService\t\t\tservice_comp\t\t";
166
167 static const CHAR service_control_dat[] = "ServiceControl\tName\tEvent\tArguments\tWait\tComponent_\n"
168                                           "s72\tl255\ti2\tL255\tI2\ts72\n"
169                                           "ServiceControl\tServiceControl\n"
170                                           "ServiceControl\tTestService\t8\t\t0\tservice_comp";
171
172 /* tables for test_continuouscabs */
173 static const CHAR cc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
174                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
175                                        "Component\tComponent\n"
176                                        "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
177                                        "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
178                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
179
180 static const CHAR cc2_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
181                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
182                                         "Component\tComponent\n"
183                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
184                                         "augustus\t\tMSITESTDIR\t0\t0\taugustus\n"
185                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
186
187 static const CHAR cc_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
188                                      "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
189                                      "Feature\tFeature\n"
190                                      "feature\t\t\t\t2\t1\tTARGETDIR\t0";
191
192 static const CHAR cc_feature_comp_dat[] = "Feature_\tComponent_\n"
193                                           "s38\ts72\n"
194                                           "FeatureComponents\tFeature_\tComponent_\n"
195                                           "feature\tmaximus\n"
196                                           "feature\taugustus\n"
197                                           "feature\tcaesar";
198
199 static const CHAR cc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
200                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
201                                   "File\tFile\n"
202                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
203                                   "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
204                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12";
205
206 static const CHAR cc2_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
207                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
208                                    "File\tFile\n"
209                                    "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
210                                    "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
211                                    "tiberius\tmaximus\ttiberius\t500\t\t\t16384\t3\n"
212                                    "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12";
213
214 static const CHAR cc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
215                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
216                                    "Media\tDiskId\n"
217                                    "1\t10\t\ttest1.cab\tDISK1\t\n"
218                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
219                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
220
221 static const CHAR co_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
222                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
223                                   "File\tFile\n"
224                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
225                                   "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
226                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
227
228 static const CHAR co_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
229                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
230                                    "Media\tDiskId\n"
231                                    "1\t10\t\ttest1.cab\tDISK1\t\n"
232                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
233                                    "3\t3\t\ttest3.cab\tDISK3\t\n";
234
235 static const CHAR co2_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
236                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
237                                     "Media\tDiskId\n"
238                                     "1\t10\t\ttest1.cab\tDISK1\t\n"
239                                     "2\t12\t\ttest3.cab\tDISK3\t\n"
240                                     "3\t2\t\ttest2.cab\tDISK2\t\n";
241
242 static const CHAR mm_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
243                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
244                                   "File\tFile\n"
245                                   "maximus\tmaximus\tmaximus\t500\t\t\t512\t1\n"
246                                   "augustus\taugustus\taugustus\t500\t\t\t512\t2\n"
247                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
248
249 static const CHAR mm_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
250                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
251                                    "Media\tDiskId\n"
252                                    "1\t3\t\ttest1.cab\tDISK1\t\n";
253
254 static const CHAR ss_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
255                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
256                                    "Media\tDiskId\n"
257                                    "1\t2\t\ttest1.cab\tDISK1\t\n"
258                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
259                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
260
261 /* tables for test_uiLevelFlags */
262 static const CHAR ui_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
263                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
264                                        "Component\tComponent\n"
265                                        "maximus\t\tMSITESTDIR\t0\tHASUIRUN=1\tmaximus\n"
266                                        "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
267                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
268
269 static const CHAR ui_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
270                                            "s72\tS255\tI2\n"
271                                            "InstallUISequence\tAction\n"
272                                            "SetUIProperty\t\t5\n"
273                                            "ExecuteAction\t\t1100\n";
274
275 static const CHAR ui_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
276                                            "s72\ti2\tS64\tS0\tS255\n"
277                                            "CustomAction\tAction\n"
278                                            "SetUIProperty\t51\tHASUIRUN\t1\t\n";
279
280 static const CHAR rof_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
281                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
282                                         "Component\tComponent\n"
283                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n";
284
285 static const CHAR rof_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
286                                       "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
287                                       "Feature\tFeature\n"
288                                       "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
289                                       "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
290
291 static const CHAR rof_feature_comp_dat[] = "Feature_\tComponent_\n"
292                                            "s38\ts72\n"
293                                            "FeatureComponents\tFeature_\tComponent_\n"
294                                            "feature\tmaximus\n"
295                                            "montecristo\tmaximus";
296
297 static const CHAR rof_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
298                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
299                                    "File\tFile\n"
300                                    "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
301
302 static const CHAR rof_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
303                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
304                                     "Media\tDiskId\n"
305                                     "1\t1\t\t\tDISK1\t\n";
306
307 static const CHAR sdp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
308                                                "s72\tS255\tI2\n"
309                                                "InstallExecuteSequence\tAction\n"
310                                                "AllocateRegistrySpace\tNOT Installed\t1550\n"
311                                                "CostFinalize\t\t1000\n"
312                                                "CostInitialize\t\t800\n"
313                                                "FileCost\t\t900\n"
314                                                "InstallFiles\t\t4000\n"
315                                                "InstallFinalize\t\t6600\n"
316                                                "InstallInitialize\t\t1500\n"
317                                                "InstallValidate\t\t1400\n"
318                                                "LaunchConditions\t\t100\n"
319                                                "SetDirProperty\t\t950";
320
321 static const CHAR sdp_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
322                                             "s72\ti2\tS64\tS0\tS255\n"
323                                             "CustomAction\tAction\n"
324                                             "SetDirProperty\t51\tMSITESTDIR\t[CommonFilesFolder]msitest\\\t\n";
325
326 static const CHAR cie_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
327                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
328                                         "Component\tComponent\n"
329                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
330                                         "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
331                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n"
332                                         "gaius\t\tMSITESTDIR\t0\t1\tgaius\n";
333
334 static const CHAR cie_feature_comp_dat[] = "Feature_\tComponent_\n"
335                                            "s38\ts72\n"
336                                            "FeatureComponents\tFeature_\tComponent_\n"
337                                            "feature\tmaximus\n"
338                                            "feature\taugustus\n"
339                                            "feature\tcaesar\n"
340                                            "feature\tgaius";
341
342 static const CHAR cie_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
343                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
344                                    "File\tFile\n"
345                                    "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
346                                    "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
347                                    "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12\n"
348                                    "gaius\tgaius\tgaius\t500\t\t\t8192\t11";
349
350 static const CHAR cie_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
351                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
352                                     "Media\tDiskId\n"
353                                     "1\t1\t\ttest1.cab\tDISK1\t\n"
354                                     "2\t2\t\ttest2.cab\tDISK2\t\n"
355                                     "3\t12\t\ttest3.cab\tDISK3\t\n";
356
357 static const CHAR ci_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
358                                               "s72\tS255\tI2\n"
359                                               "InstallExecuteSequence\tAction\n"
360                                               "CostFinalize\t\t1000\n"
361                                               "CostInitialize\t\t800\n"
362                                               "FileCost\t\t900\n"
363                                               "InstallFiles\t\t4000\n"
364                                               "InstallServices\t\t5000\n"
365                                               "InstallFinalize\t\t6600\n"
366                                               "InstallInitialize\t\t1500\n"
367                                               "RunInstall\t\t1600\n"
368                                               "InstallValidate\t\t1400\n"
369                                               "LaunchConditions\t\t100";
370
371 static const CHAR ci_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
372                                             "s72\ti2\tS64\tS0\tS255\n"
373                                             "CustomAction\tAction\n"
374                                             "RunInstall\t87\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
375
376 static const CHAR ci_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
377                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
378                                        "Component\tComponent\n"
379                                        "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
380
381 static const CHAR ci2_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
382                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
383                                         "Component\tComponent\n"
384                                         "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
385
386 static const CHAR ci2_feature_comp_dat[] = "Feature_\tComponent_\n"
387                                            "s38\ts72\n"
388                                            "FeatureComponents\tFeature_\tComponent_\n"
389                                            "feature\taugustus";
390
391 static const CHAR ci2_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
392                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
393                                    "File\tFile\n"
394                                    "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
395
396 static const CHAR spf_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
397                                             "s72\ti2\tS64\tS0\tS255\n"
398                                             "CustomAction\tAction\n"
399                                             "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n";
400
401 static const CHAR spf_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
402                                                "s72\tS255\tI2\n"
403                                                "InstallExecuteSequence\tAction\n"
404                                                "CostFinalize\t\t1000\n"
405                                                "CostInitialize\t\t800\n"
406                                                "FileCost\t\t900\n"
407                                                "SetFolderProp\t\t950\n"
408                                                "InstallFiles\t\t4000\n"
409                                                "InstallServices\t\t5000\n"
410                                                "InstallFinalize\t\t6600\n"
411                                                "InstallInitialize\t\t1500\n"
412                                                "InstallValidate\t\t1400\n"
413                                                "LaunchConditions\t\t100";
414
415 static const CHAR spf_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
416                                              "s72\tS255\tI2\n"
417                                              "InstallUISequence\tAction\n"
418                                              "CostInitialize\t\t800\n"
419                                              "FileCost\t\t900\n"
420                                              "CostFinalize\t\t1000\n"
421                                              "ExecuteAction\t\t1100\n";
422
423 static const CHAR pp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
424                                               "s72\tS255\tI2\n"
425                                               "InstallExecuteSequence\tAction\n"
426                                               "ValidateProductID\t\t700\n"
427                                               "CostInitialize\t\t800\n"
428                                               "FileCost\t\t900\n"
429                                               "CostFinalize\t\t1000\n"
430                                               "InstallValidate\t\t1400\n"
431                                               "InstallInitialize\t\t1500\n"
432                                               "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
433                                               "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
434                                               "RemoveFiles\t\t3500\n"
435                                               "InstallFiles\t\t4000\n"
436                                               "RegisterUser\tREGISTER_USER=1 Or FULL=1\t6000\n"
437                                               "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
438                                               "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
439                                               "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
440                                               "InstallFinalize\t\t6600";
441
442 static const CHAR tp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
443                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
444                                        "Component\tComponent\n"
445                                        "augustus\t\tMSITESTDIR\t0\tprop=\"val\"\taugustus\n";
446
447 static const CHAR cwd_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
448                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
449                                         "Component\tComponent\n"
450                                         "augustus\t\tMSITESTDIR\t0\t\taugustus\n";
451
452 static const CHAR adm_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
453                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
454                                         "Component\tComponent\n"
455                                         "augustus\t\tMSITESTDIR\t0\tPOSTADMIN=1\taugustus";
456
457 static const CHAR adm_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
458                                             "s72\ti2\tS64\tS0\tS255\n"
459                                             "CustomAction\tAction\n"
460                                             "SetPOSTADMIN\t51\tPOSTADMIN\t1\t\n";
461
462 static const CHAR adm_admin_exec_seq_dat[] = "Action\tCondition\tSequence\n"
463                                              "s72\tS255\tI2\n"
464                                              "AdminExecuteSequence\tAction\n"
465                                              "CostFinalize\t\t1000\n"
466                                              "CostInitialize\t\t800\n"
467                                              "FileCost\t\t900\n"
468                                              "SetPOSTADMIN\t\t950\n"
469                                              "InstallFiles\t\t4000\n"
470                                              "InstallFinalize\t\t6600\n"
471                                              "InstallInitialize\t\t1500\n"
472                                              "InstallValidate\t\t1400\n"
473                                              "LaunchConditions\t\t100";
474
475 static const CHAR amp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
476                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
477                                         "Component\tComponent\n"
478                                         "augustus\t\tMSITESTDIR\t0\tMYPROP=2718\taugustus\n";
479
480 static const CHAR rem_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
481                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
482                                         "Component\tComponent\n"
483                                         "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t0\t\thydrogen\n"
484                                         "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t1\t\thelium\n"
485                                         "lithium\t\tMSITESTDIR\t2\t\tlithium\n";
486
487 static const CHAR rem_feature_comp_dat[] = "Feature_\tComponent_\n"
488                                            "s38\ts72\n"
489                                            "FeatureComponents\tFeature_\tComponent_\n"
490                                            "feature\thydrogen\n"
491                                            "feature\thelium\n"
492                                            "feature\tlithium";
493
494 static const CHAR rem_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
495                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
496                                    "File\tFile\n"
497                                    "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
498                                    "helium\thelium\thelium\t0\t\t\t8192\t1\n"
499                                    "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
500
501 static const CHAR rem_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
502                                                "s72\tS255\tI2\n"
503                                                "InstallExecuteSequence\tAction\n"
504                                                "ValidateProductID\t\t700\n"
505                                                "CostInitialize\t\t800\n"
506                                                "FileCost\t\t900\n"
507                                                "CostFinalize\t\t1000\n"
508                                                "InstallValidate\t\t1400\n"
509                                                "InstallInitialize\t\t1500\n"
510                                                "ProcessComponents\t\t1600\n"
511                                                "UnpublishFeatures\t\t1800\n"
512                                                "RemoveFiles\t\t3500\n"
513                                                "InstallFiles\t\t4000\n"
514                                                "RegisterProduct\t\t6100\n"
515                                                "PublishFeatures\t\t6300\n"
516                                                "PublishProduct\t\t6400\n"
517                                                "InstallFinalize\t\t6600";
518
519 static const CHAR rem_remove_files_dat[] = "FileKey\tComponent_\tFileName\tDirProperty\tInstallMode\n"
520                                            "s72\ts72\tS255\ts72\tI2\n"
521                                            "RemoveFile\tFileKey\n"
522                                            "furlong\thydrogen\tfurlong\tMSITESTDIR\t1\n"
523                                            "firkin\thelium\tfirkin\tMSITESTDIR\t1\n"
524                                            "fortnight\tlithium\tfortnight\tMSITESTDIR\t1\n"
525                                            "becquerel\thydrogen\tbecquerel\tMSITESTDIR\t2\n"
526                                            "dioptre\thelium\tdioptre\tMSITESTDIR\t2\n"
527                                            "attoparsec\tlithium\tattoparsec\tMSITESTDIR\t2\n"
528                                            "storeys\thydrogen\tstoreys\tMSITESTDIR\t3\n"
529                                            "block\thelium\tblock\tMSITESTDIR\t3\n"
530                                            "siriometer\tlithium\tsiriometer\tMSITESTDIR\t3\n";
531
532 static const CHAR mov_move_file_dat[] = "FileKey\tComponent_\tSourceName\tDestName\tSourceFolder\tDestFolder\tOptions\n"
533                                         "s72\ts72\tS255\tS255\tS72\ts72\ti2\n"
534                                         "MoveFile\tFileKey\n"
535                                         "abkhazia\taugustus\tnonexistent\tdest\tSourceDir\tMSITESTDIR\t0\n"
536                                         "bahamas\taugustus\tnonexistent\tdest\tSourceDir\tMSITESTDIR\t1\n"
537                                         "cambodia\taugustus\tcameroon\tcanada\tSourceDir\tMSITESTDIR\t0\n"
538                                         "denmark\taugustus\tdjibouti\tdominica\tSourceDir\tMSITESTDIR\t1\n"
539                                         "ecuador\taugustus\tegypt\telsalvador\tNotAProp\tMSITESTDIR\t1\n"
540                                         "fiji\taugustus\tfinland\tfrance\tSourceDir\tNotAProp\t1\n"
541                                         "gabon\taugustus\tgambia\tgeorgia\tSOURCEFULL\tMSITESTDIR\t1\n"
542                                         "haiti\taugustus\thonduras\thungary\tSourceDir\tDESTFULL\t1\n"
543                                         "iceland\taugustus\tindia\tindonesia\tMSITESTDIR\tMSITESTDIR\t1\n"
544                                         "jamaica\taugustus\tjapan\tjordan\tFILEPATHBAD\tMSITESTDIR\t1\n"
545                                         "kazakhstan\taugustus\t\tkiribati\tFILEPATHGOOD\tMSITESTDIR\t1\n"
546                                         "laos\taugustus\tlatvia\tlebanon\tSourceDir\tMSITESTDIR\t1\n"
547                                         "namibia\taugustus\tnauru\tkiribati\tSourceDir\tMSITESTDIR\t1\n"
548                                         "wildcard\taugustus\tapp*\twildcard\tSourceDir\tMSITESTDIR\t1\n"
549                                         "single\taugustus\tf?o\tsingle\tSourceDir\tMSITESTDIR\t1\n"
550                                         "wildcardnodest\taugustus\tbudd*\t\tSourceDir\tMSITESTDIR\t1\n"
551                                         "singlenodest\taugustus\tb?r\t\tSourceDir\tMSITESTDIR\t1\n";
552
553 static const CHAR mc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
554                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
555                                         "Component\tComponent\n"
556                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
557                                         "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
558                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n"
559                                         "gaius\t\tMSITESTDIR\t0\tGAIUS=1\tgaius\n";
560
561 static const CHAR mc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
562                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
563                                   "File\tFile\n"
564                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
565                                   "augustus\taugustus\taugustus\t500\t\t\t0\t2\n"
566                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3\n"
567                                   "gaius\tgaius\tgaius\t500\t\t\t16384\t4";
568
569 static const CHAR mc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
570                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
571                                    "Media\tDiskId\n"
572                                    "1\t1\t\ttest1.cab\tDISK1\t\n"
573                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
574                                    "3\t3\t\ttest3.cab\tDISK3\t\n"
575                                    "4\t4\t\ttest3.cab\tDISK3\t\n";
576
577 static const CHAR mc_file_hash_dat[] = "File_\tOptions\tHashPart1\tHashPart2\tHashPart3\tHashPart4\n"
578                                        "s72\ti2\ti4\ti4\ti4\ti4\n"
579                                        "MsiFileHash\tFile_\n"
580                                        "caesar\t0\t850433704\t-241429251\t675791761\t-1221108824";
581
582 static const CHAR df_directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
583                                        "s72\tS72\tl255\n"
584                                        "Directory\tDirectory\n"
585                                        "THIS\tMSITESTDIR\tthis\n"
586                                        "DOESNOT\tTHIS\tdoesnot\n"
587                                        "NONEXISTENT\tDOESNOT\texist\n"
588                                        "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
589                                        "ProgramFilesFolder\tTARGETDIR\t.\n"
590                                        "TARGETDIR\t\tSourceDir";
591
592 static const CHAR df_duplicate_file_dat[] = "FileKey\tComponent_\tFile_\tDestName\tDestFolder\n"
593                                             "s72\ts72\ts72\tS255\tS72\n"
594                                             "DuplicateFile\tFileKey\n"
595                                             "maximus\tmaximus\tmaximus\taugustus\t\n"
596                                             "caesar\tmaximus\tmaximus\t\tNONEXISTENT\n";
597
598 static const CHAR wrv_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
599                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
600                                         "Component\tComponent\n"
601                                         "augustus\t\tMSITESTDIR\t0\t\taugustus\n";
602
603 static const CHAR wrv_registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
604                                        "s72\ti2\tl255\tL255\tL0\ts72\n"
605                                        "Registry\tRegistry\n"
606                                        "regdata\t2\tSOFTWARE\\Wine\\msitest\tValue\t[~]one[~]two[~]three\taugustus";
607
608 static const CHAR ca51_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
609                                          "s72\tS38\ts72\ti2\tS255\tS72\n"
610                                          "Component\tComponent\n"
611                                          "augustus\t\tMSITESTDIR\t0\tMYPROP=42\taugustus\n";
612
613 static const CHAR ca51_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
614                                                 "s72\tS255\tI2\n"
615                                                 "InstallExecuteSequence\tAction\n"
616                                                 "ValidateProductID\t\t700\n"
617                                                 "GoodSetProperty\t\t725\n"
618                                                 "BadSetProperty\t\t750\n"
619                                                 "CostInitialize\t\t800\n"
620                                                 "FileCost\t\t900\n"
621                                                 "CostFinalize\t\t1000\n"
622                                                 "InstallValidate\t\t1400\n"
623                                                 "InstallInitialize\t\t1500\n"
624                                                 "InstallFiles\t\t4000\n"
625                                                 "InstallFinalize\t\t6600";
626
627 static const CHAR ca51_custom_action_dat[] = "Action\tType\tSource\tTarget\n"
628                                              "s72\ti2\tS64\tS0\n"
629                                              "CustomAction\tAction\n"
630                                              "GoodSetProperty\t51\tMYPROP\t42\n"
631                                              "BadSetProperty\t51\t\tMYPROP\n";
632
633 static const CHAR is_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
634                                      "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
635                                      "Feature\tFeature\n"
636                                      "one\t\t\t\t2\t1\t\t0\n" /* favorLocal */
637                                      "two\t\t\t\t2\t1\t\t1\n" /* favorSource */
638                                      "three\t\t\t\t2\t1\t\t4\n" /* favorAdvertise */
639                                      "four\t\t\t\t2\t0\t\t0"; /* disabled */
640
641 static const CHAR is_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
642                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
643                                        "Component\tComponent\n"
644                                        "alpha\t\tMSITESTDIR\t0\t\talpha_file\n" /* favorLocal:Local */
645                                        "beta\t\tMSITESTDIR\t1\t\tbeta_file\n" /* favorLocal:Source */
646                                        "gamma\t\tMSITESTDIR\t2\t\tgamma_file\n" /* favorLocal:Optional */
647                                        "theta\t\tMSITESTDIR\t0\t\ttheta_file\n" /* favorSource:Local */
648                                        "delta\t\tMSITESTDIR\t1\t\tdelta_file\n" /* favorSource:Source */
649                                        "epsilon\t\tMSITESTDIR\t2\t\tepsilon_file\n" /* favorSource:Optional */
650                                        "zeta\t\tMSITESTDIR\t0\t\tzeta_file\n" /* favorAdvertise:Local */
651                                        "iota\t\tMSITESTDIR\t1\t\tiota_file\n" /* favorAdvertise:Source */
652                                        "eta\t\tMSITESTDIR\t2\t\teta_file\n" /* favorAdvertise:Optional */
653                                        "kappa\t\tMSITESTDIR\t0\t\tkappa_file\n" /* disabled:Local */
654                                        "lambda\t\tMSITESTDIR\t1\t\tlambda_file\n" /* disabled:Source */
655                                        "mu\t\tMSITESTDIR\t2\t\tmu_file\n"; /* disabled:Optional */
656
657 static const CHAR is_feature_comp_dat[] = "Feature_\tComponent_\n"
658                                           "s38\ts72\n"
659                                           "FeatureComponents\tFeature_\tComponent_\n"
660                                           "one\talpha\n"
661                                           "one\tbeta\n"
662                                           "one\tgamma\n"
663                                           "two\ttheta\n"
664                                           "two\tdelta\n"
665                                           "two\tepsilon\n"
666                                           "three\tzeta\n"
667                                           "three\tiota\n"
668                                           "three\teta\n"
669                                           "four\tkappa\n"
670                                           "four\tlambda\n"
671                                           "four\tmu";
672
673 static const CHAR is_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
674                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
675                                   "File\tFile\n"
676                                   "alpha_file\talpha\talpha\t500\t\t\t8192\t1\n"
677                                   "beta_file\tbeta\tbeta\t500\t\t\t8291\t2\n"
678                                   "gamma_file\tgamma\tgamma\t500\t\t\t8192\t3\n"
679                                   "theta_file\ttheta\ttheta\t500\t\t\t8192\t4\n"
680                                   "delta_file\tdelta\tdelta\t500\t\t\t8192\t5\n"
681                                   "epsilon_file\tepsilon\tepsilon\t500\t\t\t8192\t6\n"
682                                   "zeta_file\tzeta\tzeta\t500\t\t\t8192\t7\n"
683                                   "iota_file\tiota\tiota\t500\t\t\t8192\t8\n"
684                                   "eta_file\teta\teta\t500\t\t\t8192\t9\n"
685                                   "kappa_file\tkappa\tkappa\t500\t\t\t8192\t10\n"
686                                   "lambda_file\tlambda\tlambda\t500\t\t\t8192\t11\n"
687                                   "mu_file\tmu\tmu\t500\t\t\t8192\t12";
688
689 static const CHAR is_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
690                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
691                                    "Media\tDiskId\n"
692                                    "1\t12\t\t\tDISK1\t\n";
693
694 typedef struct _msi_table
695 {
696     const CHAR *filename;
697     const CHAR *data;
698     int size;
699 } msi_table;
700
701 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
702
703 static const msi_table tables[] =
704 {
705     ADD_TABLE(component),
706     ADD_TABLE(directory),
707     ADD_TABLE(feature),
708     ADD_TABLE(feature_comp),
709     ADD_TABLE(file),
710     ADD_TABLE(install_exec_seq),
711     ADD_TABLE(media),
712     ADD_TABLE(property),
713     ADD_TABLE(registry),
714     ADD_TABLE(service_install),
715     ADD_TABLE(service_control)
716 };
717
718 static const msi_table cc_tables[] =
719 {
720     ADD_TABLE(cc_component),
721     ADD_TABLE(directory),
722     ADD_TABLE(cc_feature),
723     ADD_TABLE(cc_feature_comp),
724     ADD_TABLE(cc_file),
725     ADD_TABLE(install_exec_seq),
726     ADD_TABLE(cc_media),
727     ADD_TABLE(property),
728 };
729
730 static const msi_table cc2_tables[] =
731 {
732     ADD_TABLE(cc2_component),
733     ADD_TABLE(directory),
734     ADD_TABLE(cc_feature),
735     ADD_TABLE(cc_feature_comp),
736     ADD_TABLE(cc2_file),
737     ADD_TABLE(install_exec_seq),
738     ADD_TABLE(cc_media),
739     ADD_TABLE(property),
740 };
741
742 static const msi_table co_tables[] =
743 {
744     ADD_TABLE(cc_component),
745     ADD_TABLE(directory),
746     ADD_TABLE(cc_feature),
747     ADD_TABLE(cc_feature_comp),
748     ADD_TABLE(co_file),
749     ADD_TABLE(install_exec_seq),
750     ADD_TABLE(co_media),
751     ADD_TABLE(property),
752 };
753
754 static const msi_table co2_tables[] =
755 {
756     ADD_TABLE(cc_component),
757     ADD_TABLE(directory),
758     ADD_TABLE(cc_feature),
759     ADD_TABLE(cc_feature_comp),
760     ADD_TABLE(cc_file),
761     ADD_TABLE(install_exec_seq),
762     ADD_TABLE(co2_media),
763     ADD_TABLE(property),
764 };
765
766 static const msi_table mm_tables[] =
767 {
768     ADD_TABLE(cc_component),
769     ADD_TABLE(directory),
770     ADD_TABLE(cc_feature),
771     ADD_TABLE(cc_feature_comp),
772     ADD_TABLE(mm_file),
773     ADD_TABLE(install_exec_seq),
774     ADD_TABLE(mm_media),
775     ADD_TABLE(property),
776 };
777
778 static const msi_table ss_tables[] =
779 {
780     ADD_TABLE(cc_component),
781     ADD_TABLE(directory),
782     ADD_TABLE(cc_feature),
783     ADD_TABLE(cc_feature_comp),
784     ADD_TABLE(cc_file),
785     ADD_TABLE(install_exec_seq),
786     ADD_TABLE(ss_media),
787     ADD_TABLE(property),
788 };
789
790 static const msi_table ui_tables[] =
791 {
792     ADD_TABLE(ui_component),
793     ADD_TABLE(directory),
794     ADD_TABLE(cc_feature),
795     ADD_TABLE(cc_feature_comp),
796     ADD_TABLE(cc_file),
797     ADD_TABLE(install_exec_seq),
798     ADD_TABLE(ui_install_ui_seq),
799     ADD_TABLE(ui_custom_action),
800     ADD_TABLE(cc_media),
801     ADD_TABLE(property),
802 };
803
804 static const msi_table rof_tables[] =
805 {
806     ADD_TABLE(rof_component),
807     ADD_TABLE(directory),
808     ADD_TABLE(rof_feature),
809     ADD_TABLE(rof_feature_comp),
810     ADD_TABLE(rof_file),
811     ADD_TABLE(install_exec_seq),
812     ADD_TABLE(rof_media),
813     ADD_TABLE(property),
814 };
815
816 static const msi_table sdp_tables[] =
817 {
818     ADD_TABLE(rof_component),
819     ADD_TABLE(directory),
820     ADD_TABLE(rof_feature),
821     ADD_TABLE(rof_feature_comp),
822     ADD_TABLE(rof_file),
823     ADD_TABLE(sdp_install_exec_seq),
824     ADD_TABLE(sdp_custom_action),
825     ADD_TABLE(rof_media),
826     ADD_TABLE(property),
827 };
828
829 static const msi_table cie_tables[] =
830 {
831     ADD_TABLE(cie_component),
832     ADD_TABLE(directory),
833     ADD_TABLE(cc_feature),
834     ADD_TABLE(cie_feature_comp),
835     ADD_TABLE(cie_file),
836     ADD_TABLE(install_exec_seq),
837     ADD_TABLE(cie_media),
838     ADD_TABLE(property),
839 };
840
841 static const msi_table ci_tables[] =
842 {
843     ADD_TABLE(ci_component),
844     ADD_TABLE(directory),
845     ADD_TABLE(rof_feature),
846     ADD_TABLE(rof_feature_comp),
847     ADD_TABLE(rof_file),
848     ADD_TABLE(ci_install_exec_seq),
849     ADD_TABLE(rof_media),
850     ADD_TABLE(property),
851     ADD_TABLE(ci_custom_action),
852 };
853
854 static const msi_table ci2_tables[] =
855 {
856     ADD_TABLE(ci2_component),
857     ADD_TABLE(directory),
858     ADD_TABLE(rof_feature),
859     ADD_TABLE(ci2_feature_comp),
860     ADD_TABLE(ci2_file),
861     ADD_TABLE(install_exec_seq),
862     ADD_TABLE(rof_media),
863     ADD_TABLE(property),
864 };
865
866 static const msi_table spf_tables[] =
867 {
868     ADD_TABLE(ci_component),
869     ADD_TABLE(directory),
870     ADD_TABLE(rof_feature),
871     ADD_TABLE(rof_feature_comp),
872     ADD_TABLE(rof_file),
873     ADD_TABLE(spf_install_exec_seq),
874     ADD_TABLE(rof_media),
875     ADD_TABLE(property),
876     ADD_TABLE(spf_custom_action),
877     ADD_TABLE(spf_install_ui_seq),
878 };
879
880 static const msi_table pp_tables[] =
881 {
882     ADD_TABLE(ci_component),
883     ADD_TABLE(directory),
884     ADD_TABLE(rof_feature),
885     ADD_TABLE(rof_feature_comp),
886     ADD_TABLE(rof_file),
887     ADD_TABLE(pp_install_exec_seq),
888     ADD_TABLE(rof_media),
889     ADD_TABLE(property),
890 };
891
892 static const msi_table tp_tables[] =
893 {
894     ADD_TABLE(tp_component),
895     ADD_TABLE(directory),
896     ADD_TABLE(rof_feature),
897     ADD_TABLE(ci2_feature_comp),
898     ADD_TABLE(ci2_file),
899     ADD_TABLE(install_exec_seq),
900     ADD_TABLE(rof_media),
901     ADD_TABLE(property),
902 };
903
904 static const msi_table cwd_tables[] =
905 {
906     ADD_TABLE(cwd_component),
907     ADD_TABLE(directory),
908     ADD_TABLE(rof_feature),
909     ADD_TABLE(ci2_feature_comp),
910     ADD_TABLE(ci2_file),
911     ADD_TABLE(install_exec_seq),
912     ADD_TABLE(rof_media),
913     ADD_TABLE(property),
914 };
915
916 static const msi_table adm_tables[] =
917 {
918     ADD_TABLE(adm_component),
919     ADD_TABLE(directory),
920     ADD_TABLE(rof_feature),
921     ADD_TABLE(ci2_feature_comp),
922     ADD_TABLE(ci2_file),
923     ADD_TABLE(install_exec_seq),
924     ADD_TABLE(rof_media),
925     ADD_TABLE(property),
926     ADD_TABLE(adm_custom_action),
927     ADD_TABLE(adm_admin_exec_seq),
928 };
929
930 static const msi_table amp_tables[] =
931 {
932     ADD_TABLE(amp_component),
933     ADD_TABLE(directory),
934     ADD_TABLE(rof_feature),
935     ADD_TABLE(ci2_feature_comp),
936     ADD_TABLE(ci2_file),
937     ADD_TABLE(install_exec_seq),
938     ADD_TABLE(rof_media),
939     ADD_TABLE(property),
940 };
941
942 static const msi_table rem_tables[] =
943 {
944     ADD_TABLE(rem_component),
945     ADD_TABLE(directory),
946     ADD_TABLE(rof_feature),
947     ADD_TABLE(rem_feature_comp),
948     ADD_TABLE(rem_file),
949     ADD_TABLE(rem_install_exec_seq),
950     ADD_TABLE(rof_media),
951     ADD_TABLE(property),
952     ADD_TABLE(rem_remove_files),
953 };
954
955 static const msi_table mov_tables[] =
956 {
957     ADD_TABLE(cwd_component),
958     ADD_TABLE(directory),
959     ADD_TABLE(rof_feature),
960     ADD_TABLE(ci2_feature_comp),
961     ADD_TABLE(ci2_file),
962     ADD_TABLE(install_exec_seq),
963     ADD_TABLE(rof_media),
964     ADD_TABLE(property),
965     ADD_TABLE(mov_move_file),
966 };
967
968 static const msi_table mc_tables[] =
969 {
970     ADD_TABLE(mc_component),
971     ADD_TABLE(directory),
972     ADD_TABLE(cc_feature),
973     ADD_TABLE(cie_feature_comp),
974     ADD_TABLE(mc_file),
975     ADD_TABLE(install_exec_seq),
976     ADD_TABLE(mc_media),
977     ADD_TABLE(property),
978     ADD_TABLE(mc_file_hash),
979 };
980
981 static const msi_table df_tables[] =
982 {
983     ADD_TABLE(rof_component),
984     ADD_TABLE(df_directory),
985     ADD_TABLE(rof_feature),
986     ADD_TABLE(rof_feature_comp),
987     ADD_TABLE(rof_file),
988     ADD_TABLE(install_exec_seq),
989     ADD_TABLE(rof_media),
990     ADD_TABLE(property),
991     ADD_TABLE(df_duplicate_file),
992 };
993
994 static const msi_table wrv_tables[] =
995 {
996     ADD_TABLE(wrv_component),
997     ADD_TABLE(directory),
998     ADD_TABLE(rof_feature),
999     ADD_TABLE(ci2_feature_comp),
1000     ADD_TABLE(ci2_file),
1001     ADD_TABLE(install_exec_seq),
1002     ADD_TABLE(rof_media),
1003     ADD_TABLE(property),
1004     ADD_TABLE(wrv_registry),
1005 };
1006
1007 static const msi_table sf_tables[] =
1008 {
1009     ADD_TABLE(wrv_component),
1010     ADD_TABLE(directory),
1011     ADD_TABLE(rof_feature),
1012     ADD_TABLE(ci2_feature_comp),
1013     ADD_TABLE(ci2_file),
1014     ADD_TABLE(install_exec_seq),
1015     ADD_TABLE(rof_media),
1016     ADD_TABLE(property),
1017 };
1018
1019 static const msi_table ca51_tables[] =
1020 {
1021     ADD_TABLE(ca51_component),
1022     ADD_TABLE(directory),
1023     ADD_TABLE(rof_feature),
1024     ADD_TABLE(ci2_feature_comp),
1025     ADD_TABLE(ci2_file),
1026     ADD_TABLE(ca51_install_exec_seq),
1027     ADD_TABLE(rof_media),
1028     ADD_TABLE(property),
1029     ADD_TABLE(ca51_custom_action),
1030 };
1031
1032 static const msi_table is_tables[] =
1033 {
1034     ADD_TABLE(is_component),
1035     ADD_TABLE(directory),
1036     ADD_TABLE(is_feature),
1037     ADD_TABLE(is_feature_comp),
1038     ADD_TABLE(is_file),
1039     ADD_TABLE(install_exec_seq),
1040     ADD_TABLE(is_media),
1041     ADD_TABLE(property),
1042 };
1043
1044 /* cabinet definitions */
1045
1046 /* make the max size large so there is only one cab file */
1047 #define MEDIA_SIZE          0x7FFFFFFF
1048 #define FOLDER_THRESHOLD    900000
1049
1050 /* the FCI callbacks */
1051
1052 static void *mem_alloc(ULONG cb)
1053 {
1054     return HeapAlloc(GetProcessHeap(), 0, cb);
1055 }
1056
1057 static void mem_free(void *memory)
1058 {
1059     HeapFree(GetProcessHeap(), 0, memory);
1060 }
1061
1062 static BOOL get_next_cabinet(PCCAB pccab, ULONG  cbPrevCab, void *pv)
1063 {
1064     sprintf(pccab->szCab, pv, pccab->iCab);
1065     return TRUE;
1066 }
1067
1068 static long progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
1069 {
1070     return 0;
1071 }
1072
1073 static int file_placed(PCCAB pccab, char *pszFile, long cbFile,
1074                        BOOL fContinuation, void *pv)
1075 {
1076     return 0;
1077 }
1078
1079 static INT_PTR fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
1080 {
1081     HANDLE handle;
1082     DWORD dwAccess = 0;
1083     DWORD dwShareMode = 0;
1084     DWORD dwCreateDisposition = OPEN_EXISTING;
1085     
1086     dwAccess = GENERIC_READ | GENERIC_WRITE;
1087     /* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
1088     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
1089
1090     if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
1091         dwCreateDisposition = OPEN_EXISTING;
1092     else
1093         dwCreateDisposition = CREATE_NEW;
1094
1095     handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
1096                          dwCreateDisposition, 0, NULL);
1097
1098     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
1099
1100     return (INT_PTR)handle;
1101 }
1102
1103 static UINT fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
1104 {
1105     HANDLE handle = (HANDLE)hf;
1106     DWORD dwRead;
1107     BOOL res;
1108     
1109     res = ReadFile(handle, memory, cb, &dwRead, NULL);
1110     ok(res, "Failed to ReadFile\n");
1111
1112     return dwRead;
1113 }
1114
1115 static UINT fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
1116 {
1117     HANDLE handle = (HANDLE)hf;
1118     DWORD dwWritten;
1119     BOOL res;
1120
1121     res = WriteFile(handle, memory, cb, &dwWritten, NULL);
1122     ok(res, "Failed to WriteFile\n");
1123
1124     return dwWritten;
1125 }
1126
1127 static int fci_close(INT_PTR hf, int *err, void *pv)
1128 {
1129     HANDLE handle = (HANDLE)hf;
1130     ok(CloseHandle(handle), "Failed to CloseHandle\n");
1131
1132     return 0;
1133 }
1134
1135 static long fci_seek(INT_PTR hf, long dist, int seektype, int *err, void *pv)
1136 {
1137     HANDLE handle = (HANDLE)hf;
1138     DWORD ret;
1139     
1140     ret = SetFilePointer(handle, dist, NULL, seektype);
1141     ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
1142
1143     return ret;
1144 }
1145
1146 static int fci_delete(char *pszFile, int *err, void *pv)
1147 {
1148     BOOL ret = DeleteFileA(pszFile);
1149     ok(ret, "Failed to DeleteFile %s\n", pszFile);
1150
1151     return 0;
1152 }
1153
1154 static void init_functionpointers(void)
1155 {
1156     HMODULE hmsi = GetModuleHandleA("msi.dll");
1157
1158 #define GET_PROC(func) \
1159     p ## func = (void*)GetProcAddress(hmsi, #func); \
1160     if(!p ## func) \
1161       trace("GetProcAddress(%s) failed\n", #func);
1162
1163     GET_PROC(MsiQueryComponentStateA);
1164     GET_PROC(MsiSourceListEnumSourcesA);
1165     GET_PROC(MsiSourceListGetInfoA);
1166
1167 #undef GET_PROC
1168 }
1169
1170 static void get_user_sid(LPSTR *usersid)
1171 {
1172     HANDLE token;
1173     BYTE buf[1024];
1174     DWORD size;
1175     PTOKEN_USER user;
1176     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
1177     static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
1178
1179     *usersid = NULL;
1180     pConvertSidToStringSidA = (void *)GetProcAddress(hadvapi32, "ConvertSidToStringSidA");
1181     if (!pConvertSidToStringSidA)
1182         return;
1183
1184     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
1185     size = sizeof(buf);
1186     GetTokenInformation(token, TokenUser, (void *)buf, size, &size);
1187     user = (PTOKEN_USER)buf;
1188     pConvertSidToStringSidA(user->User.Sid, usersid);
1189 }
1190
1191 static BOOL check_record(MSIHANDLE rec, UINT field, LPCSTR val)
1192 {
1193     CHAR buffer[0x20];
1194     UINT r;
1195     DWORD sz;
1196
1197     sz = sizeof buffer;
1198     r = MsiRecordGetString(rec, field, buffer, &sz);
1199     return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
1200 }
1201
1202 static BOOL get_temp_file(char *pszTempName, int cbTempName, void *pv)
1203 {
1204     LPSTR tempname;
1205
1206     tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
1207     GetTempFileNameA(".", "xx", 0, tempname);
1208
1209     if (tempname && (strlen(tempname) < (unsigned)cbTempName))
1210     {
1211         lstrcpyA(pszTempName, tempname);
1212         HeapFree(GetProcessHeap(), 0, tempname);
1213         return TRUE;
1214     }
1215
1216     HeapFree(GetProcessHeap(), 0, tempname);
1217
1218     return FALSE;
1219 }
1220
1221 static INT_PTR get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
1222                              USHORT *pattribs, int *err, void *pv)
1223 {
1224     BY_HANDLE_FILE_INFORMATION finfo;
1225     FILETIME filetime;
1226     HANDLE handle;
1227     DWORD attrs;
1228     BOOL res;
1229
1230     handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
1231                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
1232
1233     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
1234
1235     res = GetFileInformationByHandle(handle, &finfo);
1236     ok(res, "Expected GetFileInformationByHandle to succeed\n");
1237    
1238     FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
1239     FileTimeToDosDateTime(&filetime, pdate, ptime);
1240
1241     attrs = GetFileAttributes(pszName);
1242     ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
1243
1244     return (INT_PTR)handle;
1245 }
1246
1247 static BOOL add_file(HFCI hfci, const char *file, TCOMP compress)
1248 {
1249     char path[MAX_PATH];
1250     char filename[MAX_PATH];
1251
1252     lstrcpyA(path, CURR_DIR);
1253     lstrcatA(path, "\\");
1254     lstrcatA(path, file);
1255
1256     lstrcpyA(filename, file);
1257
1258     return FCIAddFile(hfci, path, filename, FALSE, get_next_cabinet,
1259                       progress, get_open_info, compress);
1260 }
1261
1262 static void set_cab_parameters(PCCAB pCabParams, const CHAR *name, DWORD max_size)
1263 {
1264     ZeroMemory(pCabParams, sizeof(CCAB));
1265
1266     pCabParams->cb = max_size;
1267     pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
1268     pCabParams->setID = 0xbeef;
1269     pCabParams->iCab = 1;
1270     lstrcpyA(pCabParams->szCabPath, CURR_DIR);
1271     lstrcatA(pCabParams->szCabPath, "\\");
1272     lstrcpyA(pCabParams->szCab, name);
1273 }
1274
1275 static void create_cab_file(const CHAR *name, DWORD max_size, const CHAR *files)
1276 {
1277     CCAB cabParams;
1278     LPCSTR ptr;
1279     HFCI hfci;
1280     ERF erf;
1281     BOOL res;
1282
1283     set_cab_parameters(&cabParams, name, max_size);
1284
1285     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1286                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1287                       get_temp_file, &cabParams, NULL);
1288
1289     ok(hfci != NULL, "Failed to create an FCI context\n");
1290
1291     ptr = files;
1292     while (*ptr)
1293     {
1294         res = add_file(hfci, ptr, tcompTYPE_MSZIP);
1295         ok(res, "Failed to add file: %s\n", ptr);
1296         ptr += lstrlen(ptr) + 1;
1297     }
1298
1299     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1300     ok(res, "Failed to flush the cabinet\n");
1301
1302     res = FCIDestroy(hfci);
1303     ok(res, "Failed to destroy the cabinet\n");
1304 }
1305
1306 static BOOL get_program_files_dir(LPSTR buf, LPSTR buf2)
1307 {
1308     HKEY hkey;
1309     DWORD type, size;
1310
1311     if (RegOpenKey(HKEY_LOCAL_MACHINE,
1312                    "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
1313         return FALSE;
1314
1315     size = MAX_PATH;
1316     if (RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)buf, &size)) {
1317         RegCloseKey(hkey);
1318         return FALSE;
1319     }
1320
1321     size = MAX_PATH;
1322     if (RegQueryValueExA(hkey, "CommonFilesDir", 0, &type, (LPBYTE)buf2, &size)) {
1323         RegCloseKey(hkey);
1324         return FALSE;
1325     }
1326
1327     RegCloseKey(hkey);
1328     return TRUE;
1329 }
1330
1331 static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
1332 {
1333     HANDLE file;
1334     DWORD written;
1335
1336     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1337     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
1338     WriteFile(file, data, strlen(data), &written, NULL);
1339
1340     if (size)
1341     {
1342         SetFilePointer(file, size, NULL, FILE_BEGIN);
1343         SetEndOfFile(file);
1344     }
1345
1346     CloseHandle(file);
1347 }
1348
1349 #define create_file(name, size) create_file_data(name, name, size)
1350
1351 static void create_test_files(void)
1352 {
1353     CreateDirectoryA("msitest", NULL);
1354     create_file("msitest\\one.txt", 100);
1355     CreateDirectoryA("msitest\\first", NULL);
1356     create_file("msitest\\first\\two.txt", 100);
1357     CreateDirectoryA("msitest\\second", NULL);
1358     create_file("msitest\\second\\three.txt", 100);
1359
1360     create_file("four.txt", 100);
1361     create_file("five.txt", 100);
1362     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1363
1364     create_file("msitest\\filename", 100);
1365     create_file("msitest\\service.exe", 100);
1366
1367     DeleteFileA("four.txt");
1368     DeleteFileA("five.txt");
1369 }
1370
1371 static BOOL delete_pf(const CHAR *rel_path, BOOL is_file)
1372 {
1373     CHAR path[MAX_PATH];
1374
1375     lstrcpyA(path, PROG_FILES_DIR);
1376     lstrcatA(path, "\\");
1377     lstrcatA(path, rel_path);
1378
1379     if (is_file)
1380         return DeleteFileA(path);
1381     else
1382         return RemoveDirectoryA(path);
1383 }
1384
1385 static BOOL delete_cf(const CHAR *rel_path, BOOL is_file)
1386 {
1387     CHAR path[MAX_PATH];
1388
1389     lstrcpyA(path, COMMON_FILES_DIR);
1390     lstrcatA(path, "\\");
1391     lstrcatA(path, rel_path);
1392
1393     if (is_file)
1394         return DeleteFileA(path);
1395     else
1396         return RemoveDirectoryA(path);
1397 }
1398
1399 static void delete_test_files(void)
1400 {
1401     DeleteFileA("msitest.msi");
1402     DeleteFileA("msitest.cab");
1403     DeleteFileA("msitest\\second\\three.txt");
1404     DeleteFileA("msitest\\first\\two.txt");
1405     DeleteFileA("msitest\\one.txt");
1406     DeleteFileA("msitest\\service.exe");
1407     DeleteFileA("msitest\\filename");
1408     RemoveDirectoryA("msitest\\second");
1409     RemoveDirectoryA("msitest\\first");
1410     RemoveDirectoryA("msitest");
1411 }
1412
1413 static void write_file(const CHAR *filename, const char *data, int data_size)
1414 {
1415     DWORD size;
1416
1417     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
1418                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1419
1420     WriteFile(hf, data, data_size, &size, NULL);
1421     CloseHandle(hf);
1422 }
1423
1424 static void write_msi_summary_info(MSIHANDLE db)
1425 {
1426     MSIHANDLE summary;
1427     UINT r;
1428
1429     r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
1430     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1431
1432     r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, ";1033");
1433     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1434
1435     r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1436                                    "{004757CA-5092-49c2-AD20-28E1CE0DF5F2}");
1437     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1438
1439     r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
1440     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1441
1442     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 0, NULL, NULL);
1443     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1444
1445     r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
1446     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1447
1448     /* write the summary changes back to the stream */
1449     r = MsiSummaryInfoPersist(summary);
1450     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1451
1452     MsiCloseHandle(summary);
1453 }
1454
1455 static void create_database(const CHAR *name, const msi_table *tables, int num_tables)
1456 {
1457     MSIHANDLE db;
1458     UINT r;
1459     int j;
1460
1461     r = MsiOpenDatabaseA(name, MSIDBOPEN_CREATE, &db);
1462     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1463
1464     /* import the tables into the database */
1465     for (j = 0; j < num_tables; j++)
1466     {
1467         const msi_table *table = &tables[j];
1468
1469         write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
1470
1471         r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
1472         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1473
1474         DeleteFileA(table->filename);
1475     }
1476
1477     write_msi_summary_info(db);
1478
1479     r = MsiDatabaseCommit(db);
1480     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1481
1482     MsiCloseHandle(db);
1483 }
1484
1485 static void check_service_is_installed(void)
1486 {
1487     SC_HANDLE scm, service;
1488     BOOL res;
1489
1490     scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1491     ok(scm != NULL, "Failed to open the SC Manager\n");
1492
1493     service = OpenService(scm, "TestService", SC_MANAGER_ALL_ACCESS);
1494     ok(service != NULL, "Failed to open TestService\n");
1495
1496     res = DeleteService(service);
1497     ok(res, "Failed to delete TestService\n");
1498
1499     CloseServiceHandle(service);
1500     CloseServiceHandle(scm);
1501 }
1502
1503 static void test_MsiInstallProduct(void)
1504 {
1505     UINT r;
1506     CHAR path[MAX_PATH];
1507     LONG res;
1508     HKEY hkey;
1509     DWORD num, size, type;
1510     SC_HANDLE scm;
1511
1512     scm = OpenSCManager(NULL, NULL, GENERIC_ALL);
1513     if (!scm && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1514     {
1515         skip("Services are not implemented, we are most likely on win9x\n");
1516         return;
1517     }
1518     CloseServiceHandle(scm);
1519
1520     create_test_files();
1521     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1522
1523     r = MsiInstallProductA(msifile, NULL);
1524     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1525
1526     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
1527     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
1528     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
1529     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
1530     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
1531     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
1532     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
1533     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
1534     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
1535     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
1536     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
1537     ok(delete_pf("msitest", FALSE), "File not installed\n");
1538
1539     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
1540     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1541
1542     size = MAX_PATH;
1543     type = REG_SZ;
1544     res = RegQueryValueExA(hkey, "Name", NULL, &type, (LPBYTE)path, &size);
1545     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1546     ok(!lstrcmpA(path, "imaname"), "Expected imaname, got %s\n", path);
1547
1548     size = MAX_PATH;
1549     type = REG_SZ;
1550     res = RegQueryValueExA(hkey, "blah", NULL, &type, (LPBYTE)path, &size);
1551     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
1552
1553     size = sizeof(num);
1554     type = REG_DWORD;
1555     res = RegQueryValueExA(hkey, "number", NULL, &type, (LPBYTE)&num, &size);
1556     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1557     ok(num == 314, "Expected 314, got %d\n", num);
1558
1559     size = MAX_PATH;
1560     type = REG_SZ;
1561     res = RegQueryValueExA(hkey, "OrderTestName", NULL, &type, (LPBYTE)path, &size);
1562     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1563     ok(!lstrcmpA(path, "OrderTestValue"), "Expected imaname, got %s\n", path);
1564
1565     check_service_is_installed();
1566
1567     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
1568
1569     delete_test_files();
1570 }
1571
1572 static void test_MsiSetComponentState(void)
1573 {
1574     INSTALLSTATE installed, action;
1575     MSIHANDLE package;
1576     char path[MAX_PATH];
1577     UINT r;
1578
1579     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1580
1581     CoInitialize(NULL);
1582
1583     lstrcpy(path, CURR_DIR);
1584     lstrcat(path, "\\");
1585     lstrcat(path, msifile);
1586
1587     r = MsiOpenPackage(path, &package);
1588     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1589
1590     r = MsiDoAction(package, "CostInitialize");
1591     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1592
1593     r = MsiDoAction(package, "FileCost");
1594     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1595
1596     r = MsiDoAction(package, "CostFinalize");
1597     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1598
1599     r = MsiGetComponentState(package, "dangler", &installed, &action);
1600     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1601     ok(installed == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", installed);
1602     ok(action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1603
1604     r = MsiSetComponentState(package, "dangler", INSTALLSTATE_SOURCE);
1605     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1606
1607     MsiCloseHandle(package);
1608     CoUninitialize();
1609
1610     DeleteFileA(msifile);
1611 }
1612
1613 static void test_packagecoltypes(void)
1614 {
1615     MSIHANDLE hdb, view, rec;
1616     char path[MAX_PATH];
1617     LPCSTR query;
1618     UINT r, count;
1619
1620     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1621
1622     CoInitialize(NULL);
1623
1624     lstrcpy(path, CURR_DIR);
1625     lstrcat(path, "\\");
1626     lstrcat(path, msifile);
1627
1628     r = MsiOpenDatabase(path, MSIDBOPEN_READONLY, &hdb);
1629     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1630
1631     query = "SELECT * FROM `Media`";
1632     r = MsiDatabaseOpenView( hdb, query, &view );
1633     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1634
1635     r = MsiViewGetColumnInfo( view, MSICOLINFO_NAMES, &rec );
1636     count = MsiRecordGetFieldCount( rec );
1637     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1638     ok(count == 6, "Expected 6, got %d\n", count);
1639     ok(check_record(rec, 1, "DiskId"), "wrong column label\n");
1640     ok(check_record(rec, 2, "LastSequence"), "wrong column label\n");
1641     ok(check_record(rec, 3, "DiskPrompt"), "wrong column label\n");
1642     ok(check_record(rec, 4, "Cabinet"), "wrong column label\n");
1643     ok(check_record(rec, 5, "VolumeLabel"), "wrong column label\n");
1644     ok(check_record(rec, 6, "Source"), "wrong column label\n");
1645     MsiCloseHandle(rec);
1646
1647     r = MsiViewGetColumnInfo( view, MSICOLINFO_TYPES, &rec );
1648     count = MsiRecordGetFieldCount( rec );
1649     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1650     ok(count == 6, "Expected 6, got %d\n", count);
1651     ok(check_record(rec, 1, "i2"), "wrong column label\n");
1652     ok(check_record(rec, 2, "i4"), "wrong column label\n");
1653     ok(check_record(rec, 3, "L64"), "wrong column label\n");
1654     ok(check_record(rec, 4, "S255"), "wrong column label\n");
1655     ok(check_record(rec, 5, "S32"), "wrong column label\n");
1656     ok(check_record(rec, 6, "S72"), "wrong column label\n");
1657
1658     MsiCloseHandle(rec);
1659     MsiCloseHandle(view);
1660     MsiCloseHandle(hdb);
1661     DeleteFile(msifile);
1662 }
1663
1664 static void create_cc_test_files(void)
1665 {
1666     CCAB cabParams;
1667     HFCI hfci;
1668     ERF erf;
1669     static CHAR cab_context[] = "test%d.cab";
1670     BOOL res;
1671
1672     create_file("maximus", 500);
1673     create_file("augustus", 50000);
1674     create_file("tiberius", 500);
1675     create_file("caesar", 500);
1676
1677     set_cab_parameters(&cabParams, "test1.cab", 40000);
1678
1679     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1680                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1681                       get_temp_file, &cabParams, cab_context);
1682     ok(hfci != NULL, "Failed to create an FCI context\n");
1683
1684     res = add_file(hfci, "maximus", tcompTYPE_NONE);
1685     ok(res, "Failed to add file maximus\n");
1686
1687     res = add_file(hfci, "augustus", tcompTYPE_NONE);
1688     ok(res, "Failed to add file augustus\n");
1689
1690     res = add_file(hfci, "tiberius", tcompTYPE_NONE);
1691     ok(res, "Failed to add file tiberius\n");
1692
1693     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1694     ok(res, "Failed to flush the cabinet\n");
1695
1696     res = FCIDestroy(hfci);
1697     ok(res, "Failed to destroy the cabinet\n");
1698
1699     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1700
1701     DeleteFile("maximus");
1702     DeleteFile("augustus");
1703     DeleteFile("tiberius");
1704     DeleteFile("caesar");
1705 }
1706
1707 static void delete_cab_files(void)
1708 {
1709     SHFILEOPSTRUCT shfl;
1710     CHAR path[MAX_PATH+10];
1711
1712     lstrcpyA(path, CURR_DIR);
1713     lstrcatA(path, "\\*.cab");
1714     path[strlen(path) + 1] = '\0';
1715
1716     shfl.hwnd = NULL;
1717     shfl.wFunc = FO_DELETE;
1718     shfl.pFrom = path;
1719     shfl.pTo = NULL;
1720     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
1721
1722     SHFileOperation(&shfl);
1723 }
1724
1725 static void test_continuouscabs(void)
1726 {
1727     UINT r;
1728
1729     create_cc_test_files();
1730     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1731
1732     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1733
1734     r = MsiInstallProductA(msifile, NULL);
1735     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
1736     {
1737         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1738         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1739         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1740         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1741         ok(delete_pf("msitest", FALSE), "File not installed\n");
1742     }
1743
1744     delete_cab_files();
1745     DeleteFile(msifile);
1746
1747     create_cc_test_files();
1748     create_database(msifile, cc2_tables, sizeof(cc2_tables) / sizeof(msi_table));
1749
1750     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1751
1752     r = MsiInstallProductA(msifile, NULL);
1753     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1754     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1755     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
1756     ok(delete_pf("msitest\\tiberius", TRUE), "File not installed\n");
1757     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1758     ok(delete_pf("msitest", FALSE), "File not installed\n");
1759
1760     delete_cab_files();
1761     DeleteFile(msifile);
1762 }
1763
1764 static void test_caborder(void)
1765 {
1766     UINT r;
1767
1768     create_file("imperator", 100);
1769     create_file("maximus", 500);
1770     create_file("augustus", 50000);
1771     create_file("caesar", 500);
1772
1773     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1774
1775     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1776
1777     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
1778     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
1779     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1780
1781     r = MsiInstallProductA(msifile, NULL);
1782     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1783     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1784     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1785     todo_wine
1786     {
1787         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1788         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1789     }
1790
1791     delete_cab_files();
1792
1793     create_cab_file("test1.cab", MEDIA_SIZE, "imperator\0");
1794     create_cab_file("test2.cab", MEDIA_SIZE, "maximus\0augustus\0");
1795     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1796
1797     r = MsiInstallProductA(msifile, NULL);
1798     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1799     ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1800     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1801     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1802     todo_wine
1803     {
1804         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1805     }
1806
1807     delete_cab_files();
1808     DeleteFile(msifile);
1809
1810     create_cc_test_files();
1811     create_database(msifile, co_tables, sizeof(co_tables) / sizeof(msi_table));
1812
1813     r = MsiInstallProductA(msifile, NULL);
1814     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1815     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1816     ok(!delete_pf("msitest", FALSE), "File is installed\n");
1817     todo_wine
1818     {
1819         ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1820         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1821     }
1822
1823     delete_cab_files();
1824     DeleteFile(msifile);
1825
1826     create_cc_test_files();
1827     create_database(msifile, co2_tables, sizeof(co2_tables) / sizeof(msi_table));
1828
1829     r = MsiInstallProductA(msifile, NULL);
1830     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1831     todo_wine
1832     {
1833         ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1834         ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1835         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1836         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1837     }
1838
1839     delete_cab_files();
1840     DeleteFile("imperator");
1841     DeleteFile("maximus");
1842     DeleteFile("augustus");
1843     DeleteFile("caesar");
1844     DeleteFile(msifile);
1845 }
1846
1847 static void test_mixedmedia(void)
1848 {
1849     UINT r;
1850
1851     CreateDirectoryA("msitest", NULL);
1852     create_file("msitest\\maximus", 500);
1853     create_file("msitest\\augustus", 500);
1854     create_file("caesar", 500);
1855
1856     create_database(msifile, mm_tables, sizeof(mm_tables) / sizeof(msi_table));
1857
1858     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1859
1860     create_cab_file("test1.cab", MEDIA_SIZE, "caesar\0");
1861
1862     r = MsiInstallProductA(msifile, NULL);
1863     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1864     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1865     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1866     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1867     ok(delete_pf("msitest", FALSE), "File not installed\n");
1868
1869     /* Delete the files in the temp (current) folder */
1870     DeleteFile("msitest\\maximus");
1871     DeleteFile("msitest\\augustus");
1872     RemoveDirectory("msitest");
1873     DeleteFile("caesar");
1874     DeleteFile("test1.cab");
1875     DeleteFile(msifile);
1876 }
1877
1878 static void test_samesequence(void)
1879 {
1880     UINT r;
1881
1882     create_cc_test_files();
1883     create_database(msifile, ss_tables, sizeof(ss_tables) / sizeof(msi_table));
1884
1885     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1886
1887     r = MsiInstallProductA(msifile, NULL);
1888     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
1889     {
1890         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1891         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1892         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1893         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1894         ok(delete_pf("msitest", FALSE), "File not installed\n");
1895     }
1896
1897     delete_cab_files();
1898     DeleteFile(msifile);
1899 }
1900
1901 static void test_uiLevelFlags(void)
1902 {
1903     UINT r;
1904
1905     create_cc_test_files();
1906     create_database(msifile, ui_tables, sizeof(ui_tables) / sizeof(msi_table));
1907
1908     MsiSetInternalUI(INSTALLUILEVEL_NONE | INSTALLUILEVEL_SOURCERESONLY, NULL);
1909
1910     r = MsiInstallProductA(msifile, NULL);
1911     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
1912     {
1913         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1914         ok(!delete_pf("msitest\\maximus", TRUE), "UI install occurred, but execute-only was requested.\n");
1915         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1916         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1917         ok(delete_pf("msitest", FALSE), "File not installed\n");
1918     }
1919
1920     delete_cab_files();
1921     DeleteFile(msifile);
1922 }
1923
1924 static BOOL file_matches(LPSTR path)
1925 {
1926     CHAR buf[MAX_PATH];
1927     HANDLE file;
1928     DWORD size;
1929
1930     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1931                       NULL, OPEN_EXISTING, 0, NULL);
1932
1933     ZeroMemory(buf, MAX_PATH);
1934     ReadFile(file, buf, 15, &size, NULL);
1935     CloseHandle(file);
1936
1937     return !lstrcmp(buf, "msitest\\maximus");
1938 }
1939
1940 static void test_readonlyfile(void)
1941 {
1942     UINT r;
1943     DWORD size;
1944     HANDLE file;
1945     CHAR path[MAX_PATH];
1946
1947     CreateDirectoryA("msitest", NULL);
1948     create_file("msitest\\maximus", 500);
1949     create_database(msifile, rof_tables, sizeof(rof_tables) / sizeof(msi_table));
1950
1951     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1952
1953     lstrcpy(path, PROG_FILES_DIR);
1954     lstrcat(path, "\\msitest");
1955     CreateDirectory(path, NULL);
1956
1957     lstrcat(path, "\\maximus");
1958     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1959                       NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
1960
1961     WriteFile(file, "readonlyfile", 20, &size, NULL);
1962     CloseHandle(file);
1963
1964     r = MsiInstallProductA(msifile, NULL);
1965     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1966     ok(file_matches(path), "Expected file to be overwritten\n");
1967     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1968     ok(delete_pf("msitest", FALSE), "File not installed\n");
1969
1970     /* Delete the files in the temp (current) folder */
1971     DeleteFile("msitest\\maximus");
1972     RemoveDirectory("msitest");
1973     DeleteFile(msifile);
1974 }
1975
1976 static void test_setdirproperty(void)
1977 {
1978     UINT r;
1979
1980     CreateDirectoryA("msitest", NULL);
1981     create_file("msitest\\maximus", 500);
1982     create_database(msifile, sdp_tables, sizeof(sdp_tables) / sizeof(msi_table));
1983
1984     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1985
1986     r = MsiInstallProductA(msifile, NULL);
1987     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1988     ok(delete_cf("msitest\\maximus", TRUE), "File not installed\n");
1989     ok(delete_cf("msitest", FALSE), "File not installed\n");
1990
1991     /* Delete the files in the temp (current) folder */
1992     DeleteFile(msifile);
1993     DeleteFile("msitest\\maximus");
1994     RemoveDirectory("msitest");
1995 }
1996
1997 static void test_cabisextracted(void)
1998 {
1999     UINT r;
2000
2001     CreateDirectoryA("msitest", NULL);
2002     create_file("msitest\\gaius", 500);
2003     create_file("maximus", 500);
2004     create_file("augustus", 500);
2005     create_file("caesar", 500);
2006
2007     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
2008     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
2009     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
2010
2011     create_database(msifile, cie_tables, sizeof(cie_tables) / sizeof(msi_table));
2012
2013     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2014
2015     r = MsiInstallProductA(msifile, NULL);
2016     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2017     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2018     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2019     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2020     ok(delete_pf("msitest\\gaius", TRUE), "File not installed\n");
2021     ok(delete_pf("msitest", FALSE), "File not installed\n");
2022
2023     /* Delete the files in the temp (current) folder */
2024     delete_cab_files();
2025     DeleteFile(msifile);
2026     DeleteFile("maximus");
2027     DeleteFile("augustus");
2028     DeleteFile("caesar");
2029     DeleteFile("msitest\\gaius");
2030     RemoveDirectory("msitest");
2031 }
2032
2033 static void test_concurrentinstall(void)
2034 {
2035     UINT r;
2036     CHAR path[MAX_PATH];
2037
2038     CreateDirectoryA("msitest", NULL);
2039     CreateDirectoryA("msitest\\msitest", NULL);
2040     create_file("msitest\\maximus", 500);
2041     create_file("msitest\\msitest\\augustus", 500);
2042
2043     create_database(msifile, ci_tables, sizeof(ci_tables) / sizeof(msi_table));
2044
2045     lstrcpyA(path, CURR_DIR);
2046     lstrcatA(path, "\\msitest\\concurrent.msi");
2047     create_database(path, ci2_tables, sizeof(ci2_tables) / sizeof(msi_table));
2048
2049     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2050
2051     r = MsiInstallProductA(msifile, NULL);
2052     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2053     if (!delete_pf("msitest\\augustus", TRUE))
2054         trace("concurrent installs not supported\n");
2055     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2056     ok(delete_pf("msitest", FALSE), "File not installed\n");
2057
2058     DeleteFile(path);
2059
2060     r = MsiInstallProductA(msifile, NULL);
2061     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2062     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2063     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2064     ok(delete_pf("msitest", FALSE), "File not installed\n");
2065
2066     DeleteFile(msifile);
2067     DeleteFile("msitest\\msitest\\augustus");
2068     DeleteFile("msitest\\maximus");
2069     RemoveDirectory("msitest\\msitest");
2070     RemoveDirectory("msitest");
2071 }
2072
2073 static void test_setpropertyfolder(void)
2074 {
2075     UINT r;
2076     CHAR path[MAX_PATH];
2077
2078     lstrcpyA(path, PROG_FILES_DIR);
2079     lstrcatA(path, "\\msitest\\added");
2080
2081     CreateDirectoryA("msitest", NULL);
2082     create_file("msitest\\maximus", 500);
2083
2084     create_database(msifile, spf_tables, sizeof(spf_tables) / sizeof(msi_table));
2085
2086     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2087
2088     r = MsiInstallProductA(msifile, NULL);
2089     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2090     if (GetFileAttributesA(path) == FILE_ATTRIBUTE_DIRECTORY)
2091     {
2092         ok(delete_pf("msitest\\added\\maximus", TRUE), "File not installed\n");
2093         ok(delete_pf("msitest\\added", FALSE), "File not installed\n");
2094         ok(delete_pf("msitest", FALSE), "File not installed\n");
2095     }
2096     else
2097     {
2098         trace("changing folder property not supported\n");
2099         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2100         ok(delete_pf("msitest", FALSE), "File not installed\n");
2101     }
2102
2103     /* Delete the files in the temp (current) folder */
2104     DeleteFile(msifile);
2105     DeleteFile("msitest\\maximus");
2106     RemoveDirectory("msitest");
2107 }
2108
2109 static BOOL file_exists(LPCSTR file)
2110 {
2111     return GetFileAttributes(file) != INVALID_FILE_ATTRIBUTES;
2112 }
2113
2114 static BOOL pf_exists(LPCSTR file)
2115 {
2116     CHAR path[MAX_PATH];
2117
2118     lstrcpyA(path, PROG_FILES_DIR);
2119     lstrcatA(path, "\\");
2120     lstrcatA(path, file);
2121
2122     return file_exists(path);
2123 }
2124
2125 static void delete_pfmsitest_files(void)
2126 {
2127     SHFILEOPSTRUCT shfl;
2128     CHAR path[MAX_PATH+11];
2129
2130     lstrcpyA(path, PROG_FILES_DIR);
2131     lstrcatA(path, "\\msitest\\*");
2132     path[strlen(path) + 1] = '\0';
2133
2134     shfl.hwnd = NULL;
2135     shfl.wFunc = FO_DELETE;
2136     shfl.pFrom = path;
2137     shfl.pTo = NULL;
2138     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
2139
2140     SHFileOperation(&shfl);
2141
2142     lstrcpyA(path, PROG_FILES_DIR);
2143     lstrcatA(path, "\\msitest");
2144     RemoveDirectoryA(path);
2145 }
2146
2147 static void check_reg_str(HKEY prodkey, LPCSTR name, LPCSTR expected, BOOL bcase, DWORD line)
2148 {
2149     char val[MAX_PATH];
2150     DWORD size, type;
2151     LONG res;
2152
2153     size = MAX_PATH;
2154     val[0] = '\0';
2155     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)val, &size);
2156
2157     if (res != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ))
2158     {
2159         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2160         return;
2161     }
2162
2163     if (!expected)
2164         ok_(__FILE__, line)(lstrlenA(val) == 0, "Expected empty string, got %s\n", val);
2165     else
2166     {
2167         if (bcase)
2168             ok_(__FILE__, line)(!lstrcmpA(val, expected), "Expected %s, got %s\n", expected, val);
2169         else
2170             ok_(__FILE__, line)(!lstrcmpiA(val, expected), "Expected %s, got %s\n", expected, val);
2171     }
2172 }
2173
2174 static void check_reg_dword(HKEY prodkey, LPCSTR name, DWORD expected, DWORD line)
2175 {
2176     DWORD val, size, type;
2177     LONG res;
2178
2179     size = sizeof(DWORD);
2180     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)&val, &size);
2181
2182     if (res != ERROR_SUCCESS || type != REG_DWORD)
2183     {
2184         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2185         return;
2186     }
2187
2188     ok_(__FILE__, line)(val == expected, "Expected %d, got %d\n", expected, val);
2189 }
2190
2191 #define CHECK_REG_STR(prodkey, name, expected) \
2192     check_reg_str(prodkey, name, expected, TRUE, __LINE__);
2193
2194 #define CHECK_REG_ISTR(prodkey, name, expected) \
2195     check_reg_str(prodkey, name, expected, FALSE, __LINE__);
2196
2197 #define CHECK_REG_DWORD(prodkey, name, expected) \
2198     check_reg_dword(prodkey, name, expected, __LINE__);
2199
2200 static void get_date_str(LPSTR date)
2201 {
2202     SYSTEMTIME systime;
2203
2204     static const char date_fmt[] = "%d%02d%02d";
2205     GetLocalTime(&systime);
2206     sprintf(date, date_fmt, systime.wYear, systime.wMonth, systime.wDay);
2207 }
2208
2209 static void test_publish_registerproduct(void)
2210 {
2211     UINT r;
2212     LONG res;
2213     HKEY uninstall, prodkey;
2214     INSTALLSTATE state;
2215     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2216     char date[MAX_PATH];
2217     char temp[MAX_PATH];
2218
2219     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2220
2221     if (!pMsiQueryComponentStateA)
2222     {
2223         skip("MsiQueryComponentStateA is not available\n");
2224         return;
2225     }
2226
2227     get_date_str(date);
2228     GetTempPath(MAX_PATH, temp);
2229
2230     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2231     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2232
2233     CreateDirectoryA("msitest", NULL);
2234     create_file("msitest\\maximus", 500);
2235
2236     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2237
2238     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2239
2240     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2241     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2242
2243     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2244     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2245
2246     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2247     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2248
2249     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2250                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2251     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2252     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2253
2254     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2255     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2256
2257     /* RegisterProduct */
2258     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
2259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2260     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2261     ok(pf_exists("msitest"), "File not installed\n");
2262
2263     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2264     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2265
2266     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2267     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2268
2269     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2270     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2271
2272     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2273                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2274     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2275     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2276
2277     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2278     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2279
2280     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
2281     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
2282     CHECK_REG_STR(prodkey, "InstallDate", date);
2283     CHECK_REG_STR(prodkey, "InstallSource", temp);
2284     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2285     CHECK_REG_STR(prodkey, "Publisher", "Wine");
2286     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2287     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
2288     CHECK_REG_STR(prodkey, "Comments", NULL);
2289     CHECK_REG_STR(prodkey, "Contact", NULL);
2290     CHECK_REG_STR(prodkey, "HelpLink", NULL);
2291     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
2292     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
2293     CHECK_REG_STR(prodkey, "Readme", NULL);
2294     CHECK_REG_STR(prodkey, "Size", NULL);
2295     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
2296     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
2297     CHECK_REG_DWORD(prodkey, "Language", 1033);
2298     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
2299     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
2300     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
2301     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
2302     todo_wine
2303     {
2304         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
2305     }
2306
2307     RegCloseKey(prodkey);
2308
2309     /* try to uninstall after RegisterProduct */
2310     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2311     todo_wine
2312     {
2313         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2314     }
2315     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2316     ok(pf_exists("msitest"), "File deleted\n");
2317
2318     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2319     todo_wine
2320     {
2321         ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2322     }
2323
2324     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2325     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2326
2327     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2328     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2329
2330     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2331                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2332     todo_wine
2333     {
2334         ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2335     }
2336     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2337
2338     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2339     todo_wine
2340     {
2341         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2342     }
2343
2344     todo_wine
2345     {
2346         CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
2347         CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
2348         CHECK_REG_STR(prodkey, "InstallDate", date);
2349         CHECK_REG_STR(prodkey, "InstallSource", temp);
2350         CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2351         CHECK_REG_STR(prodkey, "Publisher", "Wine");
2352         CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2353         CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
2354         CHECK_REG_STR(prodkey, "Comments", NULL);
2355         CHECK_REG_STR(prodkey, "Contact", NULL);
2356         CHECK_REG_STR(prodkey, "HelpLink", NULL);
2357         CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
2358         CHECK_REG_STR(prodkey, "InstallLocation", NULL);
2359         CHECK_REG_STR(prodkey, "Readme", NULL);
2360         CHECK_REG_STR(prodkey, "Size", NULL);
2361         CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
2362         CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
2363         CHECK_REG_DWORD(prodkey, "Language", 1033);
2364         CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
2365         CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
2366         CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
2367         CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
2368         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
2369     }
2370
2371     RegCloseKey(prodkey);
2372
2373     /* full install to remove */
2374     r = MsiInstallProductA(msifile, "FULL=1");
2375     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2376     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2377     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2378
2379     RegCloseKey(uninstall);
2380     DeleteFile(msifile);
2381     DeleteFile("msitest\\maximus");
2382     RemoveDirectory("msitest");
2383     delete_pfmsitest_files();
2384 }
2385
2386 static void test_publish_publishproduct(void)
2387 {
2388     UINT r;
2389     LONG res;
2390     HKEY uninstall, prodkey;
2391     INSTALLSTATE state;
2392     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2393
2394     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2395
2396     if (!pMsiQueryComponentStateA)
2397     {
2398         skip("MsiQueryComponentStateA is not available\n");
2399         return;
2400     }
2401
2402     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2403     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2404
2405     CreateDirectoryA("msitest", NULL);
2406     create_file("msitest\\maximus", 500);
2407
2408     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2409
2410     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2411
2412     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2413     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2414
2415     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2416     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2417
2418     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2419     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2420
2421     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2422                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2423     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2424     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2425
2426     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2427     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2428
2429     /* PublishProduct */
2430     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
2431     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2432     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2433     ok(pf_exists("msitest"), "File not installed\n");
2434
2435     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2436     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2437
2438     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2439     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2440
2441     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2442     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2443
2444     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2445                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2446     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2447     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2448
2449     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2450     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2451
2452     /* try to uninstall after PublishProduct */
2453     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2454     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2455     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2456     ok(pf_exists("msitest"), "File deleted\n");
2457
2458     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2459     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2460
2461     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2462     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2463
2464     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2465     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2466
2467     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2468                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2469     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2470     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2471
2472     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2473     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2474
2475     /* full install to remove */
2476     r = MsiInstallProductA(msifile, "FULL=1");
2477     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2478     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2479     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2480
2481     RegCloseKey(uninstall);
2482     DeleteFile(msifile);
2483     DeleteFile("msitest\\maximus");
2484     RemoveDirectory("msitest");
2485     delete_pfmsitest_files();
2486 }
2487
2488 static void test_publish_publishfeatures(void)
2489 {
2490     UINT r;
2491     LONG res;
2492     HKEY hkey;
2493     LPSTR usersid;
2494     CHAR keypath[MAX_PATH];
2495
2496     static const CHAR cupath[] = "Software\\Microsoft\\Installer\\Features"
2497                                  "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2498     static const CHAR udpath[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2499                                  "\\Installer\\UserData\\%s\\Products"
2500                                  "\\84A88FD7F6998CE40A22FB59F6B9C2BB\\Features";
2501     static const CHAR featkey[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2502                                   "\\Installer\\Features";
2503
2504     get_user_sid(&usersid);
2505     if (!usersid)
2506     {
2507         skip("ConvertSidToStringSidA is not available\n");
2508         return;
2509     }
2510
2511     CreateDirectoryA("msitest", NULL);
2512     create_file("msitest\\maximus", 500);
2513
2514     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2515
2516     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2517
2518     /* PublishFeatures, current user */
2519     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
2520     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2521     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2522     ok(delete_pf("msitest", FALSE), "File not installed\n");
2523
2524     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, featkey, &hkey);
2525     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2526
2527     res = RegOpenKeyA(HKEY_CURRENT_USER, cupath, &hkey);
2528     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2529
2530     CHECK_REG_STR(hkey, "feature", "");
2531     CHECK_REG_STR(hkey, "montecristo", "");
2532
2533     RegDeleteValueA(hkey, "feature");
2534     RegDeleteValueA(hkey, "montecristo");
2535     RegDeleteKeyA(hkey, "");
2536     RegCloseKey(hkey);
2537
2538     sprintf(keypath, udpath, usersid);
2539     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2540     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2541
2542     CHECK_REG_STR(hkey, "feature", "VGtfp^p+,?82@JU1j_KE");
2543     CHECK_REG_STR(hkey, "montecristo", "VGtfp^p+,?82@JU1j_KE");
2544
2545     RegDeleteValueA(hkey, "feature");
2546     RegDeleteValueA(hkey, "montecristo");
2547     RegDeleteKeyA(hkey, "");
2548     RegCloseKey(hkey);
2549
2550     DeleteFile(msifile);
2551     DeleteFile("msitest\\maximus");
2552     RemoveDirectory("msitest");
2553     HeapFree(GetProcessHeap(), 0, usersid);
2554 }
2555
2556 static LPSTR reg_get_val_str(HKEY hkey, LPCSTR name)
2557 {
2558     DWORD len = 0;
2559     LPSTR val;
2560     LONG r;
2561
2562     r = RegQueryValueExA(hkey, name, NULL, NULL, NULL, &len);
2563     if (r != ERROR_SUCCESS)
2564         return NULL;
2565
2566     len += sizeof (WCHAR);
2567     val = HeapAlloc(GetProcessHeap(), 0, len);
2568     if (!val) return NULL;
2569     val[0] = 0;
2570     RegQueryValueExA(hkey, name, NULL, NULL, (LPBYTE)val, &len);
2571     return val;
2572 }
2573
2574 static void get_owner_company(LPSTR *owner, LPSTR *company)
2575 {
2576     LONG res;
2577     HKEY hkey;
2578
2579     *owner = *company = NULL;
2580
2581     res = RegOpenKeyA(HKEY_CURRENT_USER,
2582                       "Software\\Microsoft\\MS Setup (ACME)\\User Info", &hkey);
2583     if (res == ERROR_SUCCESS)
2584     {
2585         *owner = reg_get_val_str(hkey, "DefName");
2586         *company = reg_get_val_str(hkey, "DefCompany");
2587         RegCloseKey(hkey);
2588     }
2589
2590     if (!*owner || !*company)
2591     {
2592         res = RegOpenKeyA(HKEY_LOCAL_MACHINE,
2593                           "Software\\Microsoft\\Windows\\CurrentVersion", &hkey);
2594         if (res == ERROR_SUCCESS)
2595         {
2596             *owner = reg_get_val_str(hkey, "RegisteredOwner");
2597             *company = reg_get_val_str(hkey, "RegisteredOrganization");
2598             RegCloseKey(hkey);
2599         }
2600     }
2601
2602     if (!*owner || !*company)
2603     {
2604         res = RegOpenKeyA(HKEY_LOCAL_MACHINE,
2605                           "Software\\Microsoft\\Windows NT\\CurrentVersion", &hkey);
2606         if (res == ERROR_SUCCESS)
2607         {
2608             *owner = reg_get_val_str(hkey, "RegisteredOwner");
2609             *company = reg_get_val_str(hkey, "RegisteredOrganization");
2610             RegCloseKey(hkey);
2611         }
2612     }
2613 }
2614
2615 static void test_publish_registeruser(void)
2616 {
2617     UINT r;
2618     LONG res;
2619     HKEY props;
2620     LPSTR usersid;
2621     LPSTR owner, company;
2622     CHAR keypath[MAX_PATH];
2623
2624     static const CHAR keyfmt[] =
2625         "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\"
2626         "UserData\\%s\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties";
2627
2628     get_user_sid(&usersid);
2629     if (!usersid)
2630     {
2631         skip("ConvertSidToStringSidA is not available\n");
2632         return;
2633     }
2634
2635     get_owner_company(&owner, &company);
2636
2637     CreateDirectoryA("msitest", NULL);
2638     create_file("msitest\\maximus", 500);
2639
2640     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2641
2642     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2643
2644     /* RegisterUser, per-user */
2645     r = MsiInstallProductA(msifile, "REGISTER_USER=1");
2646     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2647     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2648     ok(delete_pf("msitest", FALSE), "File not installed\n");
2649
2650     sprintf(keypath, keyfmt, usersid);
2651
2652     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
2653     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2654
2655     CHECK_REG_STR(props, "ProductID", "none");
2656     CHECK_REG_STR(props, "RegCompany", company);
2657     CHECK_REG_STR(props, "RegOwner", owner);
2658
2659     RegDeleteValueA(props, "ProductID");
2660     RegDeleteValueA(props, "RegCompany");
2661     RegDeleteValueA(props, "RegOwner");
2662     RegDeleteKeyA(props, "");
2663     RegCloseKey(props);
2664
2665     /* RegisterUser, machine */
2666     r = MsiInstallProductA(msifile, "REGISTER_USER=1 ALLUSERS=1");
2667     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2668     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2669     ok(delete_pf("msitest", FALSE), "File not installed\n");
2670
2671     sprintf(keypath, keyfmt, "S-1-5-18");
2672
2673     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
2674     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2675
2676     CHECK_REG_STR(props, "ProductID", "none");
2677     CHECK_REG_STR(props, "RegCompany", company);
2678     CHECK_REG_STR(props, "RegOwner", owner);
2679
2680     RegDeleteValueA(props, "ProductID");
2681     RegDeleteValueA(props, "RegCompany");
2682     RegDeleteValueA(props, "RegOwner");
2683     RegDeleteKeyA(props, "");
2684     RegCloseKey(props);
2685
2686     HeapFree(GetProcessHeap(), 0, company);
2687     HeapFree(GetProcessHeap(), 0, owner);
2688
2689     DeleteFile(msifile);
2690     DeleteFile("msitest\\maximus");
2691     RemoveDirectory("msitest");
2692 }
2693
2694 static void test_publish_processcomponents(void)
2695 {
2696     UINT r;
2697     LONG res;
2698     DWORD size;
2699     HKEY comp, hkey;
2700     LPSTR usersid;
2701     CHAR val[MAX_PATH];
2702     CHAR keypath[MAX_PATH];
2703
2704     static const CHAR keyfmt[] =
2705         "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\"
2706         "UserData\\%s\\Components\\CBABC2FDCCB35E749A8944D8C1C098B5";
2707     static const CHAR compkey[] =
2708         "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Components";
2709
2710     get_user_sid(&usersid);
2711     if (!usersid)
2712     {
2713         skip("ConvertSidToStringSidA is not available\n");
2714         return;
2715     }
2716
2717     CreateDirectoryA("msitest", NULL);
2718     create_file("msitest\\maximus", 500);
2719
2720     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2721
2722     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2723
2724     /* ProcessComponents, per-user */
2725     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
2726     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2727     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2728     ok(delete_pf("msitest", FALSE), "File not installed\n");
2729
2730     sprintf(keypath, keyfmt, usersid);
2731
2732     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
2733     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2734
2735     size = MAX_PATH;
2736     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
2737                            NULL, NULL, (LPBYTE)val, &size);
2738     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2739     ok(!lstrcmpA(val, "C:\\Program Files\\msitest\\maximus"),
2740        "Expected \"%s\", got \"%s\"\n", "C:\\Program Files\\msitest\\maximus", val);
2741
2742     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
2743     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2744
2745     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
2746     RegDeleteKeyA(comp, "");
2747     RegCloseKey(comp);
2748
2749     /* ProcessComponents, machine */
2750     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1 ALLUSERS=1");
2751     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2752     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2753     ok(delete_pf("msitest", FALSE), "File not installed\n");
2754
2755     sprintf(keypath, keyfmt, "S-1-5-18");
2756
2757     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
2758     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2759
2760     size = MAX_PATH;
2761     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
2762                            NULL, NULL, (LPBYTE)val, &size);
2763     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2764     ok(!lstrcmpA(val, "C:\\Program Files\\msitest\\maximus"),
2765        "Expected \"%s\", got \"%s\"\n", "C:\\Program Files\\msitest\\maximus", val);
2766
2767     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
2768     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2769
2770     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
2771     RegDeleteKeyA(comp, "");
2772     RegCloseKey(comp);
2773
2774     DeleteFile(msifile);
2775     DeleteFile("msitest\\maximus");
2776     RemoveDirectory("msitest");
2777 }
2778
2779 static void test_publish(void)
2780 {
2781     UINT r;
2782     LONG res;
2783     HKEY uninstall, prodkey;
2784     INSTALLSTATE state;
2785     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2786     char date[MAX_PATH];
2787     char temp[MAX_PATH];
2788
2789     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2790
2791     if (!pMsiQueryComponentStateA)
2792     {
2793         skip("MsiQueryComponentStateA is not available\n");
2794         return;
2795     }
2796
2797     get_date_str(date);
2798     GetTempPath(MAX_PATH, temp);
2799
2800     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2801     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2802
2803     CreateDirectoryA("msitest", NULL);
2804     create_file("msitest\\maximus", 500);
2805
2806     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2807
2808     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2809
2810     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2811     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2812
2813     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2814     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2815
2816     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2817     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2818
2819     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2820                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2821     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2822     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2823
2824     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2825     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2826
2827     /* nothing published */
2828     r = MsiInstallProductA(msifile, NULL);
2829     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2830     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2831     ok(pf_exists("msitest"), "File not installed\n");
2832
2833     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2834     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2835
2836     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2837     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2838
2839     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2840     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2841
2842     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2843                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2844     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2845     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2846
2847     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2848     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2849
2850     /* PublishProduct and RegisterProduct */
2851     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1");
2852     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2853     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2854     ok(pf_exists("msitest"), "File not installed\n");
2855
2856     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2857     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2858
2859     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2860     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2861
2862     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2863     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2864
2865     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2866                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2867     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2868     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2869
2870     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2871     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2872
2873     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
2874     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
2875     CHECK_REG_STR(prodkey, "InstallDate", date);
2876     CHECK_REG_STR(prodkey, "InstallSource", temp);
2877     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2878     CHECK_REG_STR(prodkey, "Publisher", "Wine");
2879     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2880     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
2881     CHECK_REG_STR(prodkey, "Comments", NULL);
2882     CHECK_REG_STR(prodkey, "Contact", NULL);
2883     CHECK_REG_STR(prodkey, "HelpLink", NULL);
2884     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
2885     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
2886     CHECK_REG_STR(prodkey, "Readme", NULL);
2887     CHECK_REG_STR(prodkey, "Size", NULL);
2888     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
2889     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
2890     CHECK_REG_DWORD(prodkey, "Language", 1033);
2891     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
2892     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
2893     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
2894     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
2895     todo_wine
2896     {
2897         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
2898     }
2899
2900     RegCloseKey(prodkey);
2901
2902     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2903     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2904     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2905     ok(pf_exists("msitest"), "File deleted\n");
2906
2907     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2908     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2909
2910     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2911     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2912
2913     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2914     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2915
2916     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2917                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2918     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2919     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2920
2921     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2922     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2923
2924     /* complete install */
2925     r = MsiInstallProductA(msifile, "FULL=1");
2926     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2927     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2928     ok(pf_exists("msitest"), "File not installed\n");
2929
2930     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2931     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2932
2933     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2934     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2935
2936     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2937     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2938
2939     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2940                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2941     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2942     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2943
2944     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2945     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2946
2947     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
2948     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
2949     CHECK_REG_STR(prodkey, "InstallDate", date);
2950     CHECK_REG_STR(prodkey, "InstallSource", temp);
2951     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2952     CHECK_REG_STR(prodkey, "Publisher", "Wine");
2953     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2954     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
2955     CHECK_REG_STR(prodkey, "Comments", NULL);
2956     CHECK_REG_STR(prodkey, "Contact", NULL);
2957     CHECK_REG_STR(prodkey, "HelpLink", NULL);
2958     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
2959     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
2960     CHECK_REG_STR(prodkey, "Readme", NULL);
2961     CHECK_REG_STR(prodkey, "Size", NULL);
2962     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
2963     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
2964     CHECK_REG_DWORD(prodkey, "Language", 1033);
2965     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
2966     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
2967     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
2968     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
2969     todo_wine
2970     {
2971         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
2972     }
2973
2974     RegCloseKey(prodkey);
2975
2976     /* no UnpublishFeatures */
2977     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2978     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2979     todo_wine
2980     {
2981         ok(!pf_exists("msitest\\maximus"), "File deleted\n");
2982         ok(!pf_exists("msitest"), "File deleted\n");
2983     }
2984
2985     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2986     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2987
2988     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2989     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2990
2991     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2992     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2993
2994     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2995                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2996     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2997     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2998
2999     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3000     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3001
3002     /* complete install */
3003     r = MsiInstallProductA(msifile, "FULL=1");
3004     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3005     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3006     ok(pf_exists("msitest"), "File not installed\n");
3007
3008     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3009     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3010
3011     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3012     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3013
3014     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3015     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3016
3017     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3018                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3019     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3020     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3021
3022     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3023     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3024
3025     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3026     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3027     CHECK_REG_STR(prodkey, "InstallDate", date);
3028     CHECK_REG_STR(prodkey, "InstallSource", temp);
3029     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3030     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3031     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3032     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3033     CHECK_REG_STR(prodkey, "Comments", NULL);
3034     CHECK_REG_STR(prodkey, "Contact", NULL);
3035     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3036     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3037     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3038     CHECK_REG_STR(prodkey, "Readme", NULL);
3039     CHECK_REG_STR(prodkey, "Size", NULL);
3040     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3041     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3042     CHECK_REG_DWORD(prodkey, "Language", 1033);
3043     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3044     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3045     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3046     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3047     todo_wine
3048     {
3049         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3050     }
3051
3052     RegCloseKey(prodkey);
3053
3054     /* UnpublishFeatures, only feature removed.  Only works when entire product is removed */
3055     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature");
3056     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3057     ok(pf_exists("msitest\\maximus"), "File deleted\n");
3058     ok(pf_exists("msitest"), "File deleted\n");
3059
3060     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3061     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3062
3063     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3064     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3065
3066     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3067     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3068
3069     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3070                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3071     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3072     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3073
3074     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3075     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3076
3077     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3078     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3079     CHECK_REG_STR(prodkey, "InstallDate", date);
3080     CHECK_REG_STR(prodkey, "InstallSource", temp);
3081     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3082     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3083     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3084     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3085     CHECK_REG_STR(prodkey, "Comments", NULL);
3086     CHECK_REG_STR(prodkey, "Contact", NULL);
3087     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3088     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3089     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3090     CHECK_REG_STR(prodkey, "Readme", NULL);
3091     CHECK_REG_STR(prodkey, "Size", NULL);
3092     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3093     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3094     CHECK_REG_DWORD(prodkey, "Language", 1033);
3095     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3096     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3097     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3098     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3099     todo_wine
3100     {
3101         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3102     }
3103
3104     RegCloseKey(prodkey);
3105
3106     /* complete install */
3107     r = MsiInstallProductA(msifile, "FULL=1");
3108     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3109     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3110     ok(pf_exists("msitest"), "File not installed\n");
3111
3112     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3113     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3114
3115     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3116     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3117
3118     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3119     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3120
3121     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3122                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3123     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3124     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3125
3126     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3127     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3128
3129     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3130     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3131     CHECK_REG_STR(prodkey, "InstallDate", date);
3132     CHECK_REG_STR(prodkey, "InstallSource", temp);
3133     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3134     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3135     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3136     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3137     CHECK_REG_STR(prodkey, "Comments", NULL);
3138     CHECK_REG_STR(prodkey, "Contact", NULL);
3139     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3140     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3141     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3142     CHECK_REG_STR(prodkey, "Readme", NULL);
3143     CHECK_REG_STR(prodkey, "Size", NULL);
3144     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3145     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3146     CHECK_REG_DWORD(prodkey, "Language", 1033);
3147     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3148     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3149     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3150     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3151     todo_wine
3152     {
3153         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3154     }
3155
3156     RegCloseKey(prodkey);
3157
3158     /* UnpublishFeatures, both features removed */
3159     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature,montecristo");
3160     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3161     todo_wine
3162     {
3163         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3164         ok(!pf_exists("msitest"), "File not deleted\n");
3165     }
3166
3167     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3168     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3169
3170     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3171     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3172
3173     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3174     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3175
3176     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3177                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3178     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3179     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3180
3181     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3182     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3183
3184     /* complete install */
3185     r = MsiInstallProductA(msifile, "FULL=1");
3186     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3187     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3188     ok(pf_exists("msitest"), "File not installed\n");
3189
3190     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3191     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3192
3193     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3194     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3195
3196     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3197     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3198
3199     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3200                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3201     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3202     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3203
3204     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3205     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3206
3207     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3208     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3209     CHECK_REG_STR(prodkey, "InstallDate", date);
3210     CHECK_REG_STR(prodkey, "InstallSource", temp);
3211     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3212     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3213     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3214     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3215     CHECK_REG_STR(prodkey, "Comments", NULL);
3216     CHECK_REG_STR(prodkey, "Contact", NULL);
3217     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3218     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3219     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3220     CHECK_REG_STR(prodkey, "Readme", NULL);
3221     CHECK_REG_STR(prodkey, "Size", NULL);
3222     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3223     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3224     CHECK_REG_DWORD(prodkey, "Language", 1033);
3225     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3226     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3227     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3228     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3229     todo_wine
3230     {
3231         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3232     }
3233
3234     RegCloseKey(prodkey);
3235
3236     /* complete uninstall */
3237     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3238     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3239     todo_wine
3240     {
3241         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3242         ok(!pf_exists("msitest"), "File not deleted\n");
3243     }
3244
3245     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3246     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3247
3248     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3249     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3250
3251     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3252     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3253
3254     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3255                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3256     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3257     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3258
3259     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3260     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3261
3262     /* make sure 'Program Files\msitest' is removed */
3263     delete_pfmsitest_files();
3264
3265     RegCloseKey(uninstall);
3266     DeleteFile(msifile);
3267     DeleteFile("msitest\\maximus");
3268     RemoveDirectory("msitest");
3269 }
3270
3271 static void test_publishsourcelist(void)
3272 {
3273     UINT r;
3274     DWORD size;
3275     CHAR value[MAX_PATH];
3276     CHAR path[MAX_PATH];
3277     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
3278
3279     if (!pMsiSourceListEnumSourcesA || !pMsiSourceListGetInfoA)
3280     {
3281         skip("MsiSourceListEnumSourcesA and/or MsiSourceListGetInfoA are not available\n");
3282         return;
3283     }
3284
3285     CreateDirectoryA("msitest", NULL);
3286     create_file("msitest\\maximus", 500);
3287
3288     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
3289
3290     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3291
3292     r = MsiInstallProductA(msifile, NULL);
3293     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3294     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3295     ok(pf_exists("msitest"), "File not installed\n");
3296
3297     /* nothing published */
3298     size = 0xdeadbeef;
3299     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3300                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3301     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3302     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3303
3304     size = 0xdeadbeef;
3305     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3306                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3307     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3308     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3309
3310     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
3311     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3312     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3313     ok(pf_exists("msitest"), "File not installed\n");
3314
3315     /* after RegisterProduct */
3316     size = 0xdeadbeef;
3317     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3318                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3319     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3320     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3321
3322     size = 0xdeadbeef;
3323     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3324                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3325     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3326     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3327
3328     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
3329     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3330     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3331     ok(pf_exists("msitest"), "File not installed\n");
3332
3333     /* after ProcessComponents */
3334     size = 0xdeadbeef;
3335     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3336                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3337     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3338     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3339
3340     size = 0xdeadbeef;
3341     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3342                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3343     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3344     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3345
3346     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
3347     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3348     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3349     ok(pf_exists("msitest"), "File not installed\n");
3350
3351     /* after PublishFeatures */
3352     size = 0xdeadbeef;
3353     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3354                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3355     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3356     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3357
3358     size = 0xdeadbeef;
3359     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3360                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3361     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3362     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3363
3364     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
3365     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3366     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3367     ok(pf_exists("msitest"), "File not installed\n");
3368
3369     /* after PublishProduct */
3370     size = MAX_PATH;
3371     lstrcpyA(value, "aaa");
3372     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3373                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
3374     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3375     ok(!lstrcmpA(value, "msitest.msi"), "Expected 'msitest.msi', got %s\n", value);
3376     ok(size == 11, "Expected 11, got %d\n", size);
3377
3378     size = MAX_PATH;
3379     lstrcpyA(value, "aaa");
3380     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3381                                MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATH, value, &size);
3382     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3383     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
3384     ok(size == 0, "Expected 0, got %d\n", size);
3385
3386     size = MAX_PATH;
3387     lstrcpyA(value, "aaa");
3388     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3389                                MSICODE_PRODUCT, INSTALLPROPERTY_DISKPROMPT, value, &size);
3390     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3391     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
3392     ok(size == 0, "Expected 0, got %d\n", size);
3393
3394     lstrcpyA(path, CURR_DIR);
3395     lstrcatA(path, "\\");
3396
3397     size = MAX_PATH;
3398     lstrcpyA(value, "aaa");
3399     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3400                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size);
3401     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3402     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3403     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3404
3405     size = MAX_PATH;
3406     lstrcpyA(value, "aaa");
3407     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3408                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE, value, &size);
3409     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3410     ok(!lstrcmpA(value, "n"), "Expected \"n\", got \"%s\"\n", value);
3411     ok(size == 1, "Expected 1, got %d\n", size);
3412
3413     size = MAX_PATH;
3414     lstrcpyA(value, "aaa");
3415     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3416                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
3417     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3418     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
3419     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
3420
3421     size = MAX_PATH;
3422     lstrcpyA(value, "aaa");
3423     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3424                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
3425     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3426     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3427     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3428
3429     size = MAX_PATH;
3430     lstrcpyA(value, "aaa");
3431     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3432                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 1, value, &size);
3433     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3434     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
3435     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
3436
3437     /* complete uninstall */
3438     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3439     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3440     todo_wine
3441     {
3442         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3443         ok(!pf_exists("msitest"), "File not deleted\n");
3444     }
3445
3446     /* make sure 'Program Files\msitest' is removed */
3447     delete_pfmsitest_files();
3448
3449     DeleteFile(msifile);
3450     DeleteFile("msitest\\maximus");
3451     RemoveDirectory("msitest");
3452 }
3453
3454 static UINT run_query(MSIHANDLE hdb, MSIHANDLE hrec, const char *query)
3455 {
3456     MSIHANDLE hview = 0;
3457     UINT r;
3458
3459     r = MsiDatabaseOpenView(hdb, query, &hview);
3460     if(r != ERROR_SUCCESS)
3461         return r;
3462
3463     r = MsiViewExecute(hview, hrec);
3464     if(r == ERROR_SUCCESS)
3465         r = MsiViewClose(hview);
3466     MsiCloseHandle(hview);
3467     return r;
3468 }
3469
3470 static void set_transform_summary_info(void)
3471 {
3472     UINT r;
3473     MSIHANDLE suminfo = 0;
3474
3475     /* build summary info */
3476     r = MsiGetSummaryInformation(0, mstfile, 3, &suminfo);
3477     todo_wine
3478     {
3479         ok(r == ERROR_SUCCESS , "Failed to open summaryinfo\n");
3480     }
3481
3482     r = MsiSummaryInfoSetProperty(suminfo, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
3483     todo_wine
3484     {
3485         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
3486     }
3487
3488     r = MsiSummaryInfoSetProperty(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
3489                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
3490                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
3491                         "{4C0EAA15-0264-4E5A-8758-609EF142B92D}");
3492     todo_wine
3493     {
3494         ok(r == ERROR_SUCCESS , "Failed to set summary info\n");
3495     }
3496
3497     r = MsiSummaryInfoSetProperty(suminfo, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
3498     todo_wine
3499     {
3500         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
3501     }
3502
3503     r = MsiSummaryInfoPersist(suminfo);
3504     todo_wine
3505     {
3506         ok(r == ERROR_SUCCESS , "Failed to make summary info persist\n");
3507     }
3508
3509     r = MsiCloseHandle(suminfo);
3510     ok(r == ERROR_SUCCESS , "Failed to close suminfo\n");
3511 }
3512
3513 static void generate_transform(void)
3514 {
3515     MSIHANDLE hdb1, hdb2;
3516     LPCSTR query;
3517     UINT r;
3518
3519     /* start with two identical databases */
3520     CopyFile(msifile, msifile2, FALSE);
3521
3522     r = MsiOpenDatabase(msifile2, MSIDBOPEN_TRANSACT, &hdb1);
3523     ok(r == ERROR_SUCCESS , "Failed to create database\n");
3524
3525     r = MsiDatabaseCommit(hdb1);
3526     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
3527
3528     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb2);
3529     ok(r == ERROR_SUCCESS , "Failed to create database\n");
3530
3531     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
3532     r = run_query(hdb1, 0, query);
3533     ok(r == ERROR_SUCCESS, "failed to add property\n");
3534
3535     /* database needs to be committed */
3536     MsiDatabaseCommit(hdb1);
3537
3538     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
3539     ok(r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r);
3540
3541 #if 0  /* not implemented in wine yet */
3542     r = MsiCreateTransformSummaryInfo(hdb2, hdb2, mstfile, 0, 0);
3543     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3544 #endif
3545
3546     MsiCloseHandle(hdb1);
3547     MsiCloseHandle(hdb2);
3548 }
3549
3550 /* data for generating a transform */
3551
3552 /* tables transform names - encoded as they would be in an msi database file */
3553 static const WCHAR name1[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
3554 static const WCHAR name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
3555 static const WCHAR name3[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
3556
3557 /* data in each table */
3558 static const char data1[] = /* _StringData */
3559     "propval";  /* all the strings squashed together */
3560
3561 static const WCHAR data2[] = { /* _StringPool */
3562 /*  len, refs */
3563     0,   0,    /* string 0 ''     */
3564     4,   1,    /* string 1 'prop' */
3565     3,   1,    /* string 2 'val'  */
3566 };
3567
3568 static const WCHAR data3[] = { /* Property */
3569     0x0201, 0x0001, 0x0002,
3570 };
3571
3572 static const struct {
3573     LPCWSTR name;
3574     const void *data;
3575     DWORD size;
3576 } table_transform_data[] =
3577 {
3578     { name1, data1, sizeof data1 - 1 },
3579     { name2, data2, sizeof data2 },
3580     { name3, data3, sizeof data3 },
3581 };
3582
3583 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
3584
3585 static void generate_transform_manual(void)
3586 {
3587     IStorage *stg = NULL;
3588     IStream *stm;
3589     WCHAR name[0x20];
3590     HRESULT r;
3591     DWORD i, count;
3592     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
3593
3594     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
3595
3596     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
3597
3598     r = StgCreateDocfile(name, mode, 0, &stg);
3599     ok(r == S_OK, "failed to create storage\n");
3600     if (!stg)
3601         return;
3602
3603     r = IStorage_SetClass(stg, &CLSID_MsiTransform);
3604     ok(r == S_OK, "failed to set storage type\n");
3605
3606     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
3607     {
3608         r = IStorage_CreateStream(stg, table_transform_data[i].name,
3609                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3610         if (FAILED(r))
3611         {
3612             ok(0, "failed to create stream %08x\n", r);
3613             continue;
3614         }
3615
3616         r = IStream_Write(stm, table_transform_data[i].data,
3617                           table_transform_data[i].size, &count);
3618         if (FAILED(r) || count != table_transform_data[i].size)
3619             ok(0, "failed to write stream\n");
3620         IStream_Release(stm);
3621     }
3622
3623     IStorage_Release(stg);
3624
3625     set_transform_summary_info();
3626 }
3627
3628 static void test_transformprop(void)
3629 {
3630     UINT r;
3631
3632     CreateDirectoryA("msitest", NULL);
3633     create_file("msitest\\augustus", 500);
3634
3635     create_database(msifile, tp_tables, sizeof(tp_tables) / sizeof(msi_table));
3636
3637     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3638
3639     r = MsiInstallProductA(msifile, NULL);
3640     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3641     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3642     ok(!delete_pf("msitest", FALSE), "File installed\n");
3643
3644     if (0)
3645         generate_transform();
3646     else
3647         generate_transform_manual();
3648
3649     r = MsiInstallProductA(msifile, "TRANSFORMS=winetest.mst");
3650     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3651     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
3652     ok(delete_pf("msitest", FALSE), "File not installed\n");
3653
3654     /* Delete the files in the temp (current) folder */
3655     DeleteFile(msifile);
3656     DeleteFile(msifile2);
3657     DeleteFile(mstfile);
3658     DeleteFile("msitest\\augustus");
3659     RemoveDirectory("msitest");
3660 }
3661
3662 static void test_currentworkingdir(void)
3663 {
3664     UINT r;
3665     CHAR path[MAX_PATH];
3666     LPSTR ptr, ptr2;
3667
3668     CreateDirectoryA("msitest", NULL);
3669     create_file("msitest\\augustus", 500);
3670
3671     create_database(msifile, cwd_tables, sizeof(cwd_tables) / sizeof(msi_table));
3672
3673     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3674
3675     CreateDirectoryA("diffdir", NULL);
3676     SetCurrentDirectoryA("diffdir");
3677
3678     sprintf(path, "..\\%s", msifile);
3679     r = MsiInstallProductA(path, NULL);
3680     todo_wine
3681     {
3682         ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
3683         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3684         ok(!delete_pf("msitest", FALSE), "File installed\n");
3685     }
3686
3687     sprintf(path, "%s\\%s", CURR_DIR, msifile);
3688     r = MsiInstallProductA(path, NULL);
3689     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3690     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
3691     ok(delete_pf("msitest", FALSE), "File not installed\n");
3692
3693     lstrcpyA(path, CURR_DIR);
3694     if (path[lstrlenA(path) - 1] != '\\')
3695         lstrcatA(path, "\\");
3696     lstrcatA(path, "msitest.msi");
3697
3698     ptr2 = strrchr(path, '\\');
3699     *ptr2 = '\0';
3700     ptr = strrchr(path, '\\');
3701     *ptr2 = '\\';
3702     *(ptr++) = '\0';
3703
3704     SetCurrentDirectoryA(path);
3705
3706     r = MsiInstallProductA(ptr, NULL);
3707     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3708     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
3709     ok(delete_pf("msitest", FALSE), "File not installed\n");
3710
3711     SetCurrentDirectoryA(CURR_DIR);
3712
3713     DeleteFile(msifile);
3714     DeleteFile("msitest\\augustus");
3715     RemoveDirectory("msitest");
3716     RemoveDirectory("diffdir");
3717 }
3718
3719 static void set_admin_summary_info(const CHAR *name)
3720 {
3721     MSIHANDLE db, summary;
3722     UINT r;
3723
3724     r = MsiOpenDatabaseA(name, MSIDBOPEN_DIRECT, &db);
3725     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3726
3727     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
3728     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3729
3730     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 5, NULL, NULL);
3731     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3732
3733     /* write the summary changes back to the stream */
3734     r = MsiSummaryInfoPersist(summary);
3735     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3736
3737     MsiCloseHandle(summary);
3738
3739     r = MsiDatabaseCommit(db);
3740     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3741
3742     MsiCloseHandle(db);
3743 }
3744
3745 static void test_admin(void)
3746 {
3747     UINT r;
3748
3749     CreateDirectoryA("msitest", NULL);
3750     create_file("msitest\\augustus", 500);
3751
3752     create_database(msifile, adm_tables, sizeof(adm_tables) / sizeof(msi_table));
3753     set_admin_summary_info(msifile);
3754
3755     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3756
3757     r = MsiInstallProductA(msifile, NULL);
3758     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3759     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3760     ok(!delete_pf("msitest", FALSE), "File installed\n");
3761     ok(!DeleteFile("c:\\msitest\\augustus"), "File installed\n");
3762     ok(!RemoveDirectory("c:\\msitest"), "File installed\n");
3763
3764     r = MsiInstallProductA(msifile, "ACTION=ADMIN");
3765     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3766     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3767     ok(!delete_pf("msitest", FALSE), "File installed\n");
3768     todo_wine
3769     {
3770         ok(DeleteFile("c:\\msitest\\augustus"), "File not installed\n");
3771         ok(RemoveDirectory("c:\\msitest"), "File not installed\n");
3772     }
3773
3774     DeleteFile(msifile);
3775     DeleteFile("msitest\\augustus");
3776     RemoveDirectory("msitest");
3777 }
3778
3779 static void set_admin_property_stream(LPCSTR file)
3780 {
3781     IStorage *stg;
3782     IStream *stm;
3783     WCHAR fileW[MAX_PATH];
3784     HRESULT hr;
3785     DWORD count;
3786     const DWORD mode = STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
3787
3788     /* AdminProperties */
3789     static const WCHAR stmname[] = {0x41ca,0x4330,0x3e71,0x44b5,0x4233,0x45f5,0x422c,0x4836,0};
3790     static const WCHAR data[] = {'M','Y','P','R','O','P','=','2','7','1','8',0};
3791
3792     MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH);
3793
3794     hr = StgOpenStorage(fileW, NULL, mode, NULL, 0, &stg);
3795     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
3796     if (!stg)
3797         return;
3798
3799     hr = IStorage_CreateStream(stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3800     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
3801
3802     hr = IStream_Write(stm, data, sizeof(data), &count);
3803     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
3804
3805     IStream_Release(stm);
3806     IStorage_Release(stg);
3807 }
3808
3809 static void test_adminprops(void)
3810 {
3811     UINT r;
3812
3813     CreateDirectoryA("msitest", NULL);
3814     create_file("msitest\\augustus", 500);
3815
3816     create_database(msifile, amp_tables, sizeof(amp_tables) / sizeof(msi_table));
3817     set_admin_summary_info(msifile);
3818     set_admin_property_stream(msifile);
3819
3820     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3821
3822     r = MsiInstallProductA(msifile, NULL);
3823     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3824     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
3825     ok(delete_pf("msitest", FALSE), "File installed\n");
3826
3827     DeleteFile(msifile);
3828     DeleteFile("msitest\\augustus");
3829     RemoveDirectory("msitest");
3830 }
3831
3832 static void create_pf_data(LPCSTR file, LPCSTR data, BOOL is_file)
3833 {
3834     CHAR path[MAX_PATH];
3835
3836     lstrcpyA(path, PROG_FILES_DIR);
3837     lstrcatA(path, "\\");
3838     lstrcatA(path, file);
3839
3840     if (is_file)
3841         create_file_data(path, data, 500);
3842     else
3843         CreateDirectoryA(path, NULL);
3844 }
3845
3846 #define create_pf(file, is_file) create_pf_data(file, file, is_file)
3847
3848 static void test_removefiles(void)
3849 {
3850     UINT r;
3851
3852     CreateDirectoryA("msitest", NULL);
3853     create_file("msitest\\hydrogen", 500);
3854     create_file("msitest\\helium", 500);
3855     create_file("msitest\\lithium", 500);
3856
3857     create_database(msifile, rem_tables, sizeof(rem_tables) / sizeof(msi_table));
3858
3859     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3860
3861     r = MsiInstallProductA(msifile, NULL);
3862     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3863     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
3864     ok(!pf_exists("msitest\\helium"), "File installed\n");
3865     ok(pf_exists("msitest\\lithium"), "File not installed\n");
3866     ok(pf_exists("msitest"), "File not installed\n");
3867
3868     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3869     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3870     ok(!pf_exists("msitest\\helium"), "File not deleted\n");
3871     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
3872     todo_wine
3873     {
3874         ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
3875         ok(delete_pf("msitest", FALSE), "File deleted\n");
3876     }
3877
3878     create_pf("msitest", FALSE);
3879     create_pf("msitest\\hydrogen", TRUE);
3880     create_pf("msitest\\helium", TRUE);
3881     create_pf("msitest\\lithium", TRUE);
3882
3883     r = MsiInstallProductA(msifile, NULL);
3884     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3885     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
3886     ok(pf_exists("msitest\\helium"), "File not installed\n");
3887     ok(pf_exists("msitest\\lithium"), "File not installed\n");
3888     ok(pf_exists("msitest"), "File not installed\n");
3889
3890     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3891     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3892     ok(delete_pf("msitest\\helium", TRUE), "File deleted\n");
3893     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
3894     todo_wine
3895     {
3896         ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
3897         ok(delete_pf("msitest", FALSE), "File deleted\n");
3898     }
3899
3900     create_pf("msitest", FALSE);
3901     create_pf("msitest\\furlong", TRUE);
3902     create_pf("msitest\\firkin", TRUE);
3903     create_pf("msitest\\fortnight", TRUE);
3904     create_pf("msitest\\becquerel", TRUE);
3905     create_pf("msitest\\dioptre", TRUE);
3906     create_pf("msitest\\attoparsec", TRUE);
3907     create_pf("msitest\\storeys", TRUE);
3908     create_pf("msitest\\block", TRUE);
3909     create_pf("msitest\\siriometer", TRUE);
3910
3911     r = MsiInstallProductA(msifile, NULL);
3912     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3913     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
3914     ok(!pf_exists("msitest\\helium"), "File installed\n");
3915     ok(pf_exists("msitest\\lithium"), "File not installed\n");
3916     ok(pf_exists("msitest\\becquerel"), "File not installed\n");
3917     ok(pf_exists("msitest\\dioptre"), "File not installed\n");
3918     ok(pf_exists("msitest\\attoparsec"), "File not installed\n");
3919     ok(pf_exists("msitest"), "File not installed\n");
3920     todo_wine
3921     {
3922         ok(!pf_exists("msitest\\firkin"), "File not deleted\n");
3923         ok(!pf_exists("msitest\\fortnight"), "File not deleted\n");
3924         ok(!pf_exists("msitest\\furlong"), "File not deleted\n");
3925         ok(!pf_exists("msitest\\storeys"), "File not deleted\n");
3926         ok(!pf_exists("msitest\\block"), "File not deleted\n");
3927         ok(!pf_exists("msitest\\siriometer"), "File not deleted\n");
3928     }
3929
3930     create_pf("msitest\\furlong", TRUE);
3931     create_pf("msitest\\firkin", TRUE);
3932     create_pf("msitest\\fortnight", TRUE);
3933     create_pf("msitest\\storeys", TRUE);
3934     create_pf("msitest\\block", TRUE);
3935     create_pf("msitest\\siriometer", TRUE);
3936
3937     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3938     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3939     ok(!delete_pf("msitest\\helium", TRUE), "File not deleted\n");
3940     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
3941     ok(delete_pf("msitest\\furlong", TRUE), "File deleted\n");
3942     ok(delete_pf("msitest\\firkin", TRUE), "File deleted\n");
3943     ok(delete_pf("msitest\\fortnight", TRUE), "File deleted\n");
3944     ok(delete_pf("msitest\\attoparsec", TRUE), "File deleted\n");
3945     ok(delete_pf("msitest\\siriometer", TRUE), "File deleted\n");
3946     todo_wine
3947     {
3948         ok(!delete_pf("msitest\\hydrogen", TRUE), "File not deleted\n");
3949         ok(!delete_pf("msitest\\becquerel", TRUE), "File not deleted\n");
3950         ok(!delete_pf("msitest\\dioptre", TRUE), "File not deleted\n");
3951         ok(!delete_pf("msitest\\storeys", TRUE), "File not deleted\n");
3952         ok(!delete_pf("msitest\\block", TRUE), "File not deleted\n");
3953     }
3954     ok(delete_pf("msitest", FALSE), "File deleted\n");
3955
3956     DeleteFile(msifile);
3957     DeleteFile("msitest\\hydrogen");
3958     DeleteFile("msitest\\helium");
3959     DeleteFile("msitest\\lithium");
3960     RemoveDirectory("msitest");
3961 }
3962
3963 static void test_movefiles(void)
3964 {
3965     UINT r;
3966     char props[MAX_PATH];
3967
3968     CreateDirectoryA("msitest", NULL);
3969     create_file("msitest\\augustus", 100);
3970     create_file("cameroon", 100);
3971     create_file("djibouti", 100);
3972     create_file("egypt", 100);
3973     create_file("finland", 100);
3974     create_file("gambai", 100);
3975     create_file("honduras", 100);
3976     create_file("msitest\\india", 100);
3977     create_file("japan", 100);
3978     create_file("kenya", 100);
3979     CreateDirectoryA("latvia", NULL);
3980     create_file("nauru", 100);
3981     create_file("apple", 100);
3982     create_file("application", 100);
3983     create_file("ape", 100);
3984     create_file("foo", 100);
3985     create_file("fao", 100);
3986     create_file("fbod", 100);
3987     create_file("budding", 100);
3988     create_file("buddy", 100);
3989     create_file("bud", 100);
3990     create_file("bar", 100);
3991     create_file("bur", 100);
3992     create_file("bird", 100);
3993
3994     create_database(msifile, mov_tables, sizeof(mov_tables) / sizeof(msi_table));
3995
3996     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3997
3998     /* if the source or dest property is not a full path,
3999      * windows tries to access it as a network resource
4000      */
4001
4002     sprintf(props, "SOURCEFULL=\"%s\\\" DESTFULL=\"%s\\msitest\" "
4003             "FILEPATHBAD=\"%s\\japan\" FILEPATHGOOD=\"%s\\kenya\"",
4004             CURR_DIR, PROG_FILES_DIR, CURR_DIR, CURR_DIR);
4005
4006     r = MsiInstallProductA(msifile, props);
4007     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4008     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4009     ok(!delete_pf("msitest\\dest", TRUE), "File copied\n");
4010     ok(delete_pf("msitest\\canada", TRUE), "File not copied\n");
4011     ok(delete_pf("msitest\\dominica", TRUE), "File not moved\n");
4012     ok(!delete_pf("msitest\\elsalvador", TRUE), "File moved\n");
4013     ok(!delete_pf("msitest\\france", TRUE), "File moved\n");
4014     ok(!delete_pf("msitest\\georgia", TRUE), "File moved\n");
4015     ok(delete_pf("msitest\\hungary", TRUE), "File not moved\n");
4016     ok(!delete_pf("msitest\\indonesia", TRUE), "File moved\n");
4017     ok(!delete_pf("msitest\\jordan", TRUE), "File moved\n");
4018     ok(delete_pf("msitest\\kiribati", TRUE), "File not moved\n");
4019     ok(!delete_pf("msitest\\lebanon", TRUE), "File moved\n");
4020     ok(!delete_pf("msitest\\lebanon", FALSE), "Directory moved\n");
4021     /* either apple or application will be moved depending on directory order */
4022     if (!delete_pf("msitest\\apple", TRUE))
4023         ok(delete_pf("msitest\\application", TRUE), "File not moved\n");
4024     else
4025         ok(!delete_pf("msitest\\application", TRUE), "File should not exist\n");
4026     ok(delete_pf("msitest\\wildcard", TRUE), "File not moved\n");
4027     ok(!delete_pf("msitest\\ape", TRUE), "File moved\n");
4028     /* either fao or foo will be moved depending on directory order */
4029     if (delete_pf("msitest\\foo", TRUE))
4030         ok(!delete_pf("msitest\\fao", TRUE), "File should not exist\n");
4031     else
4032         ok(delete_pf("msitest\\fao", TRUE), "File not moved\n");
4033     ok(delete_pf("msitest\\single", TRUE), "File not moved\n");
4034     ok(!delete_pf("msitest\\fbod", TRUE), "File moved\n");
4035     ok(delete_pf("msitest\\budding", TRUE), "File not moved\n");
4036     ok(delete_pf("msitest\\buddy", TRUE), "File not moved\n");
4037     ok(!delete_pf("msitest\\bud", TRUE), "File moved\n");
4038     ok(delete_pf("msitest\\bar", TRUE), "File not moved\n");
4039     ok(delete_pf("msitest\\bur", TRUE), "File not moved\n");
4040     ok(!delete_pf("msitest\\bird", TRUE), "File moved\n");
4041     ok(delete_pf("msitest", FALSE), "File not installed\n");
4042     ok(DeleteFileA("cameroon"), "File moved\n");
4043     ok(!DeleteFileA("djibouti"), "File not moved\n");
4044     ok(DeleteFileA("egypt"), "File moved\n");
4045     ok(DeleteFileA("finland"), "File moved\n");
4046     ok(DeleteFileA("gambai"), "File moved\n");
4047     ok(!DeleteFileA("honduras"), "File not moved\n");
4048     ok(DeleteFileA("msitest\\india"), "File moved\n");
4049     ok(DeleteFileA("japan"), "File moved\n");
4050     ok(!DeleteFileA("kenya"), "File not moved\n");
4051     ok(RemoveDirectoryA("latvia"), "Directory moved\n");
4052     ok(!DeleteFileA("nauru"), "File not moved\n");
4053     ok(!DeleteFileA("apple"), "File not moved\n");
4054     ok(!DeleteFileA("application"), "File not moved\n");
4055     ok(DeleteFileA("ape"), "File moved\n");
4056     ok(!DeleteFileA("foo"), "File not moved\n");
4057     ok(!DeleteFileA("fao"), "File not moved\n");
4058     ok(DeleteFileA("fbod"), "File moved\n");
4059     ok(!DeleteFileA("budding"), "File not moved\n");
4060     ok(!DeleteFileA("buddy"), "File not moved\n");
4061     ok(DeleteFileA("bud"), "File moved\n");
4062     ok(!DeleteFileA("bar"), "File not moved\n");
4063     ok(!DeleteFileA("bur"), "File not moved\n");
4064     ok(DeleteFileA("bird"), "File moved\n");
4065
4066     DeleteFile("msitest\\augustus");
4067     RemoveDirectory("msitest");
4068     DeleteFile(msifile);
4069 }
4070
4071 static void test_missingcab(void)
4072 {
4073     UINT r;
4074
4075     CreateDirectoryA("msitest", NULL);
4076     create_file("msitest\\augustus", 500);
4077     create_file("maximus", 500);
4078
4079     create_database(msifile, mc_tables, sizeof(mc_tables) / sizeof(msi_table));
4080
4081     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4082
4083     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
4084
4085     create_pf("msitest", FALSE);
4086     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
4087
4088     r = MsiInstallProductA(msifile, NULL);
4089     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4090     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4091     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
4092     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4093     ok(!delete_pf("msitest\\gaius", TRUE), "File installed\n");
4094     ok(delete_pf("msitest", FALSE), "File not installed\n");
4095
4096     create_pf("msitest", FALSE);
4097     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
4098     create_pf("msitest\\gaius", TRUE);
4099
4100     r = MsiInstallProductA(msifile, "GAIUS=1");
4101     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4102     todo_wine
4103     {
4104         ok(!delete_pf("msitest\\maximus", TRUE), "File installed\n");
4105         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4106     }
4107     ok(delete_pf("msitest\\caesar", TRUE), "File removed\n");
4108     ok(delete_pf("msitest\\gaius", TRUE), "File removed\n");
4109     ok(delete_pf("msitest", FALSE), "File not installed\n");
4110
4111     DeleteFile("msitest\\augustus");
4112     RemoveDirectory("msitest");
4113     DeleteFile("maximus");
4114     DeleteFile("test1.cab");
4115     DeleteFile(msifile);
4116 }
4117
4118 static void test_duplicatefiles(void)
4119 {
4120     UINT r;
4121
4122     CreateDirectoryA("msitest", NULL);
4123     create_file("msitest\\maximus", 500);
4124     create_database(msifile, df_tables, sizeof(df_tables) / sizeof(msi_table));
4125
4126     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4127
4128     /* fails if the destination folder is not a valid property */
4129
4130     r = MsiInstallProductA(msifile, NULL);
4131     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4132     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4133     ok(delete_pf("msitest\\augustus", TRUE), "File not duplicated\n");
4134     ok(delete_pf("msitest\\this\\doesnot\\exist\\maximus", TRUE), "File not duplicated\n");
4135     ok(delete_pf("msitest\\this\\doesnot\\exist", FALSE), "File not duplicated\n");
4136     ok(delete_pf("msitest\\this\\doesnot", FALSE), "File not duplicated\n");
4137     ok(delete_pf("msitest\\this", FALSE), "File not duplicated\n");
4138     ok(delete_pf("msitest", FALSE), "File not installed\n");
4139
4140     DeleteFile("msitest\\maximus");
4141     RemoveDirectory("msitest");
4142     DeleteFile(msifile);
4143 }
4144
4145 static void test_writeregistryvalues(void)
4146 {
4147     UINT r;
4148     LONG res;
4149     HKEY hkey;
4150     DWORD type, size;
4151     CHAR path[MAX_PATH];
4152
4153     CreateDirectoryA("msitest", NULL);
4154     create_file("msitest\\augustus", 500);
4155
4156     create_database(msifile, wrv_tables, sizeof(wrv_tables) / sizeof(msi_table));
4157
4158     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4159
4160     r = MsiInstallProductA(msifile, NULL);
4161     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4162     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4163     ok(delete_pf("msitest", FALSE), "File installed\n");
4164
4165     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
4166     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4167
4168     size = MAX_PATH;
4169     type = REG_MULTI_SZ;
4170     memset(path, 'a', MAX_PATH);
4171     res = RegQueryValueExA(hkey, "Value", NULL, &type, (LPBYTE)path, &size);
4172     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4173     ok(!memcmp(path, "one\0two\0three\0\0", size), "Wrong multi-sz data\n");
4174     ok(size == 15, "Expected 15, got %d\n", size);
4175     ok(type == REG_MULTI_SZ, "Expected REG_MULTI_SZ, got %d\n", type);
4176
4177     DeleteFile(msifile);
4178     DeleteFile("msitest\\augustus");
4179     RemoveDirectory("msitest");
4180
4181     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
4182     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine");
4183 }
4184
4185 static void test_sourcefolder(void)
4186 {
4187     UINT r;
4188
4189     CreateDirectoryA("msitest", NULL);
4190     create_file("augustus", 500);
4191
4192     create_database(msifile, sf_tables, sizeof(sf_tables) / sizeof(msi_table));
4193
4194     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4195
4196     r = MsiInstallProductA(msifile, NULL);
4197     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4198     todo_wine
4199     {
4200         ok(r == ERROR_INSTALL_FAILURE,
4201            "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4202         ok(!delete_pf("msitest", FALSE), "File installed\n");
4203     }
4204
4205     RemoveDirectoryA("msitest");
4206
4207     r = MsiInstallProductA(msifile, NULL);
4208     todo_wine
4209     {
4210         ok(r == ERROR_INSTALL_FAILURE,
4211            "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4212         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4213         ok(!delete_pf("msitest", FALSE), "File installed\n");
4214     }
4215
4216     DeleteFile(msifile);
4217     DeleteFile("augustus");
4218 }
4219
4220 static void test_customaction51(void)
4221 {
4222     UINT r;
4223
4224     CreateDirectoryA("msitest", NULL);
4225     create_file("msitest\\augustus", 500);
4226
4227     create_database(msifile, ca51_tables, sizeof(ca51_tables) / sizeof(msi_table));
4228
4229     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4230
4231     r = MsiInstallProductA(msifile, NULL);
4232     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4233     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4234     ok(delete_pf("msitest", FALSE), "File installed\n");
4235
4236     DeleteFile(msifile);
4237     DeleteFile("msitest\\augustus");
4238     RemoveDirectory("msitest");
4239 }
4240
4241 static void test_installstate(void)
4242 {
4243     UINT r;
4244
4245     CreateDirectoryA("msitest", NULL);
4246     create_file("msitest\\alpha", 500);
4247     create_file("msitest\\beta", 500);
4248     create_file("msitest\\gamma", 500);
4249     create_file("msitest\\theta", 500);
4250     create_file("msitest\\delta", 500);
4251     create_file("msitest\\epsilon", 500);
4252     create_file("msitest\\zeta", 500);
4253     create_file("msitest\\iota", 500);
4254     create_file("msitest\\eta", 500);
4255     create_file("msitest\\kappa", 500);
4256     create_file("msitest\\lambda", 500);
4257     create_file("msitest\\mu", 500);
4258
4259     create_database(msifile, is_tables, sizeof(is_tables) / sizeof(msi_table));
4260
4261     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4262
4263     r = MsiInstallProductA(msifile, NULL);
4264     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4265     ok(delete_pf("msitest\\alpha", TRUE), "File not installed\n");
4266     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4267     ok(delete_pf("msitest\\gamma", TRUE), "File not installed\n");
4268     ok(delete_pf("msitest\\theta", TRUE), "File not installed\n");
4269     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4270     ok(!delete_pf("msitest\\epsilon", TRUE), "File installed\n");
4271     ok(!delete_pf("msitest\\zeta", TRUE), "File installed\n");
4272     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4273     ok(!delete_pf("msitest\\eta", TRUE), "File installed\n");
4274     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4275     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4276     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4277     ok(delete_pf("msitest", FALSE), "File not installed\n");
4278
4279     r = MsiInstallProductA(msifile, "ADDLOCAL=\"one,two,three,four\"");
4280     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4281     ok(delete_pf("msitest\\alpha", TRUE), "File not installed\n");
4282     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4283     ok(delete_pf("msitest\\gamma", TRUE), "File not installed\n");
4284     ok(delete_pf("msitest\\theta", TRUE), "File not installed\n");
4285     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4286     ok(delete_pf("msitest\\epsilon", TRUE), "File not installed\n");
4287     ok(delete_pf("msitest\\zeta", TRUE), "File not installed\n");
4288     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4289     ok(delete_pf("msitest\\eta", TRUE), "File not installed\n");
4290     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4291     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4292     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4293     ok(delete_pf("msitest", FALSE), "File not installed\n");
4294
4295     r = MsiInstallProductA(msifile, "ADDSOURCE=\"one,two,three,four\"");
4296     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4297     ok(delete_pf("msitest\\alpha", TRUE), "File not installed\n");
4298     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4299     ok(!delete_pf("msitest\\gamma", TRUE), "File installed\n");
4300     ok(delete_pf("msitest\\theta", TRUE), "File not installed\n");
4301     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4302     ok(!delete_pf("msitest\\epsilon", TRUE), "File installed\n");
4303     ok(delete_pf("msitest\\zeta", TRUE), "File not installed\n");
4304     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4305     ok(!delete_pf("msitest\\eta", TRUE), "File installed\n");
4306     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4307     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4308     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4309     ok(delete_pf("msitest", FALSE), "File not installed\n");
4310
4311     r = MsiInstallProductA(msifile, "REMOVE=\"one,two,three,four\"");
4312     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4313     ok(!delete_pf("msitest\\alpha", TRUE), "File installed\n");
4314     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4315     ok(!delete_pf("msitest\\gamma", TRUE), "File installed\n");
4316     ok(!delete_pf("msitest\\theta", TRUE), "File installed\n");
4317     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4318     ok(!delete_pf("msitest\\epsilon", TRUE), "File installed\n");
4319     ok(!delete_pf("msitest\\zeta", TRUE), "File installed\n");
4320     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4321     ok(!delete_pf("msitest\\eta", TRUE), "File installed\n");
4322     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4323     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4324     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4325     ok(!delete_pf("msitest", FALSE), "File installed\n");
4326
4327     DeleteFile(msifile);
4328     DeleteFile("msitest\\alpha");
4329     DeleteFile("msitest\\beta");
4330     DeleteFile("msitest\\gamma");
4331     DeleteFile("msitest\\theta");
4332     DeleteFile("msitest\\delta");
4333     DeleteFile("msitest\\epsilon");
4334     DeleteFile("msitest\\zeta");
4335     DeleteFile("msitest\\iota");
4336     DeleteFile("msitest\\eta");
4337     DeleteFile("msitest\\kappa");
4338     DeleteFile("msitest\\lambda");
4339     DeleteFile("msitest\\mu");
4340     RemoveDirectory("msitest");
4341 }
4342
4343 START_TEST(install)
4344 {
4345     DWORD len;
4346     char temp_path[MAX_PATH], prev_path[MAX_PATH];
4347
4348     init_functionpointers();
4349
4350     GetCurrentDirectoryA(MAX_PATH, prev_path);
4351     GetTempPath(MAX_PATH, temp_path);
4352     SetCurrentDirectoryA(temp_path);
4353
4354     lstrcpyA(CURR_DIR, temp_path);
4355     len = lstrlenA(CURR_DIR);
4356
4357     if(len && (CURR_DIR[len - 1] == '\\'))
4358         CURR_DIR[len - 1] = 0;
4359
4360     get_program_files_dir(PROG_FILES_DIR, COMMON_FILES_DIR);
4361
4362     test_MsiInstallProduct();
4363     test_MsiSetComponentState();
4364     test_packagecoltypes();
4365     test_continuouscabs();
4366     test_caborder();
4367     test_mixedmedia();
4368     test_samesequence();
4369     test_uiLevelFlags();
4370     test_readonlyfile();
4371     test_setdirproperty();
4372     test_cabisextracted();
4373     test_concurrentinstall();
4374     test_setpropertyfolder();
4375     test_publish_registerproduct();
4376     test_publish_publishproduct();
4377     test_publish_publishfeatures();
4378     test_publish_registeruser();
4379     test_publish_processcomponents();
4380     test_publish();
4381     test_publishsourcelist();
4382     test_transformprop();
4383     test_currentworkingdir();
4384     test_admin();
4385     test_adminprops();
4386     test_removefiles();
4387     test_movefiles();
4388     test_missingcab();
4389     test_duplicatefiles();
4390     test_writeregistryvalues();
4391     test_sourcefolder();
4392     test_customaction51();
4393     test_installstate();
4394
4395     SetCurrentDirectoryA(prev_path);
4396 }