quartz: Silence requests for ipin on filters.
[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 typedef struct _msi_table
634 {
635     const CHAR *filename;
636     const CHAR *data;
637     int size;
638 } msi_table;
639
640 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
641
642 static const msi_table tables[] =
643 {
644     ADD_TABLE(component),
645     ADD_TABLE(directory),
646     ADD_TABLE(feature),
647     ADD_TABLE(feature_comp),
648     ADD_TABLE(file),
649     ADD_TABLE(install_exec_seq),
650     ADD_TABLE(media),
651     ADD_TABLE(property),
652     ADD_TABLE(registry),
653     ADD_TABLE(service_install),
654     ADD_TABLE(service_control)
655 };
656
657 static const msi_table cc_tables[] =
658 {
659     ADD_TABLE(cc_component),
660     ADD_TABLE(directory),
661     ADD_TABLE(cc_feature),
662     ADD_TABLE(cc_feature_comp),
663     ADD_TABLE(cc_file),
664     ADD_TABLE(install_exec_seq),
665     ADD_TABLE(cc_media),
666     ADD_TABLE(property),
667 };
668
669 static const msi_table cc2_tables[] =
670 {
671     ADD_TABLE(cc2_component),
672     ADD_TABLE(directory),
673     ADD_TABLE(cc_feature),
674     ADD_TABLE(cc_feature_comp),
675     ADD_TABLE(cc2_file),
676     ADD_TABLE(install_exec_seq),
677     ADD_TABLE(cc_media),
678     ADD_TABLE(property),
679 };
680
681 static const msi_table co_tables[] =
682 {
683     ADD_TABLE(cc_component),
684     ADD_TABLE(directory),
685     ADD_TABLE(cc_feature),
686     ADD_TABLE(cc_feature_comp),
687     ADD_TABLE(co_file),
688     ADD_TABLE(install_exec_seq),
689     ADD_TABLE(co_media),
690     ADD_TABLE(property),
691 };
692
693 static const msi_table co2_tables[] =
694 {
695     ADD_TABLE(cc_component),
696     ADD_TABLE(directory),
697     ADD_TABLE(cc_feature),
698     ADD_TABLE(cc_feature_comp),
699     ADD_TABLE(cc_file),
700     ADD_TABLE(install_exec_seq),
701     ADD_TABLE(co2_media),
702     ADD_TABLE(property),
703 };
704
705 static const msi_table mm_tables[] =
706 {
707     ADD_TABLE(cc_component),
708     ADD_TABLE(directory),
709     ADD_TABLE(cc_feature),
710     ADD_TABLE(cc_feature_comp),
711     ADD_TABLE(mm_file),
712     ADD_TABLE(install_exec_seq),
713     ADD_TABLE(mm_media),
714     ADD_TABLE(property),
715 };
716
717 static const msi_table ss_tables[] =
718 {
719     ADD_TABLE(cc_component),
720     ADD_TABLE(directory),
721     ADD_TABLE(cc_feature),
722     ADD_TABLE(cc_feature_comp),
723     ADD_TABLE(cc_file),
724     ADD_TABLE(install_exec_seq),
725     ADD_TABLE(ss_media),
726     ADD_TABLE(property),
727 };
728
729 static const msi_table ui_tables[] =
730 {
731     ADD_TABLE(ui_component),
732     ADD_TABLE(directory),
733     ADD_TABLE(cc_feature),
734     ADD_TABLE(cc_feature_comp),
735     ADD_TABLE(cc_file),
736     ADD_TABLE(install_exec_seq),
737     ADD_TABLE(ui_install_ui_seq),
738     ADD_TABLE(ui_custom_action),
739     ADD_TABLE(cc_media),
740     ADD_TABLE(property),
741 };
742
743 static const msi_table rof_tables[] =
744 {
745     ADD_TABLE(rof_component),
746     ADD_TABLE(directory),
747     ADD_TABLE(rof_feature),
748     ADD_TABLE(rof_feature_comp),
749     ADD_TABLE(rof_file),
750     ADD_TABLE(install_exec_seq),
751     ADD_TABLE(rof_media),
752     ADD_TABLE(property),
753 };
754
755 static const msi_table sdp_tables[] =
756 {
757     ADD_TABLE(rof_component),
758     ADD_TABLE(directory),
759     ADD_TABLE(rof_feature),
760     ADD_TABLE(rof_feature_comp),
761     ADD_TABLE(rof_file),
762     ADD_TABLE(sdp_install_exec_seq),
763     ADD_TABLE(sdp_custom_action),
764     ADD_TABLE(rof_media),
765     ADD_TABLE(property),
766 };
767
768 static const msi_table cie_tables[] =
769 {
770     ADD_TABLE(cie_component),
771     ADD_TABLE(directory),
772     ADD_TABLE(cc_feature),
773     ADD_TABLE(cie_feature_comp),
774     ADD_TABLE(cie_file),
775     ADD_TABLE(install_exec_seq),
776     ADD_TABLE(cie_media),
777     ADD_TABLE(property),
778 };
779
780 static const msi_table ci_tables[] =
781 {
782     ADD_TABLE(ci_component),
783     ADD_TABLE(directory),
784     ADD_TABLE(rof_feature),
785     ADD_TABLE(rof_feature_comp),
786     ADD_TABLE(rof_file),
787     ADD_TABLE(ci_install_exec_seq),
788     ADD_TABLE(rof_media),
789     ADD_TABLE(property),
790     ADD_TABLE(ci_custom_action),
791 };
792
793 static const msi_table ci2_tables[] =
794 {
795     ADD_TABLE(ci2_component),
796     ADD_TABLE(directory),
797     ADD_TABLE(rof_feature),
798     ADD_TABLE(ci2_feature_comp),
799     ADD_TABLE(ci2_file),
800     ADD_TABLE(install_exec_seq),
801     ADD_TABLE(rof_media),
802     ADD_TABLE(property),
803 };
804
805 static const msi_table spf_tables[] =
806 {
807     ADD_TABLE(ci_component),
808     ADD_TABLE(directory),
809     ADD_TABLE(rof_feature),
810     ADD_TABLE(rof_feature_comp),
811     ADD_TABLE(rof_file),
812     ADD_TABLE(spf_install_exec_seq),
813     ADD_TABLE(rof_media),
814     ADD_TABLE(property),
815     ADD_TABLE(spf_custom_action),
816     ADD_TABLE(spf_install_ui_seq),
817 };
818
819 static const msi_table pp_tables[] =
820 {
821     ADD_TABLE(ci_component),
822     ADD_TABLE(directory),
823     ADD_TABLE(rof_feature),
824     ADD_TABLE(rof_feature_comp),
825     ADD_TABLE(rof_file),
826     ADD_TABLE(pp_install_exec_seq),
827     ADD_TABLE(rof_media),
828     ADD_TABLE(property),
829 };
830
831 static const msi_table tp_tables[] =
832 {
833     ADD_TABLE(tp_component),
834     ADD_TABLE(directory),
835     ADD_TABLE(rof_feature),
836     ADD_TABLE(ci2_feature_comp),
837     ADD_TABLE(ci2_file),
838     ADD_TABLE(install_exec_seq),
839     ADD_TABLE(rof_media),
840     ADD_TABLE(property),
841 };
842
843 static const msi_table cwd_tables[] =
844 {
845     ADD_TABLE(cwd_component),
846     ADD_TABLE(directory),
847     ADD_TABLE(rof_feature),
848     ADD_TABLE(ci2_feature_comp),
849     ADD_TABLE(ci2_file),
850     ADD_TABLE(install_exec_seq),
851     ADD_TABLE(rof_media),
852     ADD_TABLE(property),
853 };
854
855 static const msi_table adm_tables[] =
856 {
857     ADD_TABLE(adm_component),
858     ADD_TABLE(directory),
859     ADD_TABLE(rof_feature),
860     ADD_TABLE(ci2_feature_comp),
861     ADD_TABLE(ci2_file),
862     ADD_TABLE(install_exec_seq),
863     ADD_TABLE(rof_media),
864     ADD_TABLE(property),
865     ADD_TABLE(adm_custom_action),
866     ADD_TABLE(adm_admin_exec_seq),
867 };
868
869 static const msi_table amp_tables[] =
870 {
871     ADD_TABLE(amp_component),
872     ADD_TABLE(directory),
873     ADD_TABLE(rof_feature),
874     ADD_TABLE(ci2_feature_comp),
875     ADD_TABLE(ci2_file),
876     ADD_TABLE(install_exec_seq),
877     ADD_TABLE(rof_media),
878     ADD_TABLE(property),
879 };
880
881 static const msi_table rem_tables[] =
882 {
883     ADD_TABLE(rem_component),
884     ADD_TABLE(directory),
885     ADD_TABLE(rof_feature),
886     ADD_TABLE(rem_feature_comp),
887     ADD_TABLE(rem_file),
888     ADD_TABLE(rem_install_exec_seq),
889     ADD_TABLE(rof_media),
890     ADD_TABLE(property),
891     ADD_TABLE(rem_remove_files),
892 };
893
894 static const msi_table mov_tables[] =
895 {
896     ADD_TABLE(cwd_component),
897     ADD_TABLE(directory),
898     ADD_TABLE(rof_feature),
899     ADD_TABLE(ci2_feature_comp),
900     ADD_TABLE(ci2_file),
901     ADD_TABLE(install_exec_seq),
902     ADD_TABLE(rof_media),
903     ADD_TABLE(property),
904     ADD_TABLE(mov_move_file),
905 };
906
907 static const msi_table mc_tables[] =
908 {
909     ADD_TABLE(mc_component),
910     ADD_TABLE(directory),
911     ADD_TABLE(cc_feature),
912     ADD_TABLE(cie_feature_comp),
913     ADD_TABLE(mc_file),
914     ADD_TABLE(install_exec_seq),
915     ADD_TABLE(mc_media),
916     ADD_TABLE(property),
917     ADD_TABLE(mc_file_hash),
918 };
919
920 static const msi_table df_tables[] =
921 {
922     ADD_TABLE(rof_component),
923     ADD_TABLE(df_directory),
924     ADD_TABLE(rof_feature),
925     ADD_TABLE(rof_feature_comp),
926     ADD_TABLE(rof_file),
927     ADD_TABLE(install_exec_seq),
928     ADD_TABLE(rof_media),
929     ADD_TABLE(property),
930     ADD_TABLE(df_duplicate_file),
931 };
932
933 static const msi_table wrv_tables[] =
934 {
935     ADD_TABLE(wrv_component),
936     ADD_TABLE(directory),
937     ADD_TABLE(rof_feature),
938     ADD_TABLE(ci2_feature_comp),
939     ADD_TABLE(ci2_file),
940     ADD_TABLE(install_exec_seq),
941     ADD_TABLE(rof_media),
942     ADD_TABLE(property),
943     ADD_TABLE(wrv_registry),
944 };
945
946 static const msi_table sf_tables[] =
947 {
948     ADD_TABLE(wrv_component),
949     ADD_TABLE(directory),
950     ADD_TABLE(rof_feature),
951     ADD_TABLE(ci2_feature_comp),
952     ADD_TABLE(ci2_file),
953     ADD_TABLE(install_exec_seq),
954     ADD_TABLE(rof_media),
955     ADD_TABLE(property),
956 };
957
958 static const msi_table ca51_tables[] =
959 {
960     ADD_TABLE(ca51_component),
961     ADD_TABLE(directory),
962     ADD_TABLE(rof_feature),
963     ADD_TABLE(ci2_feature_comp),
964     ADD_TABLE(ci2_file),
965     ADD_TABLE(ca51_install_exec_seq),
966     ADD_TABLE(rof_media),
967     ADD_TABLE(property),
968     ADD_TABLE(ca51_custom_action),
969 };
970
971 /* cabinet definitions */
972
973 /* make the max size large so there is only one cab file */
974 #define MEDIA_SIZE          0x7FFFFFFF
975 #define FOLDER_THRESHOLD    900000
976
977 /* the FCI callbacks */
978
979 static void *mem_alloc(ULONG cb)
980 {
981     return HeapAlloc(GetProcessHeap(), 0, cb);
982 }
983
984 static void mem_free(void *memory)
985 {
986     HeapFree(GetProcessHeap(), 0, memory);
987 }
988
989 static BOOL get_next_cabinet(PCCAB pccab, ULONG  cbPrevCab, void *pv)
990 {
991     sprintf(pccab->szCab, pv, pccab->iCab);
992     return TRUE;
993 }
994
995 static long progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
996 {
997     return 0;
998 }
999
1000 static int file_placed(PCCAB pccab, char *pszFile, long cbFile,
1001                        BOOL fContinuation, void *pv)
1002 {
1003     return 0;
1004 }
1005
1006 static INT_PTR fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
1007 {
1008     HANDLE handle;
1009     DWORD dwAccess = 0;
1010     DWORD dwShareMode = 0;
1011     DWORD dwCreateDisposition = OPEN_EXISTING;
1012     
1013     dwAccess = GENERIC_READ | GENERIC_WRITE;
1014     /* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
1015     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
1016
1017     if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
1018         dwCreateDisposition = OPEN_EXISTING;
1019     else
1020         dwCreateDisposition = CREATE_NEW;
1021
1022     handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
1023                          dwCreateDisposition, 0, NULL);
1024
1025     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
1026
1027     return (INT_PTR)handle;
1028 }
1029
1030 static UINT fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
1031 {
1032     HANDLE handle = (HANDLE)hf;
1033     DWORD dwRead;
1034     BOOL res;
1035     
1036     res = ReadFile(handle, memory, cb, &dwRead, NULL);
1037     ok(res, "Failed to ReadFile\n");
1038
1039     return dwRead;
1040 }
1041
1042 static UINT fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
1043 {
1044     HANDLE handle = (HANDLE)hf;
1045     DWORD dwWritten;
1046     BOOL res;
1047
1048     res = WriteFile(handle, memory, cb, &dwWritten, NULL);
1049     ok(res, "Failed to WriteFile\n");
1050
1051     return dwWritten;
1052 }
1053
1054 static int fci_close(INT_PTR hf, int *err, void *pv)
1055 {
1056     HANDLE handle = (HANDLE)hf;
1057     ok(CloseHandle(handle), "Failed to CloseHandle\n");
1058
1059     return 0;
1060 }
1061
1062 static long fci_seek(INT_PTR hf, long dist, int seektype, int *err, void *pv)
1063 {
1064     HANDLE handle = (HANDLE)hf;
1065     DWORD ret;
1066     
1067     ret = SetFilePointer(handle, dist, NULL, seektype);
1068     ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
1069
1070     return ret;
1071 }
1072
1073 static int fci_delete(char *pszFile, int *err, void *pv)
1074 {
1075     BOOL ret = DeleteFileA(pszFile);
1076     ok(ret, "Failed to DeleteFile %s\n", pszFile);
1077
1078     return 0;
1079 }
1080
1081 static void init_functionpointers(void)
1082 {
1083     HMODULE hmsi = GetModuleHandleA("msi.dll");
1084
1085 #define GET_PROC(func) \
1086     p ## func = (void*)GetProcAddress(hmsi, #func); \
1087     if(!p ## func) \
1088       trace("GetProcAddress(%s) failed\n", #func);
1089
1090     GET_PROC(MsiQueryComponentStateA);
1091     GET_PROC(MsiSourceListEnumSourcesA);
1092     GET_PROC(MsiSourceListGetInfoA);
1093
1094 #undef GET_PROC
1095 }
1096
1097 static BOOL check_record(MSIHANDLE rec, UINT field, LPCSTR val)
1098 {
1099     CHAR buffer[0x20];
1100     UINT r;
1101     DWORD sz;
1102
1103     sz = sizeof buffer;
1104     r = MsiRecordGetString(rec, field, buffer, &sz);
1105     return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
1106 }
1107
1108 static BOOL get_temp_file(char *pszTempName, int cbTempName, void *pv)
1109 {
1110     LPSTR tempname;
1111
1112     tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
1113     GetTempFileNameA(".", "xx", 0, tempname);
1114
1115     if (tempname && (strlen(tempname) < (unsigned)cbTempName))
1116     {
1117         lstrcpyA(pszTempName, tempname);
1118         HeapFree(GetProcessHeap(), 0, tempname);
1119         return TRUE;
1120     }
1121
1122     HeapFree(GetProcessHeap(), 0, tempname);
1123
1124     return FALSE;
1125 }
1126
1127 static INT_PTR get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
1128                              USHORT *pattribs, int *err, void *pv)
1129 {
1130     BY_HANDLE_FILE_INFORMATION finfo;
1131     FILETIME filetime;
1132     HANDLE handle;
1133     DWORD attrs;
1134     BOOL res;
1135
1136     handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
1137                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
1138
1139     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
1140
1141     res = GetFileInformationByHandle(handle, &finfo);
1142     ok(res, "Expected GetFileInformationByHandle to succeed\n");
1143    
1144     FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
1145     FileTimeToDosDateTime(&filetime, pdate, ptime);
1146
1147     attrs = GetFileAttributes(pszName);
1148     ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
1149
1150     return (INT_PTR)handle;
1151 }
1152
1153 static BOOL add_file(HFCI hfci, const char *file, TCOMP compress)
1154 {
1155     char path[MAX_PATH];
1156     char filename[MAX_PATH];
1157
1158     lstrcpyA(path, CURR_DIR);
1159     lstrcatA(path, "\\");
1160     lstrcatA(path, file);
1161
1162     lstrcpyA(filename, file);
1163
1164     return FCIAddFile(hfci, path, filename, FALSE, get_next_cabinet,
1165                       progress, get_open_info, compress);
1166 }
1167
1168 static void set_cab_parameters(PCCAB pCabParams, const CHAR *name, DWORD max_size)
1169 {
1170     ZeroMemory(pCabParams, sizeof(CCAB));
1171
1172     pCabParams->cb = max_size;
1173     pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
1174     pCabParams->setID = 0xbeef;
1175     pCabParams->iCab = 1;
1176     lstrcpyA(pCabParams->szCabPath, CURR_DIR);
1177     lstrcatA(pCabParams->szCabPath, "\\");
1178     lstrcpyA(pCabParams->szCab, name);
1179 }
1180
1181 static void create_cab_file(const CHAR *name, DWORD max_size, const CHAR *files)
1182 {
1183     CCAB cabParams;
1184     LPCSTR ptr;
1185     HFCI hfci;
1186     ERF erf;
1187     BOOL res;
1188
1189     set_cab_parameters(&cabParams, name, max_size);
1190
1191     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1192                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1193                       get_temp_file, &cabParams, NULL);
1194
1195     ok(hfci != NULL, "Failed to create an FCI context\n");
1196
1197     ptr = files;
1198     while (*ptr)
1199     {
1200         res = add_file(hfci, ptr, tcompTYPE_MSZIP);
1201         ok(res, "Failed to add file: %s\n", ptr);
1202         ptr += lstrlen(ptr) + 1;
1203     }
1204
1205     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1206     ok(res, "Failed to flush the cabinet\n");
1207
1208     res = FCIDestroy(hfci);
1209     ok(res, "Failed to destroy the cabinet\n");
1210 }
1211
1212 static BOOL get_program_files_dir(LPSTR buf, LPSTR buf2)
1213 {
1214     HKEY hkey;
1215     DWORD type, size;
1216
1217     if (RegOpenKey(HKEY_LOCAL_MACHINE,
1218                    "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
1219         return FALSE;
1220
1221     size = MAX_PATH;
1222     if (RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)buf, &size)) {
1223         RegCloseKey(hkey);
1224         return FALSE;
1225     }
1226
1227     size = MAX_PATH;
1228     if (RegQueryValueExA(hkey, "CommonFilesDir", 0, &type, (LPBYTE)buf2, &size)) {
1229         RegCloseKey(hkey);
1230         return FALSE;
1231     }
1232
1233     RegCloseKey(hkey);
1234     return TRUE;
1235 }
1236
1237 static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
1238 {
1239     HANDLE file;
1240     DWORD written;
1241
1242     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1243     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
1244     WriteFile(file, data, strlen(data), &written, NULL);
1245
1246     if (size)
1247     {
1248         SetFilePointer(file, size, NULL, FILE_BEGIN);
1249         SetEndOfFile(file);
1250     }
1251
1252     CloseHandle(file);
1253 }
1254
1255 #define create_file(name, size) create_file_data(name, name, size)
1256
1257 static void create_test_files(void)
1258 {
1259     CreateDirectoryA("msitest", NULL);
1260     create_file("msitest\\one.txt", 100);
1261     CreateDirectoryA("msitest\\first", NULL);
1262     create_file("msitest\\first\\two.txt", 100);
1263     CreateDirectoryA("msitest\\second", NULL);
1264     create_file("msitest\\second\\three.txt", 100);
1265
1266     create_file("four.txt", 100);
1267     create_file("five.txt", 100);
1268     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1269
1270     create_file("msitest\\filename", 100);
1271     create_file("msitest\\service.exe", 100);
1272
1273     DeleteFileA("four.txt");
1274     DeleteFileA("five.txt");
1275 }
1276
1277 static BOOL delete_pf(const CHAR *rel_path, BOOL is_file)
1278 {
1279     CHAR path[MAX_PATH];
1280
1281     lstrcpyA(path, PROG_FILES_DIR);
1282     lstrcatA(path, "\\");
1283     lstrcatA(path, rel_path);
1284
1285     if (is_file)
1286         return DeleteFileA(path);
1287     else
1288         return RemoveDirectoryA(path);
1289 }
1290
1291 static BOOL delete_cf(const CHAR *rel_path, BOOL is_file)
1292 {
1293     CHAR path[MAX_PATH];
1294
1295     lstrcpyA(path, COMMON_FILES_DIR);
1296     lstrcatA(path, "\\");
1297     lstrcatA(path, rel_path);
1298
1299     if (is_file)
1300         return DeleteFileA(path);
1301     else
1302         return RemoveDirectoryA(path);
1303 }
1304
1305 static void delete_test_files(void)
1306 {
1307     DeleteFileA("msitest.msi");
1308     DeleteFileA("msitest.cab");
1309     DeleteFileA("msitest\\second\\three.txt");
1310     DeleteFileA("msitest\\first\\two.txt");
1311     DeleteFileA("msitest\\one.txt");
1312     DeleteFileA("msitest\\service.exe");
1313     DeleteFileA("msitest\\filename");
1314     RemoveDirectoryA("msitest\\second");
1315     RemoveDirectoryA("msitest\\first");
1316     RemoveDirectoryA("msitest");
1317 }
1318
1319 static void write_file(const CHAR *filename, const char *data, int data_size)
1320 {
1321     DWORD size;
1322
1323     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
1324                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1325
1326     WriteFile(hf, data, data_size, &size, NULL);
1327     CloseHandle(hf);
1328 }
1329
1330 static void write_msi_summary_info(MSIHANDLE db)
1331 {
1332     MSIHANDLE summary;
1333     UINT r;
1334
1335     r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
1336     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1337
1338     r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, ";1033");
1339     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1340
1341     r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1342                                    "{004757CA-5092-49c2-AD20-28E1CE0DF5F2}");
1343     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1344
1345     r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
1346     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1347
1348     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 0, NULL, NULL);
1349     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1350
1351     r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
1352     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1353
1354     /* write the summary changes back to the stream */
1355     r = MsiSummaryInfoPersist(summary);
1356     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1357
1358     MsiCloseHandle(summary);
1359 }
1360
1361 static void create_database(const CHAR *name, const msi_table *tables, int num_tables)
1362 {
1363     MSIHANDLE db;
1364     UINT r;
1365     int j;
1366
1367     r = MsiOpenDatabaseA(name, MSIDBOPEN_CREATE, &db);
1368     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1369
1370     /* import the tables into the database */
1371     for (j = 0; j < num_tables; j++)
1372     {
1373         const msi_table *table = &tables[j];
1374
1375         write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
1376
1377         r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
1378         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1379
1380         DeleteFileA(table->filename);
1381     }
1382
1383     write_msi_summary_info(db);
1384
1385     r = MsiDatabaseCommit(db);
1386     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1387
1388     MsiCloseHandle(db);
1389 }
1390
1391 static void check_service_is_installed(void)
1392 {
1393     SC_HANDLE scm, service;
1394     BOOL res;
1395
1396     scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1397     ok(scm != NULL, "Failed to open the SC Manager\n");
1398
1399     service = OpenService(scm, "TestService", SC_MANAGER_ALL_ACCESS);
1400     ok(service != NULL, "Failed to open TestService\n");
1401
1402     res = DeleteService(service);
1403     ok(res, "Failed to delete TestService\n");
1404
1405     CloseServiceHandle(service);
1406     CloseServiceHandle(scm);
1407 }
1408
1409 static void test_MsiInstallProduct(void)
1410 {
1411     UINT r;
1412     CHAR path[MAX_PATH];
1413     LONG res;
1414     HKEY hkey;
1415     DWORD num, size, type;
1416     SC_HANDLE scm;
1417
1418     scm = OpenSCManager(NULL, NULL, GENERIC_ALL);
1419     if (!scm && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1420     {
1421         skip("Services are not implemented, we are most likely on win9x\n");
1422         return;
1423     }
1424     CloseServiceHandle(scm);
1425
1426     create_test_files();
1427     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1428
1429     r = MsiInstallProductA(msifile, NULL);
1430     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1431
1432     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
1433     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
1434     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
1435     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
1436     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
1437     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
1438     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
1439     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
1440     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
1441     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
1442     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
1443     ok(delete_pf("msitest", FALSE), "File not installed\n");
1444
1445     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
1446     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1447
1448     size = MAX_PATH;
1449     type = REG_SZ;
1450     res = RegQueryValueExA(hkey, "Name", NULL, &type, (LPBYTE)path, &size);
1451     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1452     ok(!lstrcmpA(path, "imaname"), "Expected imaname, got %s\n", path);
1453
1454     size = MAX_PATH;
1455     type = REG_SZ;
1456     res = RegQueryValueExA(hkey, "blah", NULL, &type, (LPBYTE)path, &size);
1457     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
1458
1459     size = sizeof(num);
1460     type = REG_DWORD;
1461     res = RegQueryValueExA(hkey, "number", NULL, &type, (LPBYTE)&num, &size);
1462     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1463     ok(num == 314, "Expected 314, got %d\n", num);
1464
1465     size = MAX_PATH;
1466     type = REG_SZ;
1467     res = RegQueryValueExA(hkey, "OrderTestName", NULL, &type, (LPBYTE)path, &size);
1468     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1469     ok(!lstrcmpA(path, "OrderTestValue"), "Expected imaname, got %s\n", path);
1470
1471     check_service_is_installed();
1472
1473     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
1474
1475     delete_test_files();
1476 }
1477
1478 static void test_MsiSetComponentState(void)
1479 {
1480     INSTALLSTATE installed, action;
1481     MSIHANDLE package;
1482     char path[MAX_PATH];
1483     UINT r;
1484
1485     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1486
1487     CoInitialize(NULL);
1488
1489     lstrcpy(path, CURR_DIR);
1490     lstrcat(path, "\\");
1491     lstrcat(path, msifile);
1492
1493     r = MsiOpenPackage(path, &package);
1494     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1495
1496     r = MsiDoAction(package, "CostInitialize");
1497     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1498
1499     r = MsiDoAction(package, "FileCost");
1500     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1501
1502     r = MsiDoAction(package, "CostFinalize");
1503     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1504
1505     r = MsiGetComponentState(package, "dangler", &installed, &action);
1506     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1507     ok(installed == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", installed);
1508     ok(action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1509
1510     r = MsiSetComponentState(package, "dangler", INSTALLSTATE_SOURCE);
1511     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1512
1513     MsiCloseHandle(package);
1514     CoUninitialize();
1515
1516     DeleteFileA(msifile);
1517 }
1518
1519 static void test_packagecoltypes(void)
1520 {
1521     MSIHANDLE hdb, view, rec;
1522     char path[MAX_PATH];
1523     LPCSTR query;
1524     UINT r, count;
1525
1526     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1527
1528     CoInitialize(NULL);
1529
1530     lstrcpy(path, CURR_DIR);
1531     lstrcat(path, "\\");
1532     lstrcat(path, msifile);
1533
1534     r = MsiOpenDatabase(path, MSIDBOPEN_READONLY, &hdb);
1535     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1536
1537     query = "SELECT * FROM `Media`";
1538     r = MsiDatabaseOpenView( hdb, query, &view );
1539     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1540
1541     r = MsiViewGetColumnInfo( view, MSICOLINFO_NAMES, &rec );
1542     count = MsiRecordGetFieldCount( rec );
1543     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1544     ok(count == 6, "Expected 6, got %d\n", count);
1545     ok(check_record(rec, 1, "DiskId"), "wrong column label\n");
1546     ok(check_record(rec, 2, "LastSequence"), "wrong column label\n");
1547     ok(check_record(rec, 3, "DiskPrompt"), "wrong column label\n");
1548     ok(check_record(rec, 4, "Cabinet"), "wrong column label\n");
1549     ok(check_record(rec, 5, "VolumeLabel"), "wrong column label\n");
1550     ok(check_record(rec, 6, "Source"), "wrong column label\n");
1551     MsiCloseHandle(rec);
1552
1553     r = MsiViewGetColumnInfo( view, MSICOLINFO_TYPES, &rec );
1554     count = MsiRecordGetFieldCount( rec );
1555     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1556     ok(count == 6, "Expected 6, got %d\n", count);
1557     ok(check_record(rec, 1, "i2"), "wrong column label\n");
1558     ok(check_record(rec, 2, "i4"), "wrong column label\n");
1559     ok(check_record(rec, 3, "L64"), "wrong column label\n");
1560     ok(check_record(rec, 4, "S255"), "wrong column label\n");
1561     ok(check_record(rec, 5, "S32"), "wrong column label\n");
1562     ok(check_record(rec, 6, "S72"), "wrong column label\n");
1563
1564     MsiCloseHandle(rec);
1565     MsiCloseHandle(view);
1566     MsiCloseHandle(hdb);
1567     DeleteFile(msifile);
1568 }
1569
1570 static void create_cc_test_files(void)
1571 {
1572     CCAB cabParams;
1573     HFCI hfci;
1574     ERF erf;
1575     static CHAR cab_context[] = "test%d.cab";
1576     BOOL res;
1577
1578     create_file("maximus", 500);
1579     create_file("augustus", 50000);
1580     create_file("tiberius", 500);
1581     create_file("caesar", 500);
1582
1583     set_cab_parameters(&cabParams, "test1.cab", 40000);
1584
1585     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1586                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1587                       get_temp_file, &cabParams, cab_context);
1588     ok(hfci != NULL, "Failed to create an FCI context\n");
1589
1590     res = add_file(hfci, "maximus", tcompTYPE_NONE);
1591     ok(res, "Failed to add file maximus\n");
1592
1593     res = add_file(hfci, "augustus", tcompTYPE_NONE);
1594     ok(res, "Failed to add file augustus\n");
1595
1596     res = add_file(hfci, "tiberius", tcompTYPE_NONE);
1597     ok(res, "Failed to add file tiberius\n");
1598
1599     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1600     ok(res, "Failed to flush the cabinet\n");
1601
1602     res = FCIDestroy(hfci);
1603     ok(res, "Failed to destroy the cabinet\n");
1604
1605     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1606
1607     DeleteFile("maximus");
1608     DeleteFile("augustus");
1609     DeleteFile("tiberius");
1610     DeleteFile("caesar");
1611 }
1612
1613 static void delete_cab_files(void)
1614 {
1615     SHFILEOPSTRUCT shfl;
1616     CHAR path[MAX_PATH+10];
1617
1618     lstrcpyA(path, CURR_DIR);
1619     lstrcatA(path, "\\*.cab");
1620     path[strlen(path) + 1] = '\0';
1621
1622     shfl.hwnd = NULL;
1623     shfl.wFunc = FO_DELETE;
1624     shfl.pFrom = path;
1625     shfl.pTo = NULL;
1626     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
1627
1628     SHFileOperation(&shfl);
1629 }
1630
1631 static void test_continuouscabs(void)
1632 {
1633     UINT r;
1634
1635     create_cc_test_files();
1636     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1637
1638     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1639
1640     r = MsiInstallProductA(msifile, NULL);
1641     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
1642     {
1643         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1644         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1645         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1646         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1647         ok(delete_pf("msitest", FALSE), "File not installed\n");
1648     }
1649
1650     delete_cab_files();
1651     DeleteFile(msifile);
1652
1653     create_cc_test_files();
1654     create_database(msifile, cc2_tables, sizeof(cc2_tables) / sizeof(msi_table));
1655
1656     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1657
1658     r = MsiInstallProductA(msifile, NULL);
1659     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1660     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1661     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
1662     ok(delete_pf("msitest\\tiberius", TRUE), "File not installed\n");
1663     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1664     ok(delete_pf("msitest", FALSE), "File not installed\n");
1665
1666     delete_cab_files();
1667     DeleteFile(msifile);
1668 }
1669
1670 static void test_caborder(void)
1671 {
1672     UINT r;
1673
1674     create_file("imperator", 100);
1675     create_file("maximus", 500);
1676     create_file("augustus", 50000);
1677     create_file("caesar", 500);
1678
1679     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1680
1681     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1682
1683     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
1684     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
1685     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1686
1687     r = MsiInstallProductA(msifile, NULL);
1688     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1689     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1690     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1691     todo_wine
1692     {
1693         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1694         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1695     }
1696
1697     delete_cab_files();
1698
1699     create_cab_file("test1.cab", MEDIA_SIZE, "imperator\0");
1700     create_cab_file("test2.cab", MEDIA_SIZE, "maximus\0augustus\0");
1701     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1702
1703     r = MsiInstallProductA(msifile, NULL);
1704     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1705     ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1706     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1707     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1708     todo_wine
1709     {
1710         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1711     }
1712
1713     delete_cab_files();
1714     DeleteFile(msifile);
1715
1716     create_cc_test_files();
1717     create_database(msifile, co_tables, sizeof(co_tables) / sizeof(msi_table));
1718
1719     r = MsiInstallProductA(msifile, NULL);
1720     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1721     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1722     ok(!delete_pf("msitest", FALSE), "File is installed\n");
1723     todo_wine
1724     {
1725         ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1726         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1727     }
1728
1729     delete_cab_files();
1730     DeleteFile(msifile);
1731
1732     create_cc_test_files();
1733     create_database(msifile, co2_tables, sizeof(co2_tables) / sizeof(msi_table));
1734
1735     r = MsiInstallProductA(msifile, NULL);
1736     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1737     todo_wine
1738     {
1739         ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1740         ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1741         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1742         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1743     }
1744
1745     delete_cab_files();
1746     DeleteFile("imperator");
1747     DeleteFile("maximus");
1748     DeleteFile("augustus");
1749     DeleteFile("caesar");
1750     DeleteFile(msifile);
1751 }
1752
1753 static void test_mixedmedia(void)
1754 {
1755     UINT r;
1756
1757     CreateDirectoryA("msitest", NULL);
1758     create_file("msitest\\maximus", 500);
1759     create_file("msitest\\augustus", 500);
1760     create_file("caesar", 500);
1761
1762     create_database(msifile, mm_tables, sizeof(mm_tables) / sizeof(msi_table));
1763
1764     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1765
1766     create_cab_file("test1.cab", MEDIA_SIZE, "caesar\0");
1767
1768     r = MsiInstallProductA(msifile, NULL);
1769     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1770     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1771     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1772     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1773     ok(delete_pf("msitest", FALSE), "File not installed\n");
1774
1775     /* Delete the files in the temp (current) folder */
1776     DeleteFile("msitest\\maximus");
1777     DeleteFile("msitest\\augustus");
1778     RemoveDirectory("msitest");
1779     DeleteFile("caesar");
1780     DeleteFile("test1.cab");
1781     DeleteFile(msifile);
1782 }
1783
1784 static void test_samesequence(void)
1785 {
1786     UINT r;
1787
1788     create_cc_test_files();
1789     create_database(msifile, ss_tables, sizeof(ss_tables) / sizeof(msi_table));
1790
1791     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1792
1793     r = MsiInstallProductA(msifile, NULL);
1794     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
1795     {
1796         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1797         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1798         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1799         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1800         ok(delete_pf("msitest", FALSE), "File not installed\n");
1801     }
1802
1803     delete_cab_files();
1804     DeleteFile(msifile);
1805 }
1806
1807 static void test_uiLevelFlags(void)
1808 {
1809     UINT r;
1810
1811     create_cc_test_files();
1812     create_database(msifile, ui_tables, sizeof(ui_tables) / sizeof(msi_table));
1813
1814     MsiSetInternalUI(INSTALLUILEVEL_NONE | INSTALLUILEVEL_SOURCERESONLY, NULL);
1815
1816     r = MsiInstallProductA(msifile, NULL);
1817     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
1818     {
1819         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1820         ok(!delete_pf("msitest\\maximus", TRUE), "UI install occurred, but execute-only was requested.\n");
1821         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1822         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1823         ok(delete_pf("msitest", FALSE), "File not installed\n");
1824     }
1825
1826     delete_cab_files();
1827     DeleteFile(msifile);
1828 }
1829
1830 static BOOL file_matches(LPSTR path)
1831 {
1832     CHAR buf[MAX_PATH];
1833     HANDLE file;
1834     DWORD size;
1835
1836     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1837                       NULL, OPEN_EXISTING, 0, NULL);
1838
1839     ZeroMemory(buf, MAX_PATH);
1840     ReadFile(file, buf, 15, &size, NULL);
1841     CloseHandle(file);
1842
1843     return !lstrcmp(buf, "msitest\\maximus");
1844 }
1845
1846 static void test_readonlyfile(void)
1847 {
1848     UINT r;
1849     DWORD size;
1850     HANDLE file;
1851     CHAR path[MAX_PATH];
1852
1853     CreateDirectoryA("msitest", NULL);
1854     create_file("msitest\\maximus", 500);
1855     create_database(msifile, rof_tables, sizeof(rof_tables) / sizeof(msi_table));
1856
1857     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1858
1859     lstrcpy(path, PROG_FILES_DIR);
1860     lstrcat(path, "\\msitest");
1861     CreateDirectory(path, NULL);
1862
1863     lstrcat(path, "\\maximus");
1864     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1865                       NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
1866
1867     WriteFile(file, "readonlyfile", 20, &size, NULL);
1868     CloseHandle(file);
1869
1870     r = MsiInstallProductA(msifile, NULL);
1871     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1872     ok(file_matches(path), "Expected file to be overwritten\n");
1873     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1874     ok(delete_pf("msitest", FALSE), "File not installed\n");
1875
1876     /* Delete the files in the temp (current) folder */
1877     DeleteFile("msitest\\maximus");
1878     RemoveDirectory("msitest");
1879     DeleteFile(msifile);
1880 }
1881
1882 static void test_setdirproperty(void)
1883 {
1884     UINT r;
1885
1886     CreateDirectoryA("msitest", NULL);
1887     create_file("msitest\\maximus", 500);
1888     create_database(msifile, sdp_tables, sizeof(sdp_tables) / sizeof(msi_table));
1889
1890     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1891
1892     r = MsiInstallProductA(msifile, NULL);
1893     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1894     ok(delete_cf("msitest\\maximus", TRUE), "File not installed\n");
1895     ok(delete_cf("msitest", FALSE), "File not installed\n");
1896
1897     /* Delete the files in the temp (current) folder */
1898     DeleteFile(msifile);
1899     DeleteFile("msitest\\maximus");
1900     RemoveDirectory("msitest");
1901 }
1902
1903 static void test_cabisextracted(void)
1904 {
1905     UINT r;
1906
1907     CreateDirectoryA("msitest", NULL);
1908     create_file("msitest\\gaius", 500);
1909     create_file("maximus", 500);
1910     create_file("augustus", 500);
1911     create_file("caesar", 500);
1912
1913     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
1914     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
1915     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1916
1917     create_database(msifile, cie_tables, sizeof(cie_tables) / sizeof(msi_table));
1918
1919     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1920
1921     r = MsiInstallProductA(msifile, NULL);
1922     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1923     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1924     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1925     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1926     ok(delete_pf("msitest\\gaius", TRUE), "File not installed\n");
1927     ok(delete_pf("msitest", FALSE), "File not installed\n");
1928
1929     /* Delete the files in the temp (current) folder */
1930     delete_cab_files();
1931     DeleteFile(msifile);
1932     DeleteFile("maximus");
1933     DeleteFile("augustus");
1934     DeleteFile("caesar");
1935     DeleteFile("msitest\\gaius");
1936     RemoveDirectory("msitest");
1937 }
1938
1939 static void test_concurrentinstall(void)
1940 {
1941     UINT r;
1942     CHAR path[MAX_PATH];
1943
1944     CreateDirectoryA("msitest", NULL);
1945     CreateDirectoryA("msitest\\msitest", NULL);
1946     create_file("msitest\\maximus", 500);
1947     create_file("msitest\\msitest\\augustus", 500);
1948
1949     create_database(msifile, ci_tables, sizeof(ci_tables) / sizeof(msi_table));
1950
1951     lstrcpyA(path, CURR_DIR);
1952     lstrcatA(path, "\\msitest\\concurrent.msi");
1953     create_database(path, ci2_tables, sizeof(ci2_tables) / sizeof(msi_table));
1954
1955     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
1956
1957     r = MsiInstallProductA(msifile, NULL);
1958     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1959     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1960     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1961     ok(delete_pf("msitest", FALSE), "File not installed\n");
1962
1963     DeleteFile(path);
1964
1965     r = MsiInstallProductA(msifile, NULL);
1966     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1967     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1968     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
1969     ok(delete_pf("msitest", FALSE), "File not installed\n");
1970
1971     DeleteFile(msifile);
1972     DeleteFile("msitest\\msitest\\augustus");
1973     DeleteFile("msitest\\maximus");
1974     RemoveDirectory("msitest\\msitest");
1975     RemoveDirectory("msitest");
1976 }
1977
1978 static void test_setpropertyfolder(void)
1979 {
1980     UINT r;
1981
1982     CreateDirectoryA("msitest", NULL);
1983     create_file("msitest\\maximus", 500);
1984
1985     create_database(msifile, spf_tables, sizeof(spf_tables) / sizeof(msi_table));
1986
1987     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
1988
1989     r = MsiInstallProductA(msifile, NULL);
1990     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1991     ok(delete_pf("msitest\\added\\maximus", TRUE), "File not installed\n");
1992     ok(delete_pf("msitest\\added", FALSE), "File not installed\n");
1993     ok(delete_pf("msitest", FALSE), "File not installed\n");
1994
1995     /* Delete the files in the temp (current) folder */
1996     DeleteFile(msifile);
1997     DeleteFile("msitest\\maximus");
1998     RemoveDirectory("msitest");
1999 }
2000
2001 static BOOL file_exists(LPCSTR file)
2002 {
2003     return GetFileAttributes(file) != INVALID_FILE_ATTRIBUTES;
2004 }
2005
2006 static BOOL pf_exists(LPCSTR file)
2007 {
2008     CHAR path[MAX_PATH];
2009
2010     lstrcpyA(path, PROG_FILES_DIR);
2011     lstrcatA(path, "\\");
2012     lstrcatA(path, file);
2013
2014     return file_exists(path);
2015 }
2016
2017 static void delete_pfmsitest_files(void)
2018 {
2019     SHFILEOPSTRUCT shfl;
2020     CHAR path[MAX_PATH+11];
2021
2022     lstrcpyA(path, PROG_FILES_DIR);
2023     lstrcatA(path, "\\msitest\\*");
2024     path[strlen(path) + 1] = '\0';
2025
2026     shfl.hwnd = NULL;
2027     shfl.wFunc = FO_DELETE;
2028     shfl.pFrom = path;
2029     shfl.pTo = NULL;
2030     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
2031
2032     SHFileOperation(&shfl);
2033
2034     lstrcpyA(path, PROG_FILES_DIR);
2035     lstrcatA(path, "\\msitest");
2036     RemoveDirectoryA(path);
2037 }
2038
2039 static void check_reg_str(HKEY prodkey, LPCSTR name, LPCSTR expected, BOOL bcase, DWORD line)
2040 {
2041     char val[MAX_PATH];
2042     DWORD size, type;
2043     LONG res;
2044
2045     size = MAX_PATH;
2046     val[0] = '\0';
2047     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)val, &size);
2048
2049     if (res != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ))
2050     {
2051         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2052         return;
2053     }
2054
2055     if (!expected)
2056         ok_(__FILE__, line)(lstrlenA(val) == 0, "Expected empty string, got %s\n", val);
2057     else
2058     {
2059         if (bcase)
2060             ok_(__FILE__, line)(!lstrcmpA(val, expected), "Expected %s, got %s\n", expected, val);
2061         else
2062             ok_(__FILE__, line)(!lstrcmpiA(val, expected), "Expected %s, got %s\n", expected, val);
2063     }
2064 }
2065
2066 static void check_reg_dword(HKEY prodkey, LPCSTR name, DWORD expected, DWORD line)
2067 {
2068     DWORD val, size, type;
2069     LONG res;
2070
2071     size = sizeof(DWORD);
2072     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)&val, &size);
2073
2074     if (res != ERROR_SUCCESS || type != REG_DWORD)
2075     {
2076         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2077         return;
2078     }
2079
2080     ok_(__FILE__, line)(val == expected, "Expected %d, got %d\n", expected, val);
2081 }
2082
2083 #define CHECK_REG_STR(prodkey, name, expected) \
2084     check_reg_str(prodkey, name, expected, TRUE, __LINE__);
2085
2086 #define CHECK_REG_ISTR(prodkey, name, expected) \
2087     check_reg_str(prodkey, name, expected, FALSE, __LINE__);
2088
2089 #define CHECK_REG_DWORD(prodkey, name, expected) \
2090     check_reg_dword(prodkey, name, expected, __LINE__);
2091
2092 static void get_date_str(LPSTR date)
2093 {
2094     SYSTEMTIME systime;
2095
2096     static const char date_fmt[] = "%d%02d%02d";
2097     GetLocalTime(&systime);
2098     sprintf(date, date_fmt, systime.wYear, systime.wMonth, systime.wDay);
2099 }
2100
2101 static void test_publish_registerproduct(void)
2102 {
2103     UINT r;
2104     LONG res;
2105     HKEY uninstall, prodkey;
2106     INSTALLSTATE state;
2107     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2108     char date[MAX_PATH];
2109     char temp[MAX_PATH];
2110
2111     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2112
2113     if (!pMsiQueryComponentStateA)
2114     {
2115         skip("MsiQueryComponentStateA is not available\n");
2116         return;
2117     }
2118
2119     get_date_str(date);
2120     GetTempPath(MAX_PATH, temp);
2121
2122     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2123     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2124
2125     CreateDirectoryA("msitest", NULL);
2126     create_file("msitest\\maximus", 500);
2127
2128     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2129
2130     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2131
2132     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2133     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2134
2135     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2136     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2137
2138     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2139     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2140
2141     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2142                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2143     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2144     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2145
2146     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2147     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2148
2149     /* RegisterProduct */
2150     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
2151     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2152     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2153     ok(pf_exists("msitest"), "File not installed\n");
2154
2155     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2156     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2157
2158     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2159     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2160
2161     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2162     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2163
2164     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2165                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2166     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2167     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2168
2169     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2170     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2171
2172     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
2173     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
2174     CHECK_REG_STR(prodkey, "InstallDate", date);
2175     CHECK_REG_STR(prodkey, "InstallSource", temp);
2176     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2177     CHECK_REG_STR(prodkey, "Publisher", "Wine");
2178     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2179     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
2180     CHECK_REG_STR(prodkey, "Comments", NULL);
2181     CHECK_REG_STR(prodkey, "Contact", NULL);
2182     CHECK_REG_STR(prodkey, "HelpLink", NULL);
2183     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
2184     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
2185     CHECK_REG_STR(prodkey, "Readme", NULL);
2186     CHECK_REG_STR(prodkey, "Size", NULL);
2187     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
2188     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
2189     CHECK_REG_DWORD(prodkey, "Language", 1033);
2190     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
2191     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
2192     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
2193     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
2194     todo_wine
2195     {
2196         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
2197     }
2198
2199     RegCloseKey(prodkey);
2200
2201     /* try to uninstall after RegisterProduct */
2202     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2203     todo_wine
2204     {
2205         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2206     }
2207     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2208     ok(pf_exists("msitest"), "File deleted\n");
2209
2210     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2211     todo_wine
2212     {
2213         ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2214     }
2215
2216     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2217     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2218
2219     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2220     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2221
2222     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2223                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2224     todo_wine
2225     {
2226         ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2227     }
2228     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2229
2230     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2231     todo_wine
2232     {
2233         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2234     }
2235
2236     todo_wine
2237     {
2238         CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
2239         CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
2240         CHECK_REG_STR(prodkey, "InstallDate", date);
2241         CHECK_REG_STR(prodkey, "InstallSource", temp);
2242         CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2243         CHECK_REG_STR(prodkey, "Publisher", "Wine");
2244         CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2245         CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
2246         CHECK_REG_STR(prodkey, "Comments", NULL);
2247         CHECK_REG_STR(prodkey, "Contact", NULL);
2248         CHECK_REG_STR(prodkey, "HelpLink", NULL);
2249         CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
2250         CHECK_REG_STR(prodkey, "InstallLocation", NULL);
2251         CHECK_REG_STR(prodkey, "Readme", NULL);
2252         CHECK_REG_STR(prodkey, "Size", NULL);
2253         CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
2254         CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
2255         CHECK_REG_DWORD(prodkey, "Language", 1033);
2256         CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
2257         CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
2258         CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
2259         CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
2260         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
2261     }
2262
2263     RegCloseKey(prodkey);
2264
2265     /* full install to remove */
2266     r = MsiInstallProductA(msifile, "FULL=1");
2267     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2268     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2269     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2270
2271     RegCloseKey(uninstall);
2272     DeleteFile(msifile);
2273     DeleteFile("msitest\\maximus");
2274     RemoveDirectory("msitest");
2275     delete_pfmsitest_files();
2276 }
2277
2278 static void test_publish_publishproduct(void)
2279 {
2280     UINT r;
2281     LONG res;
2282     HKEY uninstall, prodkey;
2283     INSTALLSTATE state;
2284     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2285
2286     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2287
2288     if (!pMsiQueryComponentStateA)
2289     {
2290         skip("MsiQueryComponentStateA is not available\n");
2291         return;
2292     }
2293
2294     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2295     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2296
2297     CreateDirectoryA("msitest", NULL);
2298     create_file("msitest\\maximus", 500);
2299
2300     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2301
2302     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2303
2304     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2305     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2306
2307     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2308     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2309
2310     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2311     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2312
2313     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2314                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2315     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2316     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2317
2318     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2319     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2320
2321     /* PublishProduct */
2322     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
2323     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2324     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2325     ok(pf_exists("msitest"), "File not installed\n");
2326
2327     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2328     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2329
2330     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2331     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2332
2333     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2334     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2335
2336     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2337                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2338     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2339     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2340
2341     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2342     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2343
2344     /* try to uninstall after PublishProduct */
2345     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2346     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2347     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2348     ok(pf_exists("msitest"), "File deleted\n");
2349
2350     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2351     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2352
2353     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2354     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2355
2356     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2357     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2358
2359     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2360                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2361     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2362     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2363
2364     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2365     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2366
2367     /* full install to remove */
2368     r = MsiInstallProductA(msifile, "FULL=1");
2369     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2370     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2371     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2372
2373     RegCloseKey(uninstall);
2374     DeleteFile(msifile);
2375     DeleteFile("msitest\\maximus");
2376     RemoveDirectory("msitest");
2377     delete_pfmsitest_files();
2378 }
2379
2380 static void test_publish_publishfeatures(void)
2381 {
2382     UINT r;
2383     LONG res;
2384     HKEY uninstall, prodkey;
2385     INSTALLSTATE state;
2386     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2387
2388     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2389
2390     if (!pMsiQueryComponentStateA)
2391     {
2392         skip("MsiQueryComponentStateA is not available\n");
2393         return;
2394     }
2395
2396     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2397     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2398
2399     CreateDirectoryA("msitest", NULL);
2400     create_file("msitest\\maximus", 500);
2401
2402     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2403
2404     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2405
2406     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2407     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2408
2409     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2410     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2411
2412     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2413     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2414
2415     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2416                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2417     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2418     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2419
2420     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2421     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2422
2423     /* PublishFeatures */
2424     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
2425     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2426     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2427     ok(pf_exists("msitest"), "File not installed\n");
2428
2429     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2430     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2431
2432     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2433     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2434
2435     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2436     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2437
2438     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2439                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2440     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2441     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2442
2443     /* try to uninstall after PublishFeatures */
2444     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2445     todo_wine
2446     {
2447         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2448     }
2449     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2450     ok(pf_exists("msitest"), "File deleted\n");
2451
2452     /* PublishFeatures and PublishProduct */
2453     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1 PUBLISH_FEATURES=1");
2454     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2455     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2456     ok(pf_exists("msitest"), "File not installed\n");
2457
2458     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2459     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2460
2461     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2462     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2463
2464     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2465     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2466
2467     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2468                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2469     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2470     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2471
2472     /* PublishFeatures and RegisterProduct */
2473     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_FEATURES=1");
2474     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2475     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2476     ok(pf_exists("msitest"), "File not installed\n");
2477
2478     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2479     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2480
2481     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2482     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2483
2484     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2485     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2486
2487     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2488                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2489     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2490     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2491
2492     /* full install to remove */
2493     r = MsiInstallProductA(msifile, "FULL=1");
2494     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2495     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2496     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2497
2498     RegCloseKey(uninstall);
2499     DeleteFile(msifile);
2500     DeleteFile("msitest\\maximus");
2501     RemoveDirectory("msitest");
2502     delete_pfmsitest_files();
2503 }
2504
2505 static void test_publish_registeruser(void)
2506 {
2507     UINT r;
2508     LONG res;
2509     HKEY uninstall, prodkey;
2510     INSTALLSTATE state;
2511     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2512
2513     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2514
2515     if (!pMsiQueryComponentStateA)
2516     {
2517         skip("MsiQueryComponentStateA is not available\n");
2518         return;
2519     }
2520
2521     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2522     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2523
2524     CreateDirectoryA("msitest", NULL);
2525     create_file("msitest\\maximus", 500);
2526
2527     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2528
2529     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2530
2531     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2532     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2533
2534     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2535     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2536
2537     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2538     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2539
2540     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2541                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2542     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2543     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2544
2545     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2546     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2547
2548     /* RegisterUser */
2549     r = MsiInstallProductA(msifile, "REGISTER_USER=1");
2550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2551     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2552     ok(pf_exists("msitest"), "File not installed\n");
2553
2554     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2555     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2556
2557     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2558     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2559
2560     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2561     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2562
2563     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2564                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2565     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2566     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2567
2568     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2569     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2570
2571     /* try to uninstall after RegisterUser */
2572     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2573     todo_wine
2574     {
2575         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2576     }
2577     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2578     ok(pf_exists("msitest"), "File deleted\n");
2579
2580     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2581     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2582
2583     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2584     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2585
2586     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2587     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2588
2589     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2590                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2591     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2592     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2593
2594     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2595     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2596
2597     /* full install to remove */
2598     r = MsiInstallProductA(msifile, "FULL=1");
2599     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2600     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2601     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2602
2603     RegCloseKey(uninstall);
2604     DeleteFile(msifile);
2605     DeleteFile("msitest\\maximus");
2606     RemoveDirectory("msitest");
2607     delete_pfmsitest_files();
2608 }
2609
2610 static void get_user_sid(LPSTR *usersid)
2611 {
2612     HANDLE token;
2613     BYTE buf[1024];
2614     DWORD size;
2615     PTOKEN_USER user;
2616     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
2617     static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
2618
2619     *usersid = NULL;
2620     pConvertSidToStringSidA = (void *)GetProcAddress(hadvapi32, "ConvertSidToStringSidA");
2621     if (!pConvertSidToStringSidA)
2622         return;
2623
2624     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
2625     size = sizeof(buf);
2626     GetTokenInformation(token, TokenUser, (void *)buf, size, &size);
2627     user = (PTOKEN_USER)buf;
2628     pConvertSidToStringSidA(user->User.Sid, usersid);
2629 }
2630
2631 static void test_publish_processcomponents(void)
2632 {
2633     UINT r;
2634     LONG res;
2635     HKEY uninstall, prodkey, comp;
2636     INSTALLSTATE state;
2637     LPSTR usersid;
2638     CHAR keypath[MAX_PATH];
2639     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2640
2641     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2642
2643     if (!pMsiQueryComponentStateA)
2644     {
2645         skip("MsiQueryComponentStateA is not available\n");
2646         return;
2647     }
2648
2649     get_user_sid(&usersid);
2650     if (!usersid)
2651     {
2652         skip("ConvertSidToStringSidA is not available\n");
2653         return;
2654     }
2655
2656     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2657     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2658
2659     CreateDirectoryA("msitest", NULL);
2660     create_file("msitest\\maximus", 500);
2661
2662     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2663
2664     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2665
2666     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2667     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2668
2669     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2670     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2671
2672     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2673     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2674
2675     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2676                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2677     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2678     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2679
2680     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2681     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2682
2683     /* ProcessComponent */
2684     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
2685     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2686     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2687     ok(pf_exists("msitest"), "File not installed\n");
2688
2689     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2690     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2691
2692     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2693     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2694
2695     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2696                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2697     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2698     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2699
2700     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2701     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2702
2703     /* try to uninstall after ProcessComponents */
2704     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2705     todo_wine
2706     {
2707         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2708     }
2709     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2710     ok(pf_exists("msitest"), "File deleted\n");
2711
2712     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2713     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2714
2715     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2716     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2717
2718     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2719     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2720
2721     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2722                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2723     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2724     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2725
2726     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2727     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2728
2729     /* ProcessComponent with PublishProduct */
2730     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1 PROCESS_COMPONENTS=1");
2731     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2732     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2733     ok(pf_exists("msitest"), "File not installed\n");
2734
2735     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2736     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2737
2738     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2739     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2740
2741     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2742     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2743
2744     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2745                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2746     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2747     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2748
2749     /* uninstall */
2750     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2751     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2752
2753     /* ProcessComponent with RegisterProduct */
2754     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PROCESS_COMPONENTS=1");
2755     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2756     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2757     ok(pf_exists("msitest"), "File not installed\n");
2758
2759     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2760     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2761
2762     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2763     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2764
2765     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2766     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2767
2768     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2769                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2770     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2771     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2772
2773     /* ProcessComponent with RegisterProduct and PublishProduct */
2774     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1 PROCESS_COMPONENTS=1");
2775     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2776     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2777     ok(pf_exists("msitest"), "File not installed\n");
2778
2779     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2780     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2781
2782     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2783     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2784
2785     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2786     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2787
2788     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2789                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2791     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2792
2793     /* uninstall */
2794     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2795     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2796
2797     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2798     lstrcatA(keypath, usersid);
2799     lstrcatA(keypath, "\\Components\\CBABC2FDCCB35E749A8944D8C1C098B5");
2800
2801     /* native has trouble removing the comp key unless it's a full install */
2802     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
2803     if (res == ERROR_SUCCESS)
2804     {
2805         RegDeleteKeyA(comp, "");
2806         RegCloseKey(comp);
2807     }
2808
2809     RegCloseKey(uninstall);
2810     DeleteFile(msifile);
2811     DeleteFile("msitest\\maximus");
2812     RemoveDirectory("msitest");
2813     delete_pfmsitest_files();
2814 }
2815
2816 static void test_publish(void)
2817 {
2818     UINT r;
2819     LONG res;
2820     HKEY uninstall, prodkey;
2821     INSTALLSTATE state;
2822     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2823     char date[MAX_PATH];
2824     char temp[MAX_PATH];
2825
2826     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2827
2828     if (!pMsiQueryComponentStateA)
2829     {
2830         skip("MsiQueryComponentStateA is not available\n");
2831         return;
2832     }
2833
2834     get_date_str(date);
2835     GetTempPath(MAX_PATH, temp);
2836
2837     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2838     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2839
2840     CreateDirectoryA("msitest", NULL);
2841     create_file("msitest\\maximus", 500);
2842
2843     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2844
2845     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2846
2847     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2848     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2849
2850     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2851     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2852
2853     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2854     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2855
2856     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2857                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2858     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2859     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2860
2861     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2862     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2863
2864     /* nothing published */
2865     r = MsiInstallProductA(msifile, NULL);
2866     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2867     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2868     ok(pf_exists("msitest"), "File not installed\n");
2869
2870     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2871     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2872
2873     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2874     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2875
2876     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2877     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2878
2879     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2880                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2881     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2882     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2883
2884     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2885     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2886
2887     /* PublishProduct and RegisterProduct */
2888     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1");
2889     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2890     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2891     ok(pf_exists("msitest"), "File not installed\n");
2892
2893     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2894     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2895
2896     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2897     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2898
2899     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2900     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2901
2902     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2903                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2904     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2905     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2906
2907     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2908     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2909
2910     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
2911     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
2912     CHECK_REG_STR(prodkey, "InstallDate", date);
2913     CHECK_REG_STR(prodkey, "InstallSource", temp);
2914     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2915     CHECK_REG_STR(prodkey, "Publisher", "Wine");
2916     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2917     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
2918     CHECK_REG_STR(prodkey, "Comments", NULL);
2919     CHECK_REG_STR(prodkey, "Contact", NULL);
2920     CHECK_REG_STR(prodkey, "HelpLink", NULL);
2921     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
2922     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
2923     CHECK_REG_STR(prodkey, "Readme", NULL);
2924     CHECK_REG_STR(prodkey, "Size", NULL);
2925     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
2926     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
2927     CHECK_REG_DWORD(prodkey, "Language", 1033);
2928     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
2929     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
2930     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
2931     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
2932     todo_wine
2933     {
2934         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
2935     }
2936
2937     RegCloseKey(prodkey);
2938
2939     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2940     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2941     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2942     ok(pf_exists("msitest"), "File deleted\n");
2943
2944     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2945     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2946
2947     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2948     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2949
2950     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2951     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2952
2953     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2954                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2955     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2956     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2957
2958     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2959     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2960
2961     /* complete install */
2962     r = MsiInstallProductA(msifile, "FULL=1");
2963     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2964     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2965     ok(pf_exists("msitest"), "File not installed\n");
2966
2967     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2968     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2969
2970     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2971     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2972
2973     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2974     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2975
2976     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2977                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2978     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2979     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2980
2981     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2982     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2983
2984     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
2985     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
2986     CHECK_REG_STR(prodkey, "InstallDate", date);
2987     CHECK_REG_STR(prodkey, "InstallSource", temp);
2988     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2989     CHECK_REG_STR(prodkey, "Publisher", "Wine");
2990     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2991     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
2992     CHECK_REG_STR(prodkey, "Comments", NULL);
2993     CHECK_REG_STR(prodkey, "Contact", NULL);
2994     CHECK_REG_STR(prodkey, "HelpLink", NULL);
2995     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
2996     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
2997     CHECK_REG_STR(prodkey, "Readme", NULL);
2998     CHECK_REG_STR(prodkey, "Size", NULL);
2999     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3000     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3001     CHECK_REG_DWORD(prodkey, "Language", 1033);
3002     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3003     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3004     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3005     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3006     todo_wine
3007     {
3008         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3009     }
3010
3011     RegCloseKey(prodkey);
3012
3013     /* no UnpublishFeatures */
3014     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3015     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3016     todo_wine
3017     {
3018         ok(!pf_exists("msitest\\maximus"), "File deleted\n");
3019         ok(!pf_exists("msitest"), "File deleted\n");
3020     }
3021
3022     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3023     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3024
3025     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3026     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3027
3028     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3029     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3030
3031     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3032                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3033     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3034     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3035
3036     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3037     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3038
3039     /* complete install */
3040     r = MsiInstallProductA(msifile, "FULL=1");
3041     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3042     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3043     ok(pf_exists("msitest"), "File not installed\n");
3044
3045     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3046     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3047
3048     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3049     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3050
3051     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3052     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3053
3054     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3055                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3056     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3057     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3058
3059     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3060     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3061
3062     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3063     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3064     CHECK_REG_STR(prodkey, "InstallDate", date);
3065     CHECK_REG_STR(prodkey, "InstallSource", temp);
3066     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3067     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3068     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3069     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3070     CHECK_REG_STR(prodkey, "Comments", NULL);
3071     CHECK_REG_STR(prodkey, "Contact", NULL);
3072     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3073     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3074     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3075     CHECK_REG_STR(prodkey, "Readme", NULL);
3076     CHECK_REG_STR(prodkey, "Size", NULL);
3077     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3078     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3079     CHECK_REG_DWORD(prodkey, "Language", 1033);
3080     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3081     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3082     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3083     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3084     todo_wine
3085     {
3086         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3087     }
3088
3089     RegCloseKey(prodkey);
3090
3091     /* UnpublishFeatures, only feature removed.  Only works when entire product is removed */
3092     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature");
3093     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3094     ok(pf_exists("msitest\\maximus"), "File deleted\n");
3095     ok(pf_exists("msitest"), "File deleted\n");
3096
3097     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3098     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3099
3100     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3101     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3102
3103     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3104     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3105
3106     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3107                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3108     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3109     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3110
3111     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3112     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3113
3114     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3115     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3116     CHECK_REG_STR(prodkey, "InstallDate", date);
3117     CHECK_REG_STR(prodkey, "InstallSource", temp);
3118     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3119     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3120     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3121     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3122     CHECK_REG_STR(prodkey, "Comments", NULL);
3123     CHECK_REG_STR(prodkey, "Contact", NULL);
3124     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3125     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3126     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3127     CHECK_REG_STR(prodkey, "Readme", NULL);
3128     CHECK_REG_STR(prodkey, "Size", NULL);
3129     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3130     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3131     CHECK_REG_DWORD(prodkey, "Language", 1033);
3132     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3133     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3134     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3135     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3136     todo_wine
3137     {
3138         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3139     }
3140
3141     RegCloseKey(prodkey);
3142
3143     /* complete install */
3144     r = MsiInstallProductA(msifile, "FULL=1");
3145     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3146     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3147     ok(pf_exists("msitest"), "File not installed\n");
3148
3149     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3150     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3151
3152     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3153     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3154
3155     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3156     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3157
3158     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3159                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3160     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3161     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3162
3163     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3164     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3165
3166     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3167     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3168     CHECK_REG_STR(prodkey, "InstallDate", date);
3169     CHECK_REG_STR(prodkey, "InstallSource", temp);
3170     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3171     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3172     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3173     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3174     CHECK_REG_STR(prodkey, "Comments", NULL);
3175     CHECK_REG_STR(prodkey, "Contact", NULL);
3176     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3177     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3178     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3179     CHECK_REG_STR(prodkey, "Readme", NULL);
3180     CHECK_REG_STR(prodkey, "Size", NULL);
3181     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3182     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3183     CHECK_REG_DWORD(prodkey, "Language", 1033);
3184     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3185     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3186     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3187     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3188     todo_wine
3189     {
3190         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3191     }
3192
3193     RegCloseKey(prodkey);
3194
3195     /* UnpublishFeatures, both features removed */
3196     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature,montecristo");
3197     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3198     todo_wine
3199     {
3200         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3201         ok(!pf_exists("msitest"), "File not deleted\n");
3202     }
3203
3204     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3205     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3206
3207     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3208     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3209
3210     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3211     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3212
3213     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3214                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3215     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3216     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3217
3218     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3219     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3220
3221     /* complete install */
3222     r = MsiInstallProductA(msifile, "FULL=1");
3223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3224     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3225     ok(pf_exists("msitest"), "File not installed\n");
3226
3227     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3228     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3229
3230     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3231     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3232
3233     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3234     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3235
3236     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3237                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3238     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3239     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3240
3241     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3242     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3243
3244     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3245     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3246     CHECK_REG_STR(prodkey, "InstallDate", date);
3247     CHECK_REG_STR(prodkey, "InstallSource", temp);
3248     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3249     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3250     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3251     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3252     CHECK_REG_STR(prodkey, "Comments", NULL);
3253     CHECK_REG_STR(prodkey, "Contact", NULL);
3254     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3255     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3256     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3257     CHECK_REG_STR(prodkey, "Readme", NULL);
3258     CHECK_REG_STR(prodkey, "Size", NULL);
3259     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3260     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3261     CHECK_REG_DWORD(prodkey, "Language", 1033);
3262     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3263     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3264     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3265     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3266     todo_wine
3267     {
3268         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3269     }
3270
3271     RegCloseKey(prodkey);
3272
3273     /* complete uninstall */
3274     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3275     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3276     todo_wine
3277     {
3278         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3279         ok(!pf_exists("msitest"), "File not deleted\n");
3280     }
3281
3282     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3283     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3284
3285     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3286     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3287
3288     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3289     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3290
3291     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3292                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3293     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3294     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3295
3296     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3297     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3298
3299     /* make sure 'Program Files\msitest' is removed */
3300     delete_pfmsitest_files();
3301
3302     RegCloseKey(uninstall);
3303     DeleteFile(msifile);
3304     DeleteFile("msitest\\maximus");
3305     RemoveDirectory("msitest");
3306 }
3307
3308 static void test_publishsourcelist(void)
3309 {
3310     UINT r;
3311     DWORD size;
3312     CHAR value[MAX_PATH];
3313     CHAR path[MAX_PATH];
3314     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
3315
3316     if (!pMsiSourceListEnumSourcesA || !pMsiSourceListGetInfoA)
3317     {
3318         skip("MsiSourceListEnumSourcesA and/or MsiSourceListGetInfoA are not available\n");
3319         return;
3320     }
3321
3322     CreateDirectoryA("msitest", NULL);
3323     create_file("msitest\\maximus", 500);
3324
3325     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
3326
3327     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3328
3329     r = MsiInstallProductA(msifile, NULL);
3330     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3331     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3332     ok(pf_exists("msitest"), "File not installed\n");
3333
3334     /* nothing published */
3335     size = 0xdeadbeef;
3336     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3337                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3338     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3339     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3340
3341     size = 0xdeadbeef;
3342     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3343                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3344     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3345     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3346
3347     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
3348     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3349     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3350     ok(pf_exists("msitest"), "File not installed\n");
3351
3352     /* after RegisterProduct */
3353     size = 0xdeadbeef;
3354     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3355                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3356     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3357     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3358
3359     size = 0xdeadbeef;
3360     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3361                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3362     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3363     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3364
3365     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
3366     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3367     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3368     ok(pf_exists("msitest"), "File not installed\n");
3369
3370     /* after ProcessComponents */
3371     size = 0xdeadbeef;
3372     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3373                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3374     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3375     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3376
3377     size = 0xdeadbeef;
3378     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3379                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3380     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3381     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3382
3383     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
3384     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3385     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3386     ok(pf_exists("msitest"), "File not installed\n");
3387
3388     /* after PublishFeatures */
3389     size = 0xdeadbeef;
3390     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3391                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3392     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3393     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3394
3395     size = 0xdeadbeef;
3396     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3397                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3398     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3399     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3400
3401     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
3402     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3403     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3404     ok(pf_exists("msitest"), "File not installed\n");
3405
3406     /* after PublishProduct */
3407     size = MAX_PATH;
3408     lstrcpyA(value, "aaa");
3409     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3410                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
3411     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3412     ok(!lstrcmpA(value, "msitest.msi"), "Expected 'msitest.msi', got %s\n", value);
3413     ok(size == 11, "Expected 11, got %d\n", size);
3414
3415     size = MAX_PATH;
3416     lstrcpyA(value, "aaa");
3417     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3418                                MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATH, value, &size);
3419     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3420     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
3421     ok(size == 0, "Expected 0, got %d\n", size);
3422
3423     size = MAX_PATH;
3424     lstrcpyA(value, "aaa");
3425     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3426                                MSICODE_PRODUCT, INSTALLPROPERTY_DISKPROMPT, value, &size);
3427     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3428     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
3429     ok(size == 0, "Expected 0, got %d\n", size);
3430
3431     lstrcpyA(path, CURR_DIR);
3432     lstrcatA(path, "\\");
3433
3434     size = MAX_PATH;
3435     lstrcpyA(value, "aaa");
3436     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3437                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size);
3438     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3439     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3440     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3441
3442     size = MAX_PATH;
3443     lstrcpyA(value, "aaa");
3444     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3445                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE, value, &size);
3446     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3447     ok(!lstrcmpA(value, "n"), "Expected \"n\", got \"%s\"\n", value);
3448     ok(size == 1, "Expected 1, got %d\n", size);
3449
3450     size = MAX_PATH;
3451     lstrcpyA(value, "aaa");
3452     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3453                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
3454     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3455     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
3456     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
3457
3458     size = MAX_PATH;
3459     lstrcpyA(value, "aaa");
3460     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3461                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
3462     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3463     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3464     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3465
3466     size = MAX_PATH;
3467     lstrcpyA(value, "aaa");
3468     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3469                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 1, value, &size);
3470     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3471     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
3472     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
3473
3474     /* complete uninstall */
3475     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3476     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3477     todo_wine
3478     {
3479         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3480         ok(!pf_exists("msitest"), "File not deleted\n");
3481     }
3482
3483     /* make sure 'Program Files\msitest' is removed */
3484     delete_pfmsitest_files();
3485
3486     DeleteFile(msifile);
3487     DeleteFile("msitest\\maximus");
3488     RemoveDirectory("msitest");
3489 }
3490
3491 static UINT run_query(MSIHANDLE hdb, MSIHANDLE hrec, const char *query)
3492 {
3493     MSIHANDLE hview = 0;
3494     UINT r;
3495
3496     r = MsiDatabaseOpenView(hdb, query, &hview);
3497     if(r != ERROR_SUCCESS)
3498         return r;
3499
3500     r = MsiViewExecute(hview, hrec);
3501     if(r == ERROR_SUCCESS)
3502         r = MsiViewClose(hview);
3503     MsiCloseHandle(hview);
3504     return r;
3505 }
3506
3507 static void set_transform_summary_info(void)
3508 {
3509     UINT r;
3510     MSIHANDLE suminfo = 0;
3511
3512     /* build summmary info */
3513     r = MsiGetSummaryInformation(0, mstfile, 3, &suminfo);
3514     todo_wine
3515     {
3516         ok(r == ERROR_SUCCESS , "Failed to open summaryinfo\n");
3517     }
3518
3519     r = MsiSummaryInfoSetProperty(suminfo, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
3520     todo_wine
3521     {
3522         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
3523     }
3524
3525     r = MsiSummaryInfoSetProperty(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
3526                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
3527                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
3528                         "{4C0EAA15-0264-4E5A-8758-609EF142B92D}");
3529     todo_wine
3530     {
3531         ok(r == ERROR_SUCCESS , "Failed to set summary info\n");
3532     }
3533
3534     r = MsiSummaryInfoSetProperty(suminfo, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
3535     todo_wine
3536     {
3537         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
3538     }
3539
3540     r = MsiSummaryInfoPersist(suminfo);
3541     todo_wine
3542     {
3543         ok(r == ERROR_SUCCESS , "Failed to make summary info persist\n");
3544     }
3545
3546     r = MsiCloseHandle(suminfo);
3547     ok(r == ERROR_SUCCESS , "Failed to close suminfo\n");
3548 }
3549
3550 static void generate_transform(void)
3551 {
3552     MSIHANDLE hdb1, hdb2;
3553     LPCSTR query;
3554     UINT r;
3555
3556     /* start with two identical databases */
3557     CopyFile(msifile, msifile2, FALSE);
3558
3559     r = MsiOpenDatabase(msifile2, MSIDBOPEN_TRANSACT, &hdb1);
3560     ok(r == ERROR_SUCCESS , "Failed to create database\n");
3561
3562     r = MsiDatabaseCommit(hdb1);
3563     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
3564
3565     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb2);
3566     ok(r == ERROR_SUCCESS , "Failed to create database\n");
3567
3568     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
3569     r = run_query(hdb1, 0, query);
3570     ok(r == ERROR_SUCCESS, "failed to add property\n");
3571
3572     /* database needs to be committed */
3573     MsiDatabaseCommit(hdb1);
3574
3575     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
3576     ok(r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r);
3577
3578 #if 0  /* not implemented in wine yet */
3579     r = MsiCreateTransformSummaryInfo(hdb2, hdb2, mstfile, 0, 0);
3580     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3581 #endif
3582
3583     MsiCloseHandle(hdb1);
3584     MsiCloseHandle(hdb2);
3585 }
3586
3587 /* data for generating a transform */
3588
3589 /* tables transform names - encoded as they would be in an msi database file */
3590 static const WCHAR name1[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
3591 static const WCHAR name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
3592 static const WCHAR name3[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
3593
3594 /* data in each table */
3595 static const char data1[] = /* _StringData */
3596     "propval";  /* all the strings squashed together */
3597
3598 static const WCHAR data2[] = { /* _StringPool */
3599 /*  len, refs */
3600     0,   0,    /* string 0 ''     */
3601     4,   1,    /* string 1 'prop' */
3602     3,   1,    /* string 2 'val'  */
3603 };
3604
3605 static const WCHAR data3[] = { /* Property */
3606     0x0201, 0x0001, 0x0002,
3607 };
3608
3609 static const struct {
3610     LPCWSTR name;
3611     const void *data;
3612     DWORD size;
3613 } table_transform_data[] =
3614 {
3615     { name1, data1, sizeof data1 - 1 },
3616     { name2, data2, sizeof data2 },
3617     { name3, data3, sizeof data3 },
3618 };
3619
3620 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
3621
3622 static void generate_transform_manual(void)
3623 {
3624     IStorage *stg = NULL;
3625     IStream *stm;
3626     WCHAR name[0x20];
3627     HRESULT r;
3628     DWORD i, count;
3629     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
3630
3631     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
3632
3633     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
3634
3635     r = StgCreateDocfile(name, mode, 0, &stg);
3636     ok(r == S_OK, "failed to create storage\n");
3637     if (!stg)
3638         return;
3639
3640     r = IStorage_SetClass(stg, &CLSID_MsiTransform);
3641     ok(r == S_OK, "failed to set storage type\n");
3642
3643     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
3644     {
3645         r = IStorage_CreateStream(stg, table_transform_data[i].name,
3646                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3647         if (FAILED(r))
3648         {
3649             ok(0, "failed to create stream %08x\n", r);
3650             continue;
3651         }
3652
3653         r = IStream_Write(stm, table_transform_data[i].data,
3654                           table_transform_data[i].size, &count);
3655         if (FAILED(r) || count != table_transform_data[i].size)
3656             ok(0, "failed to write stream\n");
3657         IStream_Release(stm);
3658     }
3659
3660     IStorage_Release(stg);
3661
3662     set_transform_summary_info();
3663 }
3664
3665 static void test_transformprop(void)
3666 {
3667     UINT r;
3668
3669     CreateDirectoryA("msitest", NULL);
3670     create_file("msitest\\augustus", 500);
3671
3672     create_database(msifile, tp_tables, sizeof(tp_tables) / sizeof(msi_table));
3673
3674     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3675
3676     r = MsiInstallProductA(msifile, NULL);
3677     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3678     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3679     ok(!delete_pf("msitest", FALSE), "File installed\n");
3680
3681     if (0)
3682         generate_transform();
3683     else
3684         generate_transform_manual();
3685
3686     r = MsiInstallProductA(msifile, "TRANSFORMS=winetest.mst");
3687     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3688     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
3689     ok(delete_pf("msitest", FALSE), "File not installed\n");
3690
3691     /* Delete the files in the temp (current) folder */
3692     DeleteFile(msifile);
3693     DeleteFile(msifile2);
3694     DeleteFile(mstfile);
3695     DeleteFile("msitest\\augustus");
3696     RemoveDirectory("msitest");
3697 }
3698
3699 static void test_currentworkingdir(void)
3700 {
3701     UINT r;
3702     CHAR path[MAX_PATH];
3703     LPSTR ptr, ptr2;
3704
3705     CreateDirectoryA("msitest", NULL);
3706     create_file("msitest\\augustus", 500);
3707
3708     create_database(msifile, cwd_tables, sizeof(cwd_tables) / sizeof(msi_table));
3709
3710     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3711
3712     CreateDirectoryA("diffdir", NULL);
3713     SetCurrentDirectoryA("diffdir");
3714
3715     sprintf(path, "..\\%s", msifile);
3716     r = MsiInstallProductA(path, NULL);
3717     todo_wine
3718     {
3719         ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
3720         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3721         ok(!delete_pf("msitest", FALSE), "File installed\n");
3722     }
3723
3724     sprintf(path, "%s\\%s", CURR_DIR, msifile);
3725     r = MsiInstallProductA(path, NULL);
3726     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3727     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
3728     ok(delete_pf("msitest", FALSE), "File not installed\n");
3729
3730     lstrcpyA(path, CURR_DIR);
3731     if (path[lstrlenA(path) - 1] != '\\')
3732         lstrcatA(path, "\\");
3733     lstrcatA(path, "msitest.msi");
3734
3735     ptr2 = strrchr(path, '\\');
3736     *ptr2 = '\0';
3737     ptr = strrchr(path, '\\');
3738     *ptr2 = '\\';
3739     *(ptr++) = '\0';
3740
3741     SetCurrentDirectoryA(path);
3742
3743     r = MsiInstallProductA(ptr, NULL);
3744     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3745     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
3746     ok(delete_pf("msitest", FALSE), "File not installed\n");
3747
3748     SetCurrentDirectoryA(CURR_DIR);
3749
3750     DeleteFile(msifile);
3751     DeleteFile("msitest\\augustus");
3752     RemoveDirectory("msitest");
3753     RemoveDirectory("diffdir");
3754 }
3755
3756 static void set_admin_summary_info(const CHAR *name)
3757 {
3758     MSIHANDLE db, summary;
3759     UINT r;
3760
3761     r = MsiOpenDatabaseA(name, MSIDBOPEN_DIRECT, &db);
3762     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3763
3764     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
3765     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3766
3767     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 5, NULL, NULL);
3768     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3769
3770     /* write the summary changes back to the stream */
3771     r = MsiSummaryInfoPersist(summary);
3772     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3773
3774     MsiCloseHandle(summary);
3775
3776     r = MsiDatabaseCommit(db);
3777     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3778
3779     MsiCloseHandle(db);
3780 }
3781
3782 static void test_admin(void)
3783 {
3784     UINT r;
3785
3786     CreateDirectoryA("msitest", NULL);
3787     create_file("msitest\\augustus", 500);
3788
3789     create_database(msifile, adm_tables, sizeof(adm_tables) / sizeof(msi_table));
3790     set_admin_summary_info(msifile);
3791
3792     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3793
3794     r = MsiInstallProductA(msifile, NULL);
3795     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3796     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3797     ok(!delete_pf("msitest", FALSE), "File installed\n");
3798     ok(!DeleteFile("c:\\msitest\\augustus"), "File installed\n");
3799     ok(!RemoveDirectory("c:\\msitest"), "File installed\n");
3800
3801     r = MsiInstallProductA(msifile, "ACTION=ADMIN");
3802     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3803     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3804     ok(!delete_pf("msitest", FALSE), "File installed\n");
3805     todo_wine
3806     {
3807         ok(DeleteFile("c:\\msitest\\augustus"), "File not installed\n");
3808         ok(RemoveDirectory("c:\\msitest"), "File not installed\n");
3809     }
3810
3811     DeleteFile(msifile);
3812     DeleteFile("msitest\\augustus");
3813     RemoveDirectory("msitest");
3814 }
3815
3816 static void set_admin_property_stream(LPCSTR file)
3817 {
3818     IStorage *stg;
3819     IStream *stm;
3820     WCHAR fileW[MAX_PATH];
3821     HRESULT hr;
3822     DWORD count;
3823     const DWORD mode = STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
3824
3825     /* AdminProperties */
3826     static const WCHAR stmname[] = {0x41ca,0x4330,0x3e71,0x44b5,0x4233,0x45f5,0x422c,0x4836,0};
3827     static const WCHAR data[] = {'M','Y','P','R','O','P','=','2','7','1','8',0};
3828
3829     MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH);
3830
3831     hr = StgOpenStorage(fileW, NULL, mode, NULL, 0, &stg);
3832     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
3833     if (!stg)
3834         return;
3835
3836     hr = IStorage_CreateStream(stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3837     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
3838
3839     hr = IStream_Write(stm, data, sizeof(data), &count);
3840     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
3841
3842     IStream_Release(stm);
3843     IStorage_Release(stg);
3844 }
3845
3846 static void test_adminprops(void)
3847 {
3848     UINT r;
3849
3850     CreateDirectoryA("msitest", NULL);
3851     create_file("msitest\\augustus", 500);
3852
3853     create_database(msifile, amp_tables, sizeof(amp_tables) / sizeof(msi_table));
3854     set_admin_summary_info(msifile);
3855     set_admin_property_stream(msifile);
3856
3857     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3858
3859     r = MsiInstallProductA(msifile, NULL);
3860     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3861     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
3862     ok(delete_pf("msitest", FALSE), "File installed\n");
3863
3864     DeleteFile(msifile);
3865     DeleteFile("msitest\\augustus");
3866     RemoveDirectory("msitest");
3867 }
3868
3869 static void create_pf_data(LPCSTR file, LPCSTR data, BOOL is_file)
3870 {
3871     CHAR path[MAX_PATH];
3872
3873     lstrcpyA(path, PROG_FILES_DIR);
3874     lstrcatA(path, "\\");
3875     lstrcatA(path, file);
3876
3877     if (is_file)
3878         create_file_data(path, data, 500);
3879     else
3880         CreateDirectoryA(path, NULL);
3881 }
3882
3883 #define create_pf(file, is_file) create_pf_data(file, file, is_file)
3884
3885 static void test_removefiles(void)
3886 {
3887     UINT r;
3888
3889     CreateDirectoryA("msitest", NULL);
3890     create_file("msitest\\hydrogen", 500);
3891     create_file("msitest\\helium", 500);
3892     create_file("msitest\\lithium", 500);
3893
3894     create_database(msifile, rem_tables, sizeof(rem_tables) / sizeof(msi_table));
3895
3896     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3897
3898     r = MsiInstallProductA(msifile, NULL);
3899     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3900     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
3901     ok(!pf_exists("msitest\\helium"), "File installed\n");
3902     ok(pf_exists("msitest\\lithium"), "File not installed\n");
3903     ok(pf_exists("msitest"), "File not installed\n");
3904
3905     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3906     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3907     ok(!pf_exists("msitest\\helium"), "File not deleted\n");
3908     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
3909     todo_wine
3910     {
3911         ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
3912         ok(delete_pf("msitest", FALSE), "File deleted\n");
3913     }
3914
3915     create_pf("msitest", FALSE);
3916     create_pf("msitest\\hydrogen", TRUE);
3917     create_pf("msitest\\helium", TRUE);
3918     create_pf("msitest\\lithium", TRUE);
3919
3920     r = MsiInstallProductA(msifile, NULL);
3921     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3922     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
3923     ok(pf_exists("msitest\\helium"), "File not installed\n");
3924     ok(pf_exists("msitest\\lithium"), "File not installed\n");
3925     ok(pf_exists("msitest"), "File not installed\n");
3926
3927     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3928     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3929     ok(delete_pf("msitest\\helium", TRUE), "File deleted\n");
3930     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
3931     todo_wine
3932     {
3933         ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
3934         ok(delete_pf("msitest", FALSE), "File deleted\n");
3935     }
3936
3937     create_pf("msitest", FALSE);
3938     create_pf("msitest\\furlong", TRUE);
3939     create_pf("msitest\\firkin", TRUE);
3940     create_pf("msitest\\fortnight", TRUE);
3941     create_pf("msitest\\becquerel", TRUE);
3942     create_pf("msitest\\dioptre", TRUE);
3943     create_pf("msitest\\attoparsec", TRUE);
3944     create_pf("msitest\\storeys", TRUE);
3945     create_pf("msitest\\block", TRUE);
3946     create_pf("msitest\\siriometer", TRUE);
3947
3948     r = MsiInstallProductA(msifile, NULL);
3949     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3950     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
3951     ok(!pf_exists("msitest\\helium"), "File installed\n");
3952     ok(pf_exists("msitest\\lithium"), "File not installed\n");
3953     ok(pf_exists("msitest\\becquerel"), "File not installed\n");
3954     ok(pf_exists("msitest\\dioptre"), "File not installed\n");
3955     ok(pf_exists("msitest\\attoparsec"), "File not installed\n");
3956     ok(pf_exists("msitest"), "File not installed\n");
3957     todo_wine
3958     {
3959         ok(!pf_exists("msitest\\firkin"), "File not deleted\n");
3960         ok(!pf_exists("msitest\\fortnight"), "File not deleted\n");
3961         ok(!pf_exists("msitest\\furlong"), "File not deleted\n");
3962         ok(!pf_exists("msitest\\storeys"), "File not deleted\n");
3963         ok(!pf_exists("msitest\\block"), "File not deleted\n");
3964         ok(!pf_exists("msitest\\siriometer"), "File not deleted\n");
3965     }
3966
3967     create_pf("msitest\\furlong", TRUE);
3968     create_pf("msitest\\firkin", TRUE);
3969     create_pf("msitest\\fortnight", TRUE);
3970     create_pf("msitest\\storeys", TRUE);
3971     create_pf("msitest\\block", TRUE);
3972     create_pf("msitest\\siriometer", TRUE);
3973
3974     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3975     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3976     ok(!delete_pf("msitest\\helium", TRUE), "File not deleted\n");
3977     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
3978     ok(delete_pf("msitest\\furlong", TRUE), "File deleted\n");
3979     ok(delete_pf("msitest\\firkin", TRUE), "File deleted\n");
3980     ok(delete_pf("msitest\\fortnight", TRUE), "File deleted\n");
3981     ok(delete_pf("msitest\\attoparsec", TRUE), "File deleted\n");
3982     ok(delete_pf("msitest\\siriometer", TRUE), "File deleted\n");
3983     todo_wine
3984     {
3985         ok(!delete_pf("msitest\\hydrogen", TRUE), "File not deleted\n");
3986         ok(!delete_pf("msitest\\becquerel", TRUE), "File not deleted\n");
3987         ok(!delete_pf("msitest\\dioptre", TRUE), "File not deleted\n");
3988         ok(!delete_pf("msitest\\storeys", TRUE), "File not deleted\n");
3989         ok(!delete_pf("msitest\\block", TRUE), "File not deleted\n");
3990     }
3991     ok(delete_pf("msitest", FALSE), "File deleted\n");
3992
3993     DeleteFile(msifile);
3994     DeleteFile("msitest\\hydrogen");
3995     DeleteFile("msitest\\helium");
3996     DeleteFile("msitest\\lithium");
3997     RemoveDirectory("msitest");
3998 }
3999
4000 static void test_movefiles(void)
4001 {
4002     UINT r;
4003     char props[MAX_PATH];
4004
4005     CreateDirectoryA("msitest", NULL);
4006     create_file("msitest\\augustus", 100);
4007     create_file("cameroon", 100);
4008     create_file("djibouti", 100);
4009     create_file("egypt", 100);
4010     create_file("finland", 100);
4011     create_file("gambai", 100);
4012     create_file("honduras", 100);
4013     create_file("msitest\\india", 100);
4014     create_file("japan", 100);
4015     create_file("kenya", 100);
4016     CreateDirectoryA("latvia", NULL);
4017     create_file("nauru", 100);
4018     create_file("apple", 100);
4019     create_file("application", 100);
4020     create_file("ape", 100);
4021     create_file("foo", 100);
4022     create_file("fao", 100);
4023     create_file("fbod", 100);
4024     create_file("budding", 100);
4025     create_file("buddy", 100);
4026     create_file("bud", 100);
4027     create_file("bar", 100);
4028     create_file("bur", 100);
4029     create_file("bird", 100);
4030
4031     create_database(msifile, mov_tables, sizeof(mov_tables) / sizeof(msi_table));
4032
4033     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
4034     MsiEnableLog(INSTALLLOGMODE_VERBOSE | INSTALLLOGMODE_EXTRADEBUG, "log.txt", 0);
4035
4036     /* if the source or dest property is not a full path,
4037      * windows tries to access it as a network resource
4038      */
4039
4040     sprintf(props, "SOURCEFULL=\"%s\\\" DESTFULL=\"%s\\msitest\" "
4041             "FILEPATHBAD=\"%s\\japan\" FILEPATHGOOD=\"%s\\kenya\"",
4042             CURR_DIR, PROG_FILES_DIR, CURR_DIR, CURR_DIR);
4043
4044     r = MsiInstallProductA(msifile, props);
4045     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4046     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4047     ok(!delete_pf("msitest\\dest", TRUE), "File copied\n");
4048     ok(delete_pf("msitest\\canada", TRUE), "File not copied\n");
4049     ok(delete_pf("msitest\\dominica", TRUE), "File not moved\n");
4050     ok(!delete_pf("msitest\\elsalvador", TRUE), "File moved\n");
4051     ok(!delete_pf("msitest\\france", TRUE), "File moved\n");
4052     ok(!delete_pf("msitest\\georgia", TRUE), "File moved\n");
4053     ok(delete_pf("msitest\\hungary", TRUE), "File not moved\n");
4054     ok(!delete_pf("msitest\\indonesia", TRUE), "File moved\n");
4055     ok(!delete_pf("msitest\\jordan", TRUE), "File moved\n");
4056     ok(delete_pf("msitest\\kiribati", TRUE), "File not moved\n");
4057     ok(!delete_pf("msitest\\lebanon", TRUE), "File moved\n");
4058     ok(!delete_pf("msitest\\lebanon", FALSE), "Directory moved\n");
4059     /* either apple or application will be moved depending on directory order */
4060     if (!delete_pf("msitest\\apple", TRUE))
4061         ok(delete_pf("msitest\\application", TRUE), "File not moved\n");
4062     else
4063         ok(!delete_pf("msitest\\application", TRUE), "File should not exist\n");
4064     ok(delete_pf("msitest\\wildcard", TRUE), "File not moved\n");
4065     ok(!delete_pf("msitest\\ape", TRUE), "File moved\n");
4066     /* either fao or foo will be moved depending on directory order */
4067     if (delete_pf("msitest\\foo", TRUE))
4068         ok(!delete_pf("msitest\\fao", TRUE), "File should not exist\n");
4069     else
4070         ok(delete_pf("msitest\\fao", TRUE), "File not moved\n");
4071     ok(delete_pf("msitest\\single", TRUE), "File not moved\n");
4072     ok(!delete_pf("msitest\\fbod", TRUE), "File moved\n");
4073     ok(delete_pf("msitest\\budding", TRUE), "File not moved\n");
4074     ok(delete_pf("msitest\\buddy", TRUE), "File not moved\n");
4075     ok(!delete_pf("msitest\\bud", TRUE), "File moved\n");
4076     ok(delete_pf("msitest\\bar", TRUE), "File not moved\n");
4077     ok(delete_pf("msitest\\bur", TRUE), "File not moved\n");
4078     ok(!delete_pf("msitest\\bird", TRUE), "File moved\n");
4079     ok(delete_pf("msitest", FALSE), "File not installed\n");
4080     ok(DeleteFileA("cameroon"), "File moved\n");
4081     ok(!DeleteFileA("djibouti"), "File not moved\n");
4082     ok(DeleteFileA("egypt"), "File moved\n");
4083     ok(DeleteFileA("finland"), "File moved\n");
4084     ok(DeleteFileA("gambai"), "File moved\n");
4085     ok(!DeleteFileA("honduras"), "File not moved\n");
4086     ok(DeleteFileA("msitest\\india"), "File moved\n");
4087     ok(DeleteFileA("japan"), "File moved\n");
4088     ok(!DeleteFileA("kenya"), "File not moved\n");
4089     ok(RemoveDirectoryA("latvia"), "Directory moved\n");
4090     ok(!DeleteFileA("nauru"), "File not moved\n");
4091     ok(!DeleteFileA("apple"), "File not moved\n");
4092     ok(!DeleteFileA("application"), "File not moved\n");
4093     ok(DeleteFileA("ape"), "File moved\n");
4094     ok(!DeleteFileA("foo"), "File not moved\n");
4095     ok(!DeleteFileA("fao"), "File not moved\n");
4096     ok(DeleteFileA("fbod"), "File moved\n");
4097     ok(!DeleteFileA("budding"), "File not moved\n");
4098     ok(!DeleteFileA("buddy"), "File not moved\n");
4099     ok(DeleteFileA("bud"), "File moved\n");
4100     ok(!DeleteFileA("bar"), "File not moved\n");
4101     ok(!DeleteFileA("bur"), "File not moved\n");
4102     ok(DeleteFileA("bird"), "File moved\n");
4103
4104     DeleteFile("msitest\\augustus");
4105     RemoveDirectory("msitest");
4106     DeleteFile(msifile);
4107 }
4108
4109 static void test_missingcab(void)
4110 {
4111     UINT r;
4112
4113     CreateDirectoryA("msitest", NULL);
4114     create_file("msitest\\augustus", 500);
4115     create_file("maximus", 500);
4116
4117     create_database(msifile, mc_tables, sizeof(mc_tables) / sizeof(msi_table));
4118
4119     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4120
4121     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
4122
4123     create_pf("msitest", FALSE);
4124     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
4125
4126     r = MsiInstallProductA(msifile, NULL);
4127     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4128     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4129     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
4130     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4131     ok(!delete_pf("msitest\\gaius", TRUE), "File installed\n");
4132     ok(delete_pf("msitest", FALSE), "File not installed\n");
4133
4134     create_pf("msitest", FALSE);
4135     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
4136     create_pf("msitest\\gaius", TRUE);
4137
4138     r = MsiInstallProductA(msifile, "GAIUS=1");
4139     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4140     todo_wine
4141     {
4142         ok(!delete_pf("msitest\\maximus", TRUE), "File installed\n");
4143         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4144     }
4145     ok(delete_pf("msitest\\caesar", TRUE), "File removed\n");
4146     ok(delete_pf("msitest\\gaius", TRUE), "File removed\n");
4147     ok(delete_pf("msitest", FALSE), "File not installed\n");
4148
4149     DeleteFile("msitest\\augustus");
4150     RemoveDirectory("msitest");
4151     DeleteFile("maximus");
4152     DeleteFile("test1.cab");
4153     DeleteFile(msifile);
4154 }
4155
4156 static void test_duplicatefiles(void)
4157 {
4158     UINT r;
4159
4160     CreateDirectoryA("msitest", NULL);
4161     create_file("msitest\\maximus", 500);
4162     create_database(msifile, df_tables, sizeof(df_tables) / sizeof(msi_table));
4163
4164     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4165
4166     /* fails if the destination folder is not a valid property */
4167
4168     r = MsiInstallProductA(msifile, NULL);
4169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4170     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4171     ok(delete_pf("msitest\\augustus", TRUE), "File not duplicated\n");
4172     ok(delete_pf("msitest\\this\\doesnot\\exist\\maximus", TRUE), "File not duplicated\n");
4173     ok(delete_pf("msitest\\this\\doesnot\\exist", FALSE), "File not duplicated\n");
4174     ok(delete_pf("msitest\\this\\doesnot", FALSE), "File not duplicated\n");
4175     ok(delete_pf("msitest\\this", FALSE), "File not duplicated\n");
4176     ok(delete_pf("msitest", FALSE), "File not installed\n");
4177
4178     DeleteFile("msitest\\maximus");
4179     RemoveDirectory("msitest");
4180     DeleteFile(msifile);
4181 }
4182
4183 static void test_writeregistryvalues(void)
4184 {
4185     UINT r;
4186     LONG res;
4187     HKEY hkey;
4188     DWORD type, size;
4189     CHAR path[MAX_PATH];
4190
4191     CreateDirectoryA("msitest", NULL);
4192     create_file("msitest\\augustus", 500);
4193
4194     create_database(msifile, wrv_tables, sizeof(wrv_tables) / sizeof(msi_table));
4195
4196     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4197
4198     r = MsiInstallProductA(msifile, NULL);
4199     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4200     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4201     ok(delete_pf("msitest", FALSE), "File installed\n");
4202
4203     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
4204     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4205
4206     size = MAX_PATH;
4207     type = REG_MULTI_SZ;
4208     memset(path, 'a', MAX_PATH);
4209     res = RegQueryValueExA(hkey, "Value", NULL, &type, (LPBYTE)path, &size);
4210     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4211     ok(!memcmp(path, "one\0two\0three\0\0", size), "Wrong multi-sz data\n");
4212     ok(size == 15, "Expected 15, got %d\n", size);
4213     ok(type == REG_MULTI_SZ, "Expected REG_MULTI_SZ, got %d\n", type);
4214
4215     DeleteFile(msifile);
4216     DeleteFile("msitest\\augustus");
4217     RemoveDirectory("msitest");
4218 }
4219
4220 static void test_sourcefolder(void)
4221 {
4222     UINT r;
4223
4224     CreateDirectoryA("msitest", NULL);
4225     create_file("augustus", 500);
4226
4227     create_database(msifile, sf_tables, sizeof(sf_tables) / sizeof(msi_table));
4228
4229     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4230
4231     r = MsiInstallProductA(msifile, NULL);
4232     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4233     todo_wine
4234     {
4235         ok(r == ERROR_INSTALL_FAILURE,
4236            "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4237         ok(!delete_pf("msitest", FALSE), "File installed\n");
4238     }
4239
4240     RemoveDirectoryA("msitest");
4241
4242     r = MsiInstallProductA(msifile, NULL);
4243     todo_wine
4244     {
4245         ok(r == ERROR_INSTALL_FAILURE,
4246            "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4247         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4248         ok(!delete_pf("msitest", FALSE), "File installed\n");
4249     }
4250
4251     DeleteFile(msifile);
4252     DeleteFile("augustus");
4253 }
4254
4255 static void test_customaction51(void)
4256 {
4257     UINT r;
4258
4259     CreateDirectoryA("msitest", NULL);
4260     create_file("msitest\\augustus", 500);
4261
4262     create_database(msifile, ca51_tables, sizeof(ca51_tables) / sizeof(msi_table));
4263
4264     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4265
4266     r = MsiInstallProductA(msifile, NULL);
4267     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4268     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4269     ok(delete_pf("msitest", FALSE), "File installed\n");
4270
4271     DeleteFile(msifile);
4272     DeleteFile("msitest\\augustus");
4273     RemoveDirectory("msitest");
4274 }
4275
4276 START_TEST(install)
4277 {
4278     DWORD len;
4279     char temp_path[MAX_PATH], prev_path[MAX_PATH];
4280
4281     init_functionpointers();
4282
4283     GetCurrentDirectoryA(MAX_PATH, prev_path);
4284     GetTempPath(MAX_PATH, temp_path);
4285     SetCurrentDirectoryA(temp_path);
4286
4287     lstrcpyA(CURR_DIR, temp_path);
4288     len = lstrlenA(CURR_DIR);
4289
4290     if(len && (CURR_DIR[len - 1] == '\\'))
4291         CURR_DIR[len - 1] = 0;
4292
4293     get_program_files_dir(PROG_FILES_DIR, COMMON_FILES_DIR);
4294
4295     test_MsiInstallProduct();
4296     test_MsiSetComponentState();
4297     test_packagecoltypes();
4298     test_continuouscabs();
4299     test_caborder();
4300     test_mixedmedia();
4301     test_samesequence();
4302     test_uiLevelFlags();
4303     test_readonlyfile();
4304     test_setdirproperty();
4305     test_cabisextracted();
4306     test_concurrentinstall();
4307     test_setpropertyfolder();
4308     test_publish_registerproduct();
4309     test_publish_publishproduct();
4310     test_publish_publishfeatures();
4311     test_publish_registeruser();
4312     test_publish_processcomponents();
4313     test_publish();
4314     test_publishsourcelist();
4315     test_transformprop();
4316     test_currentworkingdir();
4317     test_admin();
4318     test_adminprops();
4319     test_removefiles();
4320     test_movefiles();
4321     test_missingcab();
4322     test_duplicatefiles();
4323     test_writeregistryvalues();
4324     test_sourcefolder();
4325     test_customaction51();
4326
4327     SetCurrentDirectoryA(prev_path);
4328 }