user32/tests: Fix the listbox delete test on NT4.
[wine] / dlls / msi / tests / install.c
1 /*
2  * Copyright (C) 2006 James Hawkins
3  *
4  * A test program for installing MSI products.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define _WIN32_MSI 300
22 #define COBJMACROS
23
24 #include <stdio.h>
25
26 #include <windows.h>
27 #include <msiquery.h>
28 #include <msidefs.h>
29 #include <msi.h>
30 #include <fci.h>
31 #include <objidl.h>
32 #include <srrestoreptapi.h>
33
34 #include "wine/test.h"
35
36 static UINT (WINAPI *pMsiQueryComponentStateA)
37     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
38 static UINT (WINAPI *pMsiSourceListEnumSourcesA)
39     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPSTR, LPDWORD);
40 static UINT (WINAPI *pMsiSourceListGetInfoA)
41     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
42
43 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
44
45 static HMODULE hsrclient = 0;
46 static BOOL (WINAPI *pSRRemoveRestorePoint)(DWORD);
47 static BOOL (WINAPI *pSRSetRestorePointA)(RESTOREPOINTINFOA*, STATEMGRSTATUS*);
48
49 static BOOL on_win9x = FALSE;
50
51 static const char *msifile = "msitest.msi";
52 static const char *msifile2 = "winetest2.msi";
53 static const char *mstfile = "winetest.mst";
54 static CHAR CURR_DIR[MAX_PATH];
55 static CHAR PROG_FILES_DIR[MAX_PATH];
56 static CHAR COMMON_FILES_DIR[MAX_PATH];
57
58 /* msi database data */
59
60 static const CHAR component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
61                                     "s72\tS38\ts72\ti2\tS255\tS72\n"
62                                     "Component\tComponent\n"
63                                     "Five\t{8CC92E9D-14B2-4CA4-B2AA-B11D02078087}\tNEWDIR\t2\t\tfive.txt\n"
64                                     "Four\t{FD37B4EA-7209-45C0-8917-535F35A2F080}\tCABOUTDIR\t2\t\tfour.txt\n"
65                                     "One\t{783B242E-E185-4A56-AF86-C09815EC053C}\tMSITESTDIR\t2\t\tone.txt\n"
66                                     "Three\t{010B6ADD-B27D-4EDD-9B3D-34C4F7D61684}\tCHANGEDDIR\t2\t\tthree.txt\n"
67                                     "Two\t{BF03D1A6-20DA-4A65-82F3-6CAC995915CE}\tFIRSTDIR\t2\t\ttwo.txt\n"
68                                     "dangler\t{6091DF25-EF96-45F1-B8E9-A9B1420C7A3C}\tTARGETDIR\t4\t\tregdata\n"
69                                     "component\t\tMSITESTDIR\t0\t1\tfile\n"
70                                     "service_comp\t\tMSITESTDIR\t0\t1\tservice_file";
71
72 static const CHAR directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
73                                     "s72\tS72\tl255\n"
74                                     "Directory\tDirectory\n"
75                                     "CABOUTDIR\tMSITESTDIR\tcabout\n"
76                                     "CHANGEDDIR\tMSITESTDIR\tchanged:second\n"
77                                     "FIRSTDIR\tMSITESTDIR\tfirst\n"
78                                     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
79                                     "NEWDIR\tCABOUTDIR\tnew\n"
80                                     "ProgramFilesFolder\tTARGETDIR\t.\n"
81                                     "TARGETDIR\t\tSourceDir";
82
83 static const CHAR feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
84                                   "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
85                                   "Feature\tFeature\n"
86                                   "Five\t\tFive\tThe Five Feature\t5\t3\tNEWDIR\t0\n"
87                                   "Four\t\tFour\tThe Four Feature\t4\t3\tCABOUTDIR\t0\n"
88                                   "One\t\tOne\tThe One Feature\t1\t3\tMSITESTDIR\t0\n"
89                                   "Three\t\tThree\tThe Three Feature\t3\t3\tCHANGEDDIR\t0\n"
90                                   "Two\t\tTwo\tThe Two Feature\t2\t3\tFIRSTDIR\t0\n"
91                                   "feature\t\t\t\t2\t1\tTARGETDIR\t0\n"
92                                   "service_feature\t\t\t\t2\t1\tTARGETDIR\t0";
93
94 static const CHAR feature_comp_dat[] = "Feature_\tComponent_\n"
95                                        "s38\ts72\n"
96                                        "FeatureComponents\tFeature_\tComponent_\n"
97                                        "Five\tFive\n"
98                                        "Four\tFour\n"
99                                        "One\tOne\n"
100                                        "Three\tThree\n"
101                                        "Two\tTwo\n"
102                                        "feature\tcomponent\n"
103                                        "service_feature\tservice_comp\n";
104
105 static const CHAR file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
106                                "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
107                                "File\tFile\n"
108                                "five.txt\tFive\tfive.txt\t1000\t\t\t16384\t5\n"
109                                "four.txt\tFour\tfour.txt\t1000\t\t\t16384\t4\n"
110                                "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n"
111                                "three.txt\tThree\tthree.txt\t1000\t\t\t0\t3\n"
112                                "two.txt\tTwo\ttwo.txt\t1000\t\t\t0\t2\n"
113                                "file\tcomponent\tfilename\t100\t\t\t8192\t1\n"
114                                "service_file\tservice_comp\tservice.exe\t100\t\t\t8192\t1";
115
116 static const CHAR install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
117                                            "s72\tS255\tI2\n"
118                                            "InstallExecuteSequence\tAction\n"
119                                            "AllocateRegistrySpace\tNOT Installed\t1550\n"
120                                            "CostFinalize\t\t1000\n"
121                                            "CostInitialize\t\t800\n"
122                                            "FileCost\t\t900\n"
123                                            "ResolveSource\t\t950\n"
124                                            "MoveFiles\t\t1700\n"
125                                            "InstallFiles\t\t4000\n"
126                                            "DuplicateFiles\t\t4500\n"
127                                            "InstallServices\t\t5000\n"
128                                            "InstallFinalize\t\t6600\n"
129                                            "InstallInitialize\t\t1500\n"
130                                            "InstallValidate\t\t1400\n"
131                                            "LaunchConditions\t\t100\n"
132                                            "WriteRegistryValues\tSourceDir And SOURCEDIR\t5000";
133
134 static const CHAR media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
135                                 "i2\ti4\tL64\tS255\tS32\tS72\n"
136                                 "Media\tDiskId\n"
137                                 "1\t3\t\t\tDISK1\t\n"
138                                 "2\t5\t\tmsitest.cab\tDISK2\t\n";
139
140 static const CHAR property_dat[] = "Property\tValue\n"
141                                    "s72\tl0\n"
142                                    "Property\tProperty\n"
143                                    "DefaultUIFont\tDlgFont8\n"
144                                    "HASUIRUN\t0\n"
145                                    "INSTALLLEVEL\t3\n"
146                                    "InstallMode\tTypical\n"
147                                    "Manufacturer\tWine\n"
148                                    "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
149                                    "ProductCode\t{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}\n"
150                                    "ProductID\tnone\n"
151                                    "ProductLanguage\t1033\n"
152                                    "ProductName\tMSITEST\n"
153                                    "ProductVersion\t1.1.1\n"
154                                    "PROMPTROLLBACKCOST\tP\n"
155                                    "Setup\tSetup\n"
156                                    "UpgradeCode\t{4C0EAA15-0264-4E5A-8758-609EF142B92D}\n"
157                                    "AdminProperties\tPOSTADMIN\n"
158                                    "ROOTDRIVE\tC:\\\n"
159                                    "SERVNAME\tTestService\n"
160                                    "SERVDISP\tTestServiceDisp\n";
161
162 static const CHAR registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
163                                    "s72\ti2\tl255\tL255\tL0\ts72\n"
164                                    "Registry\tRegistry\n"
165                                    "Apples\t2\tSOFTWARE\\Wine\\msitest\tName\timaname\tOne\n"
166                                    "Oranges\t2\tSOFTWARE\\Wine\\msitest\tnumber\t#314\tTwo\n"
167                                    "regdata\t2\tSOFTWARE\\Wine\\msitest\tblah\tbad\tdangler\n"
168                                    "OrderTest\t2\tSOFTWARE\\Wine\\msitest\tOrderTestName\tOrderTestValue\tcomponent";
169
170 static const CHAR service_install_dat[] = "ServiceInstall\tName\tDisplayName\tServiceType\tStartType\tErrorControl\t"
171                                           "LoadOrderGroup\tDependencies\tStartName\tPassword\tArguments\tComponent_\tDescription\n"
172                                           "s72\ts255\tL255\ti4\ti4\ti4\tS255\tS255\tS255\tS255\tS255\ts72\tL255\n"
173                                           "ServiceInstall\tServiceInstall\n"
174                                           "TestService\t[SERVNAME]\t[SERVDISP]\t2\t3\t0\t\t\tTestService\t\t\tservice_comp\t\t";
175
176 static const CHAR service_control_dat[] = "ServiceControl\tName\tEvent\tArguments\tWait\tComponent_\n"
177                                           "s72\tl255\ti2\tL255\tI2\ts72\n"
178                                           "ServiceControl\tServiceControl\n"
179                                           "ServiceControl\tTestService\t8\t\t0\tservice_comp";
180
181 /* tables for test_continuouscabs */
182 static const CHAR cc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
183                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
184                                        "Component\tComponent\n"
185                                        "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
186                                        "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
187                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
188
189 static const CHAR cc2_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
190                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
191                                         "Component\tComponent\n"
192                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
193                                         "augustus\t\tMSITESTDIR\t0\t0\taugustus\n"
194                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
195
196 static const CHAR cc_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
197                                      "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
198                                      "Feature\tFeature\n"
199                                      "feature\t\t\t\t2\t1\tTARGETDIR\t0";
200
201 static const CHAR cc_feature_comp_dat[] = "Feature_\tComponent_\n"
202                                           "s38\ts72\n"
203                                           "FeatureComponents\tFeature_\tComponent_\n"
204                                           "feature\tmaximus\n"
205                                           "feature\taugustus\n"
206                                           "feature\tcaesar";
207
208 static const CHAR cc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
209                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
210                                   "File\tFile\n"
211                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
212                                   "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
213                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12";
214
215 static const CHAR cc2_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
216                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
217                                    "File\tFile\n"
218                                    "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
219                                    "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
220                                    "tiberius\tmaximus\ttiberius\t500\t\t\t16384\t3\n"
221                                    "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12";
222
223 static const CHAR cc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
224                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
225                                    "Media\tDiskId\n"
226                                    "1\t10\t\ttest1.cab\tDISK1\t\n"
227                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
228                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
229
230 static const CHAR co_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
231                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
232                                   "File\tFile\n"
233                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
234                                   "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
235                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
236
237 static const CHAR co_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
238                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
239                                    "Media\tDiskId\n"
240                                    "1\t10\t\ttest1.cab\tDISK1\t\n"
241                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
242                                    "3\t3\t\ttest3.cab\tDISK3\t\n";
243
244 static const CHAR co2_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
245                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
246                                     "Media\tDiskId\n"
247                                     "1\t10\t\ttest1.cab\tDISK1\t\n"
248                                     "2\t12\t\ttest3.cab\tDISK3\t\n"
249                                     "3\t2\t\ttest2.cab\tDISK2\t\n";
250
251 static const CHAR mm_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
252                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
253                                   "File\tFile\n"
254                                   "maximus\tmaximus\tmaximus\t500\t\t\t512\t1\n"
255                                   "augustus\taugustus\taugustus\t500\t\t\t512\t2\n"
256                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
257
258 static const CHAR mm_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
259                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
260                                    "Media\tDiskId\n"
261                                    "1\t3\t\ttest1.cab\tDISK1\t\n";
262
263 static const CHAR ss_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
264                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
265                                    "Media\tDiskId\n"
266                                    "1\t2\t\ttest1.cab\tDISK1\t\n"
267                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
268                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
269
270 /* tables for test_uiLevelFlags */
271 static const CHAR ui_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
272                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
273                                        "Component\tComponent\n"
274                                        "maximus\t\tMSITESTDIR\t0\tHASUIRUN=1\tmaximus\n"
275                                        "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
276                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
277
278 static const CHAR ui_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
279                                            "s72\tS255\tI2\n"
280                                            "InstallUISequence\tAction\n"
281                                            "SetUIProperty\t\t5\n"
282                                            "ExecuteAction\t\t1100\n";
283
284 static const CHAR ui_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
285                                            "s72\ti2\tS64\tS0\tS255\n"
286                                            "CustomAction\tAction\n"
287                                            "SetUIProperty\t51\tHASUIRUN\t1\t\n";
288
289 static const CHAR rof_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
290                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
291                                         "Component\tComponent\n"
292                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n";
293
294 static const CHAR rof_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
295                                       "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
296                                       "Feature\tFeature\n"
297                                       "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
298                                       "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
299
300 static const CHAR rof_feature_comp_dat[] = "Feature_\tComponent_\n"
301                                            "s38\ts72\n"
302                                            "FeatureComponents\tFeature_\tComponent_\n"
303                                            "feature\tmaximus\n"
304                                            "montecristo\tmaximus";
305
306 static const CHAR rof_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
307                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
308                                    "File\tFile\n"
309                                    "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
310
311 static const CHAR rof_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
312                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
313                                     "Media\tDiskId\n"
314                                     "1\t1\t\t\tDISK1\t\n";
315
316 static const CHAR sdp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
317                                                "s72\tS255\tI2\n"
318                                                "InstallExecuteSequence\tAction\n"
319                                                "AllocateRegistrySpace\tNOT Installed\t1550\n"
320                                                "CostFinalize\t\t1000\n"
321                                                "CostInitialize\t\t800\n"
322                                                "FileCost\t\t900\n"
323                                                "InstallFiles\t\t4000\n"
324                                                "InstallFinalize\t\t6600\n"
325                                                "InstallInitialize\t\t1500\n"
326                                                "InstallValidate\t\t1400\n"
327                                                "LaunchConditions\t\t100\n"
328                                                "SetDirProperty\t\t950";
329
330 static const CHAR sdp_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
331                                             "s72\ti2\tS64\tS0\tS255\n"
332                                             "CustomAction\tAction\n"
333                                             "SetDirProperty\t51\tMSITESTDIR\t[CommonFilesFolder]msitest\\\t\n";
334
335 static const CHAR cie_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
336                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
337                                         "Component\tComponent\n"
338                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
339                                         "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
340                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n"
341                                         "gaius\t\tMSITESTDIR\t0\t1\tgaius\n";
342
343 static const CHAR cie_feature_comp_dat[] = "Feature_\tComponent_\n"
344                                            "s38\ts72\n"
345                                            "FeatureComponents\tFeature_\tComponent_\n"
346                                            "feature\tmaximus\n"
347                                            "feature\taugustus\n"
348                                            "feature\tcaesar\n"
349                                            "feature\tgaius";
350
351 static const CHAR cie_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
352                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
353                                    "File\tFile\n"
354                                    "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
355                                    "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
356                                    "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12\n"
357                                    "gaius\tgaius\tgaius\t500\t\t\t8192\t11";
358
359 static const CHAR cie_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
360                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
361                                     "Media\tDiskId\n"
362                                     "1\t1\t\ttest1.cab\tDISK1\t\n"
363                                     "2\t2\t\ttest2.cab\tDISK2\t\n"
364                                     "3\t12\t\ttest3.cab\tDISK3\t\n";
365
366 static const CHAR ci_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
367                                               "s72\tS255\tI2\n"
368                                               "InstallExecuteSequence\tAction\n"
369                                               "CostFinalize\t\t1000\n"
370                                               "CostInitialize\t\t800\n"
371                                               "FileCost\t\t900\n"
372                                               "InstallFiles\t\t4000\n"
373                                               "InstallServices\t\t5000\n"
374                                               "InstallFinalize\t\t6600\n"
375                                               "InstallInitialize\t\t1500\n"
376                                               "RunInstall\t\t1600\n"
377                                               "InstallValidate\t\t1400\n"
378                                               "LaunchConditions\t\t100";
379
380 static const CHAR ci_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
381                                             "s72\ti2\tS64\tS0\tS255\n"
382                                             "CustomAction\tAction\n"
383                                             "RunInstall\t87\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
384
385 static const CHAR ci_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
386                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
387                                        "Component\tComponent\n"
388                                        "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
389
390 static const CHAR ci2_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
391                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
392                                         "Component\tComponent\n"
393                                         "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
394
395 static const CHAR ci2_feature_comp_dat[] = "Feature_\tComponent_\n"
396                                            "s38\ts72\n"
397                                            "FeatureComponents\tFeature_\tComponent_\n"
398                                            "feature\taugustus";
399
400 static const CHAR ci2_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
401                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
402                                    "File\tFile\n"
403                                    "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
404
405 static const CHAR spf_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
406                                             "s72\ti2\tS64\tS0\tS255\n"
407                                             "CustomAction\tAction\n"
408                                             "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n";
409
410 static const CHAR spf_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
411                                                "s72\tS255\tI2\n"
412                                                "InstallExecuteSequence\tAction\n"
413                                                "CostFinalize\t\t1000\n"
414                                                "CostInitialize\t\t800\n"
415                                                "FileCost\t\t900\n"
416                                                "SetFolderProp\t\t950\n"
417                                                "InstallFiles\t\t4000\n"
418                                                "InstallServices\t\t5000\n"
419                                                "InstallFinalize\t\t6600\n"
420                                                "InstallInitialize\t\t1500\n"
421                                                "InstallValidate\t\t1400\n"
422                                                "LaunchConditions\t\t100";
423
424 static const CHAR spf_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
425                                              "s72\tS255\tI2\n"
426                                              "InstallUISequence\tAction\n"
427                                              "CostInitialize\t\t800\n"
428                                              "FileCost\t\t900\n"
429                                              "CostFinalize\t\t1000\n"
430                                              "ExecuteAction\t\t1100\n";
431
432 static const CHAR pp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
433                                               "s72\tS255\tI2\n"
434                                               "InstallExecuteSequence\tAction\n"
435                                               "ValidateProductID\t\t700\n"
436                                               "CostInitialize\t\t800\n"
437                                               "FileCost\t\t900\n"
438                                               "CostFinalize\t\t1000\n"
439                                               "InstallValidate\t\t1400\n"
440                                               "InstallInitialize\t\t1500\n"
441                                               "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
442                                               "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
443                                               "RemoveFiles\t\t3500\n"
444                                               "InstallFiles\t\t4000\n"
445                                               "RegisterUser\tREGISTER_USER=1 Or FULL=1\t6000\n"
446                                               "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
447                                               "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
448                                               "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
449                                               "InstallFinalize\t\t6600";
450
451 static const CHAR ppc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
452                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
453                                         "Component\tComponent\n"
454                                         "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n"
455                                         "augustus\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t1\t\taugustus\n";
456
457 static const CHAR ppc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
458                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
459                                    "File\tFile\n"
460                                    "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1\n"
461                                    "augustus\taugustus\taugustus\t500\t\t\t8192\t2";
462
463 static const CHAR ppc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
464                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
465                                     "Media\tDiskId\n"
466                                     "1\t2\t\t\tDISK1\t\n";
467
468 static const CHAR ppc_feature_comp_dat[] = "Feature_\tComponent_\n"
469                                            "s38\ts72\n"
470                                            "FeatureComponents\tFeature_\tComponent_\n"
471                                            "feature\tmaximus\n"
472                                            "feature\taugustus\n"
473                                            "montecristo\tmaximus";
474
475 static const CHAR tp_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\tprop=\"val\"\taugustus\n";
479
480 static const CHAR cwd_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
481                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
482                                         "Component\tComponent\n"
483                                         "augustus\t\tMSITESTDIR\t0\t\taugustus\n";
484
485 static const CHAR adm_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
486                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
487                                         "Component\tComponent\n"
488                                         "augustus\t\tMSITESTDIR\t0\tPOSTADMIN=1\taugustus";
489
490 static const CHAR adm_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
491                                             "s72\ti2\tS64\tS0\tS255\n"
492                                             "CustomAction\tAction\n"
493                                             "SetPOSTADMIN\t51\tPOSTADMIN\t1\t\n";
494
495 static const CHAR adm_admin_exec_seq_dat[] = "Action\tCondition\tSequence\n"
496                                              "s72\tS255\tI2\n"
497                                              "AdminExecuteSequence\tAction\n"
498                                              "CostFinalize\t\t1000\n"
499                                              "CostInitialize\t\t800\n"
500                                              "FileCost\t\t900\n"
501                                              "SetPOSTADMIN\t\t950\n"
502                                              "InstallFiles\t\t4000\n"
503                                              "InstallFinalize\t\t6600\n"
504                                              "InstallInitialize\t\t1500\n"
505                                              "InstallValidate\t\t1400\n"
506                                              "LaunchConditions\t\t100";
507
508 static const CHAR amp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
509                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
510                                         "Component\tComponent\n"
511                                         "augustus\t\tMSITESTDIR\t0\tMYPROP=2718 and MyProp=42\taugustus\n";
512
513 static const CHAR rem_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
514                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
515                                         "Component\tComponent\n"
516                                         "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t0\t\thydrogen\n"
517                                         "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t1\t\thelium\n"
518                                         "lithium\t\tMSITESTDIR\t2\t\tlithium\n";
519
520 static const CHAR rem_feature_comp_dat[] = "Feature_\tComponent_\n"
521                                            "s38\ts72\n"
522                                            "FeatureComponents\tFeature_\tComponent_\n"
523                                            "feature\thydrogen\n"
524                                            "feature\thelium\n"
525                                            "feature\tlithium";
526
527 static const CHAR rem_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
528                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
529                                    "File\tFile\n"
530                                    "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
531                                    "helium\thelium\thelium\t0\t\t\t8192\t1\n"
532                                    "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
533
534 static const CHAR rem_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
535                                                "s72\tS255\tI2\n"
536                                                "InstallExecuteSequence\tAction\n"
537                                                "ValidateProductID\t\t700\n"
538                                                "CostInitialize\t\t800\n"
539                                                "FileCost\t\t900\n"
540                                                "CostFinalize\t\t1000\n"
541                                                "InstallValidate\t\t1400\n"
542                                                "InstallInitialize\t\t1500\n"
543                                                "ProcessComponents\t\t1600\n"
544                                                "UnpublishFeatures\t\t1800\n"
545                                                "RemoveFiles\t\t3500\n"
546                                                "InstallFiles\t\t4000\n"
547                                                "RegisterProduct\t\t6100\n"
548                                                "PublishFeatures\t\t6300\n"
549                                                "PublishProduct\t\t6400\n"
550                                                "InstallFinalize\t\t6600";
551
552 static const CHAR rem_remove_files_dat[] = "FileKey\tComponent_\tFileName\tDirProperty\tInstallMode\n"
553                                            "s72\ts72\tS255\ts72\tI2\n"
554                                            "RemoveFile\tFileKey\n"
555                                            "furlong\thydrogen\tfurlong\tMSITESTDIR\t1\n"
556                                            "firkin\thelium\tfirkin\tMSITESTDIR\t1\n"
557                                            "fortnight\tlithium\tfortnight\tMSITESTDIR\t1\n"
558                                            "becquerel\thydrogen\tbecquerel\tMSITESTDIR\t2\n"
559                                            "dioptre\thelium\tdioptre\tMSITESTDIR\t2\n"
560                                            "attoparsec\tlithium\tattoparsec\tMSITESTDIR\t2\n"
561                                            "storeys\thydrogen\tstoreys\tMSITESTDIR\t3\n"
562                                            "block\thelium\tblock\tMSITESTDIR\t3\n"
563                                            "siriometer\tlithium\tsiriometer\tMSITESTDIR\t3\n"
564                                            "nanoacre\thydrogen\t\tCABOUTDIR\t3\n";
565
566 static const CHAR mov_move_file_dat[] = "FileKey\tComponent_\tSourceName\tDestName\tSourceFolder\tDestFolder\tOptions\n"
567                                         "s72\ts72\tS255\tS255\tS72\ts72\ti2\n"
568                                         "MoveFile\tFileKey\n"
569                                         "abkhazia\taugustus\tnonexistent\tdest\tSourceDir\tMSITESTDIR\t0\n"
570                                         "bahamas\taugustus\tnonexistent\tdest\tSourceDir\tMSITESTDIR\t1\n"
571                                         "cambodia\taugustus\tcameroon\tcanada\tSourceDir\tMSITESTDIR\t0\n"
572                                         "denmark\taugustus\tdjibouti\tdominica\tSourceDir\tMSITESTDIR\t1\n"
573                                         "ecuador\taugustus\tegypt\telsalvador\tNotAProp\tMSITESTDIR\t1\n"
574                                         "fiji\taugustus\tfinland\tfrance\tSourceDir\tNotAProp\t1\n"
575                                         "gabon\taugustus\tgambia\tgeorgia\tSOURCEFULL\tMSITESTDIR\t1\n"
576                                         "haiti\taugustus\thonduras\thungary\tSourceDir\tDESTFULL\t1\n"
577                                         "iceland\taugustus\tindia\tindonesia\tMSITESTDIR\tMSITESTDIR\t1\n"
578                                         "jamaica\taugustus\tjapan\tjordan\tFILEPATHBAD\tMSITESTDIR\t1\n"
579                                         "kazakhstan\taugustus\t\tkiribati\tFILEPATHGOOD\tMSITESTDIR\t1\n"
580                                         "laos\taugustus\tlatvia\tlebanon\tSourceDir\tMSITESTDIR\t1\n"
581                                         "namibia\taugustus\tnauru\tkiribati\tSourceDir\tMSITESTDIR\t1\n"
582                                         "pakistan\taugustus\tperu\tsfn|poland\tSourceDir\tMSITESTDIR\t1\n"
583                                         "wildcard\taugustus\tapp*\twildcard\tSourceDir\tMSITESTDIR\t1\n"
584                                         "single\taugustus\tf?o\tsingle\tSourceDir\tMSITESTDIR\t1\n"
585                                         "wildcardnodest\taugustus\tbudd*\t\tSourceDir\tMSITESTDIR\t1\n"
586                                         "singlenodest\taugustus\tb?r\t\tSourceDir\tMSITESTDIR\t1\n";
587
588 static const CHAR mc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
589                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
590                                         "Component\tComponent\n"
591                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
592                                         "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
593                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n"
594                                         "gaius\t\tMSITESTDIR\t0\tGAIUS=1\tgaius\n";
595
596 static const CHAR mc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
597                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
598                                   "File\tFile\n"
599                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
600                                   "augustus\taugustus\taugustus\t500\t\t\t0\t2\n"
601                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3\n"
602                                   "gaius\tgaius\tgaius\t500\t\t\t16384\t4";
603
604 static const CHAR mc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
605                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
606                                    "Media\tDiskId\n"
607                                    "1\t1\t\ttest1.cab\tDISK1\t\n"
608                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
609                                    "3\t3\t\ttest3.cab\tDISK3\t\n"
610                                    "4\t4\t\ttest3.cab\tDISK3\t\n";
611
612 static const CHAR mc_file_hash_dat[] = "File_\tOptions\tHashPart1\tHashPart2\tHashPart3\tHashPart4\n"
613                                        "s72\ti2\ti4\ti4\ti4\ti4\n"
614                                        "MsiFileHash\tFile_\n"
615                                        "caesar\t0\t850433704\t-241429251\t675791761\t-1221108824";
616
617 static const CHAR df_directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
618                                        "s72\tS72\tl255\n"
619                                        "Directory\tDirectory\n"
620                                        "THIS\tMSITESTDIR\tthis\n"
621                                        "DOESNOT\tTHIS\tdoesnot\n"
622                                        "NONEXISTENT\tDOESNOT\texist\n"
623                                        "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
624                                        "ProgramFilesFolder\tTARGETDIR\t.\n"
625                                        "TARGETDIR\t\tSourceDir";
626
627 static const CHAR df_duplicate_file_dat[] = "FileKey\tComponent_\tFile_\tDestName\tDestFolder\n"
628                                             "s72\ts72\ts72\tS255\tS72\n"
629                                             "DuplicateFile\tFileKey\n"
630                                             "maximus\tmaximus\tmaximus\taugustus\t\n"
631                                             "caesar\tmaximus\tmaximus\t\tNONEXISTENT\n";
632
633 static const CHAR wrv_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
634                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
635                                         "Component\tComponent\n"
636                                         "augustus\t\tMSITESTDIR\t0\t\taugustus\n";
637
638 static const CHAR wrv_registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
639                                        "s72\ti2\tl255\tL255\tL0\ts72\n"
640                                        "Registry\tRegistry\n"
641                                        "regdata\t2\tSOFTWARE\\Wine\\msitest\tValue\t[~]one[~]two[~]three\taugustus";
642
643 static const CHAR ca51_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
644                                          "s72\tS38\ts72\ti2\tS255\tS72\n"
645                                          "Component\tComponent\n"
646                                          "augustus\t\tMSITESTDIR\t0\tMYPROP=42\taugustus\n";
647
648 static const CHAR ca51_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
649                                                 "s72\tS255\tI2\n"
650                                                 "InstallExecuteSequence\tAction\n"
651                                                 "ValidateProductID\t\t700\n"
652                                                 "GoodSetProperty\t\t725\n"
653                                                 "BadSetProperty\t\t750\n"
654                                                 "CostInitialize\t\t800\n"
655                                                 "ResolveSource\t\t810\n"
656                                                 "FileCost\t\t900\n"
657                                                 "SetSourceDir\tSRCDIR\t910\n"
658                                                 "CostFinalize\t\t1000\n"
659                                                 "InstallValidate\t\t1400\n"
660                                                 "InstallInitialize\t\t1500\n"
661                                                 "InstallFiles\t\t4000\n"
662                                                 "InstallFinalize\t\t6600";
663
664 static const CHAR ca51_custom_action_dat[] = "Action\tType\tSource\tTarget\n"
665                                              "s72\ti2\tS64\tS0\n"
666                                              "CustomAction\tAction\n"
667                                              "GoodSetProperty\t51\tMYPROP\t42\n"
668                                              "BadSetProperty\t51\t\tMYPROP\n"
669                                              "SetSourceDir\t51\tSourceDir\t[SRCDIR]\n";
670
671 static const CHAR is_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
672                                      "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
673                                      "Feature\tFeature\n"
674                                      "one\t\t\t\t2\t1\t\t0\n" /* favorLocal */
675                                      "two\t\t\t\t2\t1\t\t1\n" /* favorSource */
676                                      "three\t\t\t\t2\t1\t\t4\n" /* favorAdvertise */
677                                      "four\t\t\t\t2\t0\t\t0"; /* disabled */
678
679 static const CHAR is_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
680                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
681                                        "Component\tComponent\n"
682                                        "alpha\t\tMSITESTDIR\t0\t\talpha_file\n" /* favorLocal:Local */
683                                        "beta\t\tMSITESTDIR\t1\t\tbeta_file\n" /* favorLocal:Source */
684                                        "gamma\t\tMSITESTDIR\t2\t\tgamma_file\n" /* favorLocal:Optional */
685                                        "theta\t\tMSITESTDIR\t0\t\ttheta_file\n" /* favorSource:Local */
686                                        "delta\t\tMSITESTDIR\t1\t\tdelta_file\n" /* favorSource:Source */
687                                        "epsilon\t\tMSITESTDIR\t2\t\tepsilon_file\n" /* favorSource:Optional */
688                                        "zeta\t\tMSITESTDIR\t0\t\tzeta_file\n" /* favorAdvertise:Local */
689                                        "iota\t\tMSITESTDIR\t1\t\tiota_file\n" /* favorAdvertise:Source */
690                                        "eta\t\tMSITESTDIR\t2\t\teta_file\n" /* favorAdvertise:Optional */
691                                        "kappa\t\tMSITESTDIR\t0\t\tkappa_file\n" /* disabled:Local */
692                                        "lambda\t\tMSITESTDIR\t1\t\tlambda_file\n" /* disabled:Source */
693                                        "mu\t\tMSITESTDIR\t2\t\tmu_file\n"; /* disabled:Optional */
694
695 static const CHAR is_feature_comp_dat[] = "Feature_\tComponent_\n"
696                                           "s38\ts72\n"
697                                           "FeatureComponents\tFeature_\tComponent_\n"
698                                           "one\talpha\n"
699                                           "one\tbeta\n"
700                                           "one\tgamma\n"
701                                           "two\ttheta\n"
702                                           "two\tdelta\n"
703                                           "two\tepsilon\n"
704                                           "three\tzeta\n"
705                                           "three\tiota\n"
706                                           "three\teta\n"
707                                           "four\tkappa\n"
708                                           "four\tlambda\n"
709                                           "four\tmu";
710
711 static const CHAR is_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
712                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
713                                   "File\tFile\n"
714                                   "alpha_file\talpha\talpha\t500\t\t\t8192\t1\n"
715                                   "beta_file\tbeta\tbeta\t500\t\t\t8291\t2\n"
716                                   "gamma_file\tgamma\tgamma\t500\t\t\t8192\t3\n"
717                                   "theta_file\ttheta\ttheta\t500\t\t\t8192\t4\n"
718                                   "delta_file\tdelta\tdelta\t500\t\t\t8192\t5\n"
719                                   "epsilon_file\tepsilon\tepsilon\t500\t\t\t8192\t6\n"
720                                   "zeta_file\tzeta\tzeta\t500\t\t\t8192\t7\n"
721                                   "iota_file\tiota\tiota\t500\t\t\t8192\t8\n"
722                                   "eta_file\teta\teta\t500\t\t\t8192\t9\n"
723                                   "kappa_file\tkappa\tkappa\t500\t\t\t8192\t10\n"
724                                   "lambda_file\tlambda\tlambda\t500\t\t\t8192\t11\n"
725                                   "mu_file\tmu\tmu\t500\t\t\t8192\t12";
726
727 static const CHAR is_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
728                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
729                                    "Media\tDiskId\n"
730                                    "1\t12\t\t\tDISK1\t\n";
731
732 static const CHAR sp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
733                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
734                                         "Component\tComponent\n"
735                                         "augustus\t\tTWODIR\t0\t\taugustus\n";
736
737 static const CHAR sp_directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
738                                        "s72\tS72\tl255\n"
739                                        "Directory\tDirectory\n"
740                                        "TARGETDIR\t\tSourceDir\n"
741                                        "ProgramFilesFolder\tTARGETDIR\t.\n"
742                                        "MSITESTDIR\tProgramFilesFolder\tmsitest:.\n"
743                                        "ONEDIR\tMSITESTDIR\t.:shortone|longone\n"
744                                        "TWODIR\tONEDIR\t.:shorttwo|longtwo";
745
746 static const CHAR mcp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
747                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
748                                         "Component\tComponent\n"
749                                         "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t2\t\thydrogen\n"
750                                         "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t2\t\thelium\n"
751                                         "lithium\t{4AF28FFC-71C7-4307-BDE4-B77C5338F56F}\tMSITESTDIR\t2\tPROPVAR=42\tlithium\n";
752
753 static const CHAR mcp_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
754                                       "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
755                                       "Feature\tFeature\n"
756                                       "hydroxyl\t\thydroxyl\thydroxyl\t2\t1\tTARGETDIR\t0\n"
757                                       "heliox\t\theliox\theliox\t2\t5\tTARGETDIR\t0\n"
758                                       "lithia\t\tlithia\tlithia\t2\t10\tTARGETDIR\t0";
759
760 static const CHAR mcp_feature_comp_dat[] = "Feature_\tComponent_\n"
761                                            "s38\ts72\n"
762                                            "FeatureComponents\tFeature_\tComponent_\n"
763                                            "hydroxyl\thydrogen\n"
764                                            "heliox\thelium\n"
765                                            "lithia\tlithium";
766
767 static const CHAR mcomp_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
768                                      "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
769                                      "File\tFile\n"
770                                      "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
771                                      "helium\thelium\thelium\t0\t\t\t8192\t1\n"
772                                      "lithium\tlithium\tlithium\t0\t\t\t8192\t1\n"
773                                      "beryllium\tmissingcomp\tberyllium\t0\t\t\t8192\t1";
774
775 static const CHAR ai_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
776                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
777                                   "File\tFile\n"
778                                   "five.txt\tFive\tfive.txt\t1000\t\t\t16384\t5\n"
779                                   "four.txt\tFour\tfour.txt\t1000\t\t\t16384\t4\n"
780                                   "one.txt\tOne\tone.txt\t1000\t\t\t16384\t1\n"
781                                   "three.txt\tThree\tthree.txt\t1000\t\t\t16384\t3\n"
782                                   "two.txt\tTwo\ttwo.txt\t1000\t\t\t16384\t2\n"
783                                   "file\tcomponent\tfilename\t100\t\t\t8192\t1\n"
784                                   "service_file\tservice_comp\tservice.exe\t100\t\t\t8192\t1";
785
786 typedef struct _msi_table
787 {
788     const CHAR *filename;
789     const CHAR *data;
790     int size;
791 } msi_table;
792
793 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
794
795 static const msi_table tables[] =
796 {
797     ADD_TABLE(component),
798     ADD_TABLE(directory),
799     ADD_TABLE(feature),
800     ADD_TABLE(feature_comp),
801     ADD_TABLE(file),
802     ADD_TABLE(install_exec_seq),
803     ADD_TABLE(media),
804     ADD_TABLE(property),
805     ADD_TABLE(registry),
806     ADD_TABLE(service_install),
807     ADD_TABLE(service_control)
808 };
809
810 static const msi_table cc_tables[] =
811 {
812     ADD_TABLE(cc_component),
813     ADD_TABLE(directory),
814     ADD_TABLE(cc_feature),
815     ADD_TABLE(cc_feature_comp),
816     ADD_TABLE(cc_file),
817     ADD_TABLE(install_exec_seq),
818     ADD_TABLE(cc_media),
819     ADD_TABLE(property),
820 };
821
822 static const msi_table cc2_tables[] =
823 {
824     ADD_TABLE(cc2_component),
825     ADD_TABLE(directory),
826     ADD_TABLE(cc_feature),
827     ADD_TABLE(cc_feature_comp),
828     ADD_TABLE(cc2_file),
829     ADD_TABLE(install_exec_seq),
830     ADD_TABLE(cc_media),
831     ADD_TABLE(property),
832 };
833
834 static const msi_table co_tables[] =
835 {
836     ADD_TABLE(cc_component),
837     ADD_TABLE(directory),
838     ADD_TABLE(cc_feature),
839     ADD_TABLE(cc_feature_comp),
840     ADD_TABLE(co_file),
841     ADD_TABLE(install_exec_seq),
842     ADD_TABLE(co_media),
843     ADD_TABLE(property),
844 };
845
846 static const msi_table co2_tables[] =
847 {
848     ADD_TABLE(cc_component),
849     ADD_TABLE(directory),
850     ADD_TABLE(cc_feature),
851     ADD_TABLE(cc_feature_comp),
852     ADD_TABLE(cc_file),
853     ADD_TABLE(install_exec_seq),
854     ADD_TABLE(co2_media),
855     ADD_TABLE(property),
856 };
857
858 static const msi_table mm_tables[] =
859 {
860     ADD_TABLE(cc_component),
861     ADD_TABLE(directory),
862     ADD_TABLE(cc_feature),
863     ADD_TABLE(cc_feature_comp),
864     ADD_TABLE(mm_file),
865     ADD_TABLE(install_exec_seq),
866     ADD_TABLE(mm_media),
867     ADD_TABLE(property),
868 };
869
870 static const msi_table ss_tables[] =
871 {
872     ADD_TABLE(cc_component),
873     ADD_TABLE(directory),
874     ADD_TABLE(cc_feature),
875     ADD_TABLE(cc_feature_comp),
876     ADD_TABLE(cc_file),
877     ADD_TABLE(install_exec_seq),
878     ADD_TABLE(ss_media),
879     ADD_TABLE(property),
880 };
881
882 static const msi_table ui_tables[] =
883 {
884     ADD_TABLE(ui_component),
885     ADD_TABLE(directory),
886     ADD_TABLE(cc_feature),
887     ADD_TABLE(cc_feature_comp),
888     ADD_TABLE(cc_file),
889     ADD_TABLE(install_exec_seq),
890     ADD_TABLE(ui_install_ui_seq),
891     ADD_TABLE(ui_custom_action),
892     ADD_TABLE(cc_media),
893     ADD_TABLE(property),
894 };
895
896 static const msi_table rof_tables[] =
897 {
898     ADD_TABLE(rof_component),
899     ADD_TABLE(directory),
900     ADD_TABLE(rof_feature),
901     ADD_TABLE(rof_feature_comp),
902     ADD_TABLE(rof_file),
903     ADD_TABLE(install_exec_seq),
904     ADD_TABLE(rof_media),
905     ADD_TABLE(property),
906 };
907
908 static const msi_table sdp_tables[] =
909 {
910     ADD_TABLE(rof_component),
911     ADD_TABLE(directory),
912     ADD_TABLE(rof_feature),
913     ADD_TABLE(rof_feature_comp),
914     ADD_TABLE(rof_file),
915     ADD_TABLE(sdp_install_exec_seq),
916     ADD_TABLE(sdp_custom_action),
917     ADD_TABLE(rof_media),
918     ADD_TABLE(property),
919 };
920
921 static const msi_table cie_tables[] =
922 {
923     ADD_TABLE(cie_component),
924     ADD_TABLE(directory),
925     ADD_TABLE(cc_feature),
926     ADD_TABLE(cie_feature_comp),
927     ADD_TABLE(cie_file),
928     ADD_TABLE(install_exec_seq),
929     ADD_TABLE(cie_media),
930     ADD_TABLE(property),
931 };
932
933 static const msi_table ci_tables[] =
934 {
935     ADD_TABLE(ci_component),
936     ADD_TABLE(directory),
937     ADD_TABLE(rof_feature),
938     ADD_TABLE(rof_feature_comp),
939     ADD_TABLE(rof_file),
940     ADD_TABLE(ci_install_exec_seq),
941     ADD_TABLE(rof_media),
942     ADD_TABLE(property),
943     ADD_TABLE(ci_custom_action),
944 };
945
946 static const msi_table ci2_tables[] =
947 {
948     ADD_TABLE(ci2_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 spf_tables[] =
959 {
960     ADD_TABLE(ci_component),
961     ADD_TABLE(directory),
962     ADD_TABLE(rof_feature),
963     ADD_TABLE(rof_feature_comp),
964     ADD_TABLE(rof_file),
965     ADD_TABLE(spf_install_exec_seq),
966     ADD_TABLE(rof_media),
967     ADD_TABLE(property),
968     ADD_TABLE(spf_custom_action),
969     ADD_TABLE(spf_install_ui_seq),
970 };
971
972 static const msi_table pp_tables[] =
973 {
974     ADD_TABLE(ci_component),
975     ADD_TABLE(directory),
976     ADD_TABLE(rof_feature),
977     ADD_TABLE(rof_feature_comp),
978     ADD_TABLE(rof_file),
979     ADD_TABLE(pp_install_exec_seq),
980     ADD_TABLE(rof_media),
981     ADD_TABLE(property),
982 };
983
984 static const msi_table ppc_tables[] =
985 {
986     ADD_TABLE(ppc_component),
987     ADD_TABLE(directory),
988     ADD_TABLE(rof_feature),
989     ADD_TABLE(ppc_feature_comp),
990     ADD_TABLE(ppc_file),
991     ADD_TABLE(pp_install_exec_seq),
992     ADD_TABLE(ppc_media),
993     ADD_TABLE(property),
994 };
995
996 static const msi_table tp_tables[] =
997 {
998     ADD_TABLE(tp_component),
999     ADD_TABLE(directory),
1000     ADD_TABLE(rof_feature),
1001     ADD_TABLE(ci2_feature_comp),
1002     ADD_TABLE(ci2_file),
1003     ADD_TABLE(install_exec_seq),
1004     ADD_TABLE(rof_media),
1005     ADD_TABLE(property),
1006 };
1007
1008 static const msi_table cwd_tables[] =
1009 {
1010     ADD_TABLE(cwd_component),
1011     ADD_TABLE(directory),
1012     ADD_TABLE(rof_feature),
1013     ADD_TABLE(ci2_feature_comp),
1014     ADD_TABLE(ci2_file),
1015     ADD_TABLE(install_exec_seq),
1016     ADD_TABLE(rof_media),
1017     ADD_TABLE(property),
1018 };
1019
1020 static const msi_table adm_tables[] =
1021 {
1022     ADD_TABLE(adm_component),
1023     ADD_TABLE(directory),
1024     ADD_TABLE(rof_feature),
1025     ADD_TABLE(ci2_feature_comp),
1026     ADD_TABLE(ci2_file),
1027     ADD_TABLE(install_exec_seq),
1028     ADD_TABLE(rof_media),
1029     ADD_TABLE(property),
1030     ADD_TABLE(adm_custom_action),
1031     ADD_TABLE(adm_admin_exec_seq),
1032 };
1033
1034 static const msi_table amp_tables[] =
1035 {
1036     ADD_TABLE(amp_component),
1037     ADD_TABLE(directory),
1038     ADD_TABLE(rof_feature),
1039     ADD_TABLE(ci2_feature_comp),
1040     ADD_TABLE(ci2_file),
1041     ADD_TABLE(install_exec_seq),
1042     ADD_TABLE(rof_media),
1043     ADD_TABLE(property),
1044 };
1045
1046 static const msi_table rem_tables[] =
1047 {
1048     ADD_TABLE(rem_component),
1049     ADD_TABLE(directory),
1050     ADD_TABLE(rof_feature),
1051     ADD_TABLE(rem_feature_comp),
1052     ADD_TABLE(rem_file),
1053     ADD_TABLE(rem_install_exec_seq),
1054     ADD_TABLE(rof_media),
1055     ADD_TABLE(property),
1056     ADD_TABLE(rem_remove_files),
1057 };
1058
1059 static const msi_table mov_tables[] =
1060 {
1061     ADD_TABLE(cwd_component),
1062     ADD_TABLE(directory),
1063     ADD_TABLE(rof_feature),
1064     ADD_TABLE(ci2_feature_comp),
1065     ADD_TABLE(ci2_file),
1066     ADD_TABLE(install_exec_seq),
1067     ADD_TABLE(rof_media),
1068     ADD_TABLE(property),
1069     ADD_TABLE(mov_move_file),
1070 };
1071
1072 static const msi_table mc_tables[] =
1073 {
1074     ADD_TABLE(mc_component),
1075     ADD_TABLE(directory),
1076     ADD_TABLE(cc_feature),
1077     ADD_TABLE(cie_feature_comp),
1078     ADD_TABLE(mc_file),
1079     ADD_TABLE(install_exec_seq),
1080     ADD_TABLE(mc_media),
1081     ADD_TABLE(property),
1082     ADD_TABLE(mc_file_hash),
1083 };
1084
1085 static const msi_table df_tables[] =
1086 {
1087     ADD_TABLE(rof_component),
1088     ADD_TABLE(df_directory),
1089     ADD_TABLE(rof_feature),
1090     ADD_TABLE(rof_feature_comp),
1091     ADD_TABLE(rof_file),
1092     ADD_TABLE(install_exec_seq),
1093     ADD_TABLE(rof_media),
1094     ADD_TABLE(property),
1095     ADD_TABLE(df_duplicate_file),
1096 };
1097
1098 static const msi_table wrv_tables[] =
1099 {
1100     ADD_TABLE(wrv_component),
1101     ADD_TABLE(directory),
1102     ADD_TABLE(rof_feature),
1103     ADD_TABLE(ci2_feature_comp),
1104     ADD_TABLE(ci2_file),
1105     ADD_TABLE(install_exec_seq),
1106     ADD_TABLE(rof_media),
1107     ADD_TABLE(property),
1108     ADD_TABLE(wrv_registry),
1109 };
1110
1111 static const msi_table sf_tables[] =
1112 {
1113     ADD_TABLE(wrv_component),
1114     ADD_TABLE(directory),
1115     ADD_TABLE(rof_feature),
1116     ADD_TABLE(ci2_feature_comp),
1117     ADD_TABLE(ci2_file),
1118     ADD_TABLE(install_exec_seq),
1119     ADD_TABLE(rof_media),
1120     ADD_TABLE(property),
1121 };
1122
1123 static const msi_table ca51_tables[] =
1124 {
1125     ADD_TABLE(ca51_component),
1126     ADD_TABLE(directory),
1127     ADD_TABLE(rof_feature),
1128     ADD_TABLE(ci2_feature_comp),
1129     ADD_TABLE(ci2_file),
1130     ADD_TABLE(ca51_install_exec_seq),
1131     ADD_TABLE(rof_media),
1132     ADD_TABLE(property),
1133     ADD_TABLE(ca51_custom_action),
1134 };
1135
1136 static const msi_table is_tables[] =
1137 {
1138     ADD_TABLE(is_component),
1139     ADD_TABLE(directory),
1140     ADD_TABLE(is_feature),
1141     ADD_TABLE(is_feature_comp),
1142     ADD_TABLE(is_file),
1143     ADD_TABLE(install_exec_seq),
1144     ADD_TABLE(is_media),
1145     ADD_TABLE(property),
1146 };
1147
1148 static const msi_table sp_tables[] =
1149 {
1150     ADD_TABLE(sp_component),
1151     ADD_TABLE(sp_directory),
1152     ADD_TABLE(rof_feature),
1153     ADD_TABLE(ci2_feature_comp),
1154     ADD_TABLE(ci2_file),
1155     ADD_TABLE(install_exec_seq),
1156     ADD_TABLE(rof_media),
1157     ADD_TABLE(property),
1158 };
1159
1160 static const msi_table mcp_tables[] =
1161 {
1162     ADD_TABLE(mcp_component),
1163     ADD_TABLE(directory),
1164     ADD_TABLE(mcp_feature),
1165     ADD_TABLE(mcp_feature_comp),
1166     ADD_TABLE(rem_file),
1167     ADD_TABLE(rem_install_exec_seq),
1168     ADD_TABLE(rof_media),
1169     ADD_TABLE(property),
1170 };
1171
1172 static const msi_table mcomp_tables[] =
1173 {
1174     ADD_TABLE(mcp_component),
1175     ADD_TABLE(directory),
1176     ADD_TABLE(mcp_feature),
1177     ADD_TABLE(mcp_feature_comp),
1178     ADD_TABLE(mcomp_file),
1179     ADD_TABLE(rem_install_exec_seq),
1180     ADD_TABLE(rof_media),
1181     ADD_TABLE(property),
1182 };
1183
1184 static const msi_table ai_tables[] =
1185 {
1186     ADD_TABLE(component),
1187     ADD_TABLE(directory),
1188     ADD_TABLE(feature),
1189     ADD_TABLE(feature_comp),
1190     ADD_TABLE(ai_file),
1191     ADD_TABLE(install_exec_seq),
1192     ADD_TABLE(media),
1193     ADD_TABLE(property)
1194 };
1195
1196 static const msi_table pc_tables[] =
1197 {
1198     ADD_TABLE(ca51_component),
1199     ADD_TABLE(directory),
1200     ADD_TABLE(rof_feature),
1201     ADD_TABLE(ci2_feature_comp),
1202     ADD_TABLE(ci2_file),
1203     ADD_TABLE(install_exec_seq),
1204     ADD_TABLE(rof_media),
1205     ADD_TABLE(property)
1206 };
1207
1208 /* cabinet definitions */
1209
1210 /* make the max size large so there is only one cab file */
1211 #define MEDIA_SIZE          0x7FFFFFFF
1212 #define FOLDER_THRESHOLD    900000
1213
1214 /* the FCI callbacks */
1215
1216 static void * CDECL mem_alloc(ULONG cb)
1217 {
1218     return HeapAlloc(GetProcessHeap(), 0, cb);
1219 }
1220
1221 static void CDECL mem_free(void *memory)
1222 {
1223     HeapFree(GetProcessHeap(), 0, memory);
1224 }
1225
1226 static BOOL CDECL get_next_cabinet(PCCAB pccab, ULONG  cbPrevCab, void *pv)
1227 {
1228     sprintf(pccab->szCab, pv, pccab->iCab);
1229     return TRUE;
1230 }
1231
1232 static LONG CDECL progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
1233 {
1234     return 0;
1235 }
1236
1237 static int CDECL file_placed(PCCAB pccab, char *pszFile, LONG cbFile,
1238                              BOOL fContinuation, void *pv)
1239 {
1240     return 0;
1241 }
1242
1243 static INT_PTR CDECL fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
1244 {
1245     HANDLE handle;
1246     DWORD dwAccess = 0;
1247     DWORD dwShareMode = 0;
1248     DWORD dwCreateDisposition = OPEN_EXISTING;
1249     
1250     dwAccess = GENERIC_READ | GENERIC_WRITE;
1251     /* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
1252     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
1253
1254     if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
1255         dwCreateDisposition = OPEN_EXISTING;
1256     else
1257         dwCreateDisposition = CREATE_NEW;
1258
1259     handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
1260                          dwCreateDisposition, 0, NULL);
1261
1262     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
1263
1264     return (INT_PTR)handle;
1265 }
1266
1267 static UINT CDECL fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
1268 {
1269     HANDLE handle = (HANDLE)hf;
1270     DWORD dwRead;
1271     BOOL res;
1272     
1273     res = ReadFile(handle, memory, cb, &dwRead, NULL);
1274     ok(res, "Failed to ReadFile\n");
1275
1276     return dwRead;
1277 }
1278
1279 static UINT CDECL fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
1280 {
1281     HANDLE handle = (HANDLE)hf;
1282     DWORD dwWritten;
1283     BOOL res;
1284
1285     res = WriteFile(handle, memory, cb, &dwWritten, NULL);
1286     ok(res, "Failed to WriteFile\n");
1287
1288     return dwWritten;
1289 }
1290
1291 static int CDECL fci_close(INT_PTR hf, int *err, void *pv)
1292 {
1293     HANDLE handle = (HANDLE)hf;
1294     ok(CloseHandle(handle), "Failed to CloseHandle\n");
1295
1296     return 0;
1297 }
1298
1299 static LONG CDECL fci_seek(INT_PTR hf, LONG dist, int seektype, int *err, void *pv)
1300 {
1301     HANDLE handle = (HANDLE)hf;
1302     DWORD ret;
1303     
1304     ret = SetFilePointer(handle, dist, NULL, seektype);
1305     ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
1306
1307     return ret;
1308 }
1309
1310 static int CDECL fci_delete(char *pszFile, int *err, void *pv)
1311 {
1312     BOOL ret = DeleteFileA(pszFile);
1313     ok(ret, "Failed to DeleteFile %s\n", pszFile);
1314
1315     return 0;
1316 }
1317
1318 static void init_functionpointers(void)
1319 {
1320     HMODULE hmsi = GetModuleHandleA("msi.dll");
1321     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
1322
1323 #define GET_PROC(mod, func) \
1324     p ## func = (void*)GetProcAddress(mod, #func); \
1325     if(!p ## func) \
1326       trace("GetProcAddress(%s) failed\n", #func);
1327
1328     GET_PROC(hmsi, MsiQueryComponentStateA);
1329     GET_PROC(hmsi, MsiSourceListEnumSourcesA);
1330     GET_PROC(hmsi, MsiSourceListGetInfoA);
1331
1332     GET_PROC(hadvapi32, ConvertSidToStringSidA);
1333
1334     hsrclient = LoadLibraryA("srclient.dll");
1335     GET_PROC(hsrclient, SRRemoveRestorePoint);
1336     GET_PROC(hsrclient, SRSetRestorePointA);
1337
1338 #undef GET_PROC
1339 }
1340
1341 static BOOL check_win9x(void)
1342 {
1343     SC_HANDLE scm;
1344
1345     scm = OpenSCManager(NULL, NULL, GENERIC_ALL);
1346     if (!scm && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1347         return TRUE;
1348
1349     CloseServiceHandle(scm);
1350
1351     return FALSE;
1352 }
1353
1354 static LPSTR get_user_sid(LPSTR *usersid)
1355 {
1356     HANDLE token;
1357     BYTE buf[1024];
1358     DWORD size;
1359     PTOKEN_USER user;
1360
1361     if (!pConvertSidToStringSidA)
1362     {
1363         win_skip("ConvertSidToStringSidA is not available\n");
1364         return NULL;
1365     }
1366
1367     *usersid = NULL;
1368     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
1369     size = sizeof(buf);
1370     GetTokenInformation(token, TokenUser, buf, size, &size);
1371     user = (PTOKEN_USER)buf;
1372     pConvertSidToStringSidA(user->User.Sid, usersid);
1373     ok(*usersid != NULL, "pConvertSidToStringSidA failed lre=%d\n", GetLastError());
1374     CloseHandle(token);
1375     return *usersid;
1376 }
1377
1378 static BOOL check_record(MSIHANDLE rec, UINT field, LPCSTR val)
1379 {
1380     CHAR buffer[0x20];
1381     UINT r;
1382     DWORD sz;
1383
1384     sz = sizeof buffer;
1385     r = MsiRecordGetString(rec, field, buffer, &sz);
1386     return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
1387 }
1388
1389 static BOOL CDECL get_temp_file(char *pszTempName, int cbTempName, void *pv)
1390 {
1391     LPSTR tempname;
1392
1393     tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
1394     GetTempFileNameA(".", "xx", 0, tempname);
1395
1396     if (tempname && (strlen(tempname) < (unsigned)cbTempName))
1397     {
1398         lstrcpyA(pszTempName, tempname);
1399         HeapFree(GetProcessHeap(), 0, tempname);
1400         return TRUE;
1401     }
1402
1403     HeapFree(GetProcessHeap(), 0, tempname);
1404
1405     return FALSE;
1406 }
1407
1408 static INT_PTR CDECL get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
1409                                    USHORT *pattribs, int *err, void *pv)
1410 {
1411     BY_HANDLE_FILE_INFORMATION finfo;
1412     FILETIME filetime;
1413     HANDLE handle;
1414     DWORD attrs;
1415     BOOL res;
1416
1417     handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
1418                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
1419
1420     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
1421
1422     res = GetFileInformationByHandle(handle, &finfo);
1423     ok(res, "Expected GetFileInformationByHandle to succeed\n");
1424    
1425     FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
1426     FileTimeToDosDateTime(&filetime, pdate, ptime);
1427
1428     attrs = GetFileAttributes(pszName);
1429     ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
1430
1431     return (INT_PTR)handle;
1432 }
1433
1434 static BOOL add_file(HFCI hfci, const char *file, TCOMP compress)
1435 {
1436     char path[MAX_PATH];
1437     char filename[MAX_PATH];
1438
1439     lstrcpyA(path, CURR_DIR);
1440     lstrcatA(path, "\\");
1441     lstrcatA(path, file);
1442
1443     lstrcpyA(filename, file);
1444
1445     return FCIAddFile(hfci, path, filename, FALSE, get_next_cabinet,
1446                       progress, get_open_info, compress);
1447 }
1448
1449 static void set_cab_parameters(PCCAB pCabParams, const CHAR *name, DWORD max_size)
1450 {
1451     ZeroMemory(pCabParams, sizeof(CCAB));
1452
1453     pCabParams->cb = max_size;
1454     pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
1455     pCabParams->setID = 0xbeef;
1456     pCabParams->iCab = 1;
1457     lstrcpyA(pCabParams->szCabPath, CURR_DIR);
1458     lstrcatA(pCabParams->szCabPath, "\\");
1459     lstrcpyA(pCabParams->szCab, name);
1460 }
1461
1462 static void create_cab_file(const CHAR *name, DWORD max_size, const CHAR *files)
1463 {
1464     CCAB cabParams;
1465     LPCSTR ptr;
1466     HFCI hfci;
1467     ERF erf;
1468     BOOL res;
1469
1470     set_cab_parameters(&cabParams, name, max_size);
1471
1472     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1473                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1474                       get_temp_file, &cabParams, NULL);
1475
1476     ok(hfci != NULL, "Failed to create an FCI context\n");
1477
1478     ptr = files;
1479     while (*ptr)
1480     {
1481         res = add_file(hfci, ptr, tcompTYPE_MSZIP);
1482         ok(res, "Failed to add file: %s\n", ptr);
1483         ptr += lstrlen(ptr) + 1;
1484     }
1485
1486     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1487     ok(res, "Failed to flush the cabinet\n");
1488
1489     res = FCIDestroy(hfci);
1490     ok(res, "Failed to destroy the cabinet\n");
1491 }
1492
1493 static BOOL get_program_files_dir(LPSTR buf, LPSTR buf2)
1494 {
1495     HKEY hkey;
1496     DWORD type, size;
1497
1498     if (RegOpenKey(HKEY_LOCAL_MACHINE,
1499                    "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
1500         return FALSE;
1501
1502     size = MAX_PATH;
1503     if (RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)buf, &size)) {
1504         RegCloseKey(hkey);
1505         return FALSE;
1506     }
1507
1508     size = MAX_PATH;
1509     if (RegQueryValueExA(hkey, "CommonFilesDir", 0, &type, (LPBYTE)buf2, &size)) {
1510         RegCloseKey(hkey);
1511         return FALSE;
1512     }
1513
1514     RegCloseKey(hkey);
1515     return TRUE;
1516 }
1517
1518 static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
1519 {
1520     HANDLE file;
1521     DWORD written;
1522
1523     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1524     if (file == INVALID_HANDLE_VALUE)
1525         return;
1526
1527     WriteFile(file, data, strlen(data), &written, NULL);
1528
1529     if (size)
1530     {
1531         SetFilePointer(file, size, NULL, FILE_BEGIN);
1532         SetEndOfFile(file);
1533     }
1534
1535     CloseHandle(file);
1536 }
1537
1538 #define create_file(name, size) create_file_data(name, name, size)
1539
1540 static void create_test_files(void)
1541 {
1542     CreateDirectoryA("msitest", NULL);
1543     create_file("msitest\\one.txt", 100);
1544     CreateDirectoryA("msitest\\first", NULL);
1545     create_file("msitest\\first\\two.txt", 100);
1546     CreateDirectoryA("msitest\\second", NULL);
1547     create_file("msitest\\second\\three.txt", 100);
1548
1549     create_file("four.txt", 100);
1550     create_file("five.txt", 100);
1551     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1552
1553     create_file("msitest\\filename", 100);
1554     create_file("msitest\\service.exe", 100);
1555
1556     DeleteFileA("four.txt");
1557     DeleteFileA("five.txt");
1558 }
1559
1560 static BOOL delete_pf(const CHAR *rel_path, BOOL is_file)
1561 {
1562     CHAR path[MAX_PATH];
1563
1564     lstrcpyA(path, PROG_FILES_DIR);
1565     lstrcatA(path, "\\");
1566     lstrcatA(path, rel_path);
1567
1568     if (is_file)
1569         return DeleteFileA(path);
1570     else
1571         return RemoveDirectoryA(path);
1572 }
1573
1574 static BOOL delete_cf(const CHAR *rel_path, BOOL is_file)
1575 {
1576     CHAR path[MAX_PATH];
1577
1578     lstrcpyA(path, COMMON_FILES_DIR);
1579     lstrcatA(path, "\\");
1580     lstrcatA(path, rel_path);
1581
1582     if (is_file)
1583         return DeleteFileA(path);
1584     else
1585         return RemoveDirectoryA(path);
1586 }
1587
1588 static void delete_test_files(void)
1589 {
1590     DeleteFileA("msitest.msi");
1591     DeleteFileA("msitest.cab");
1592     DeleteFileA("msitest\\second\\three.txt");
1593     DeleteFileA("msitest\\first\\two.txt");
1594     DeleteFileA("msitest\\one.txt");
1595     DeleteFileA("msitest\\service.exe");
1596     DeleteFileA("msitest\\filename");
1597     RemoveDirectoryA("msitest\\second");
1598     RemoveDirectoryA("msitest\\first");
1599     RemoveDirectoryA("msitest");
1600 }
1601
1602 static void write_file(const CHAR *filename, const char *data, int data_size)
1603 {
1604     DWORD size;
1605
1606     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
1607                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1608
1609     WriteFile(hf, data, data_size, &size, NULL);
1610     CloseHandle(hf);
1611 }
1612
1613 static void write_msi_summary_info(MSIHANDLE db, INT wordcount)
1614 {
1615     MSIHANDLE summary;
1616     UINT r;
1617
1618     r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
1619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1620
1621     r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, ";1033");
1622     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1623
1624     r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1625                                    "{004757CA-5092-49c2-AD20-28E1CE0DF5F2}");
1626     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1627
1628     r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
1629     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1630
1631     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, wordcount, NULL, NULL);
1632     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1633
1634     r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
1635     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1636
1637     /* write the summary changes back to the stream */
1638     r = MsiSummaryInfoPersist(summary);
1639     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1640
1641     MsiCloseHandle(summary);
1642 }
1643
1644 #define create_database(name, tables, num_tables) \
1645     create_database_wordcount(name, tables, num_tables, 0);
1646
1647 static void create_database_wordcount(const CHAR *name, const msi_table *tables,
1648                                       int num_tables, INT wordcount)
1649 {
1650     MSIHANDLE db;
1651     UINT r;
1652     int j;
1653
1654     r = MsiOpenDatabaseA(name, MSIDBOPEN_CREATE, &db);
1655     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1656
1657     /* import the tables into the database */
1658     for (j = 0; j < num_tables; j++)
1659     {
1660         const msi_table *table = &tables[j];
1661
1662         write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
1663
1664         r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
1665         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1666
1667         DeleteFileA(table->filename);
1668     }
1669
1670     write_msi_summary_info(db, wordcount);
1671
1672     r = MsiDatabaseCommit(db);
1673     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1674
1675     MsiCloseHandle(db);
1676 }
1677
1678 static void check_service_is_installed(void)
1679 {
1680     SC_HANDLE scm, service;
1681     BOOL res;
1682
1683     scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1684     ok(scm != NULL, "Failed to open the SC Manager\n");
1685
1686     service = OpenService(scm, "TestService", SC_MANAGER_ALL_ACCESS);
1687     ok(service != NULL, "Failed to open TestService\n");
1688
1689     res = DeleteService(service);
1690     ok(res, "Failed to delete TestService\n");
1691
1692     CloseServiceHandle(service);
1693     CloseServiceHandle(scm);
1694 }
1695
1696 static BOOL notify_system_change(DWORD event_type, STATEMGRSTATUS *status)
1697 {
1698     RESTOREPOINTINFOA spec;
1699
1700     spec.dwEventType = event_type;
1701     spec.dwRestorePtType = APPLICATION_INSTALL;
1702     spec.llSequenceNumber = status->llSequenceNumber;
1703     lstrcpyA(spec.szDescription, "msitest restore point");
1704
1705     return pSRSetRestorePointA(&spec, status);
1706 }
1707
1708 static void remove_restore_point(DWORD seq_number)
1709 {
1710     DWORD res;
1711
1712     res = pSRRemoveRestorePoint(seq_number);
1713     if (res != ERROR_SUCCESS)
1714         trace("Failed to remove the restore point : %08x\n", res);
1715 }
1716
1717 static void test_MsiInstallProduct(void)
1718 {
1719     UINT r;
1720     CHAR path[MAX_PATH];
1721     LONG res;
1722     HKEY hkey;
1723     DWORD num, size, type;
1724
1725     if (on_win9x)
1726     {
1727         win_skip("Services are not implemented on Win9x and WinMe\n");
1728         return;
1729     }
1730
1731     /* szPackagePath is NULL */
1732     r = MsiInstallProductA(NULL, "INSTALL=ALL");
1733     ok(r == ERROR_INVALID_PARAMETER,
1734        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1735
1736     /* both szPackagePath and szCommandLine are NULL */
1737     r = MsiInstallProductA(NULL, NULL);
1738     ok(r == ERROR_INVALID_PARAMETER,
1739        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
1740
1741     /* szPackagePath is empty */
1742     r = MsiInstallProductA("", "INSTALL=ALL");
1743     ok(r == ERROR_PATH_NOT_FOUND,
1744        "Expected ERROR_PATH_NOT_FOUND, got %d\n", r);
1745
1746     create_test_files();
1747     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1748
1749     r = MsiInstallProductA(msifile, NULL);
1750     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1751
1752     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
1753     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
1754     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
1755     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
1756     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
1757     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
1758     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
1759     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
1760     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
1761     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
1762     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
1763     ok(delete_pf("msitest", FALSE), "File not installed\n");
1764
1765     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
1766     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1767
1768     size = MAX_PATH;
1769     type = REG_SZ;
1770     res = RegQueryValueExA(hkey, "Name", NULL, &type, (LPBYTE)path, &size);
1771     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1772     ok(!lstrcmpA(path, "imaname"), "Expected imaname, got %s\n", path);
1773
1774     size = MAX_PATH;
1775     type = REG_SZ;
1776     res = RegQueryValueExA(hkey, "blah", NULL, &type, (LPBYTE)path, &size);
1777     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
1778
1779     size = sizeof(num);
1780     type = REG_DWORD;
1781     res = RegQueryValueExA(hkey, "number", NULL, &type, (LPBYTE)&num, &size);
1782     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1783     ok(num == 314, "Expected 314, got %d\n", num);
1784
1785     size = MAX_PATH;
1786     type = REG_SZ;
1787     res = RegQueryValueExA(hkey, "OrderTestName", NULL, &type, (LPBYTE)path, &size);
1788     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1789     ok(!lstrcmpA(path, "OrderTestValue"), "Expected OrderTestValue, got %s\n", path);
1790
1791     check_service_is_installed();
1792
1793     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
1794
1795     delete_test_files();
1796 }
1797
1798 static void test_MsiSetComponentState(void)
1799 {
1800     INSTALLSTATE installed, action;
1801     MSIHANDLE package;
1802     char path[MAX_PATH];
1803     UINT r;
1804
1805     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1806
1807     CoInitialize(NULL);
1808
1809     lstrcpy(path, CURR_DIR);
1810     lstrcat(path, "\\");
1811     lstrcat(path, msifile);
1812
1813     r = MsiOpenPackage(path, &package);
1814     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1815
1816     r = MsiDoAction(package, "CostInitialize");
1817     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1818
1819     r = MsiDoAction(package, "FileCost");
1820     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1821
1822     r = MsiDoAction(package, "CostFinalize");
1823     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1824
1825     r = MsiGetComponentState(package, "dangler", &installed, &action);
1826     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1827     ok(installed == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", installed);
1828     ok(action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1829
1830     r = MsiSetComponentState(package, "dangler", INSTALLSTATE_SOURCE);
1831     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1832
1833     MsiCloseHandle(package);
1834     CoUninitialize();
1835
1836     DeleteFileA(msifile);
1837 }
1838
1839 static void test_packagecoltypes(void)
1840 {
1841     MSIHANDLE hdb, view, rec;
1842     char path[MAX_PATH];
1843     LPCSTR query;
1844     UINT r, count;
1845
1846     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1847
1848     CoInitialize(NULL);
1849
1850     lstrcpy(path, CURR_DIR);
1851     lstrcat(path, "\\");
1852     lstrcat(path, msifile);
1853
1854     r = MsiOpenDatabase(path, MSIDBOPEN_READONLY, &hdb);
1855     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1856
1857     query = "SELECT * FROM `Media`";
1858     r = MsiDatabaseOpenView( hdb, query, &view );
1859     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1860
1861     r = MsiViewGetColumnInfo( view, MSICOLINFO_NAMES, &rec );
1862     count = MsiRecordGetFieldCount( rec );
1863     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1864     ok(count == 6, "Expected 6, got %d\n", count);
1865     ok(check_record(rec, 1, "DiskId"), "wrong column label\n");
1866     ok(check_record(rec, 2, "LastSequence"), "wrong column label\n");
1867     ok(check_record(rec, 3, "DiskPrompt"), "wrong column label\n");
1868     ok(check_record(rec, 4, "Cabinet"), "wrong column label\n");
1869     ok(check_record(rec, 5, "VolumeLabel"), "wrong column label\n");
1870     ok(check_record(rec, 6, "Source"), "wrong column label\n");
1871     MsiCloseHandle(rec);
1872
1873     r = MsiViewGetColumnInfo( view, MSICOLINFO_TYPES, &rec );
1874     count = MsiRecordGetFieldCount( rec );
1875     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1876     ok(count == 6, "Expected 6, got %d\n", count);
1877     ok(check_record(rec, 1, "i2"), "wrong column label\n");
1878     ok(check_record(rec, 2, "i4"), "wrong column label\n");
1879     ok(check_record(rec, 3, "L64"), "wrong column label\n");
1880     ok(check_record(rec, 4, "S255"), "wrong column label\n");
1881     ok(check_record(rec, 5, "S32"), "wrong column label\n");
1882     ok(check_record(rec, 6, "S72"), "wrong column label\n");
1883
1884     MsiCloseHandle(rec);
1885     MsiCloseHandle(view);
1886     MsiCloseHandle(hdb);
1887     CoUninitialize();
1888
1889     DeleteFile(msifile);
1890 }
1891
1892 static void create_cc_test_files(void)
1893 {
1894     CCAB cabParams;
1895     HFCI hfci;
1896     ERF erf;
1897     static CHAR cab_context[] = "test%d.cab";
1898     BOOL res;
1899
1900     create_file("maximus", 500);
1901     create_file("augustus", 50000);
1902     create_file("tiberius", 500);
1903     create_file("caesar", 500);
1904
1905     set_cab_parameters(&cabParams, "test1.cab", 40000);
1906
1907     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1908                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1909                       get_temp_file, &cabParams, cab_context);
1910     ok(hfci != NULL, "Failed to create an FCI context\n");
1911
1912     res = add_file(hfci, "maximus", tcompTYPE_NONE);
1913     ok(res, "Failed to add file maximus\n");
1914
1915     res = add_file(hfci, "augustus", tcompTYPE_NONE);
1916     ok(res, "Failed to add file augustus\n");
1917
1918     res = add_file(hfci, "tiberius", tcompTYPE_NONE);
1919     ok(res, "Failed to add file tiberius\n");
1920
1921     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1922     ok(res, "Failed to flush the cabinet\n");
1923
1924     res = FCIDestroy(hfci);
1925     ok(res, "Failed to destroy the cabinet\n");
1926
1927     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1928
1929     DeleteFile("maximus");
1930     DeleteFile("augustus");
1931     DeleteFile("tiberius");
1932     DeleteFile("caesar");
1933 }
1934
1935 static void delete_cab_files(void)
1936 {
1937     SHFILEOPSTRUCT shfl;
1938     CHAR path[MAX_PATH+10];
1939
1940     lstrcpyA(path, CURR_DIR);
1941     lstrcatA(path, "\\*.cab");
1942     path[strlen(path) + 1] = '\0';
1943
1944     shfl.hwnd = NULL;
1945     shfl.wFunc = FO_DELETE;
1946     shfl.pFrom = path;
1947     shfl.pTo = NULL;
1948     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
1949
1950     SHFileOperation(&shfl);
1951 }
1952
1953 static void test_continuouscabs(void)
1954 {
1955     UINT r;
1956
1957     create_cc_test_files();
1958     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1959
1960     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1961
1962     r = MsiInstallProductA(msifile, NULL);
1963     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
1964     {
1965         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1966         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1967         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1968         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1969         ok(delete_pf("msitest", FALSE), "File not installed\n");
1970     }
1971
1972     delete_cab_files();
1973     DeleteFile(msifile);
1974
1975     create_cc_test_files();
1976     create_database(msifile, cc2_tables, sizeof(cc2_tables) / sizeof(msi_table));
1977
1978     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1979
1980     r = MsiInstallProductA(msifile, NULL);
1981     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1982     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1983     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
1984     ok(delete_pf("msitest\\tiberius", TRUE), "File not installed\n");
1985     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1986     ok(delete_pf("msitest", FALSE), "File not installed\n");
1987
1988     delete_cab_files();
1989     DeleteFile(msifile);
1990 }
1991
1992 static void test_caborder(void)
1993 {
1994     UINT r;
1995
1996     create_file("imperator", 100);
1997     create_file("maximus", 500);
1998     create_file("augustus", 50000);
1999     create_file("caesar", 500);
2000
2001     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
2002
2003     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2004
2005     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
2006     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
2007     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
2008
2009     r = MsiInstallProductA(msifile, NULL);
2010     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
2011     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
2012     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
2013     todo_wine
2014     {
2015         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
2016         ok(!delete_pf("msitest", FALSE), "File is installed\n");
2017     }
2018
2019     delete_cab_files();
2020
2021     create_cab_file("test1.cab", MEDIA_SIZE, "imperator\0");
2022     create_cab_file("test2.cab", MEDIA_SIZE, "maximus\0augustus\0");
2023     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
2024
2025     r = MsiInstallProductA(msifile, NULL);
2026     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
2027     ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
2028     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
2029     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
2030     todo_wine
2031     {
2032         ok(!delete_pf("msitest", FALSE), "File is installed\n");
2033     }
2034
2035     delete_cab_files();
2036     DeleteFile(msifile);
2037
2038     create_cc_test_files();
2039     create_database(msifile, co_tables, sizeof(co_tables) / sizeof(msi_table));
2040
2041     r = MsiInstallProductA(msifile, NULL);
2042     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
2043     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
2044     ok(!delete_pf("msitest", FALSE), "File is installed\n");
2045     todo_wine
2046     {
2047         ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
2048         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
2049     }
2050
2051     delete_cab_files();
2052     DeleteFile(msifile);
2053
2054     create_cc_test_files();
2055     create_database(msifile, co2_tables, sizeof(co2_tables) / sizeof(msi_table));
2056
2057     r = MsiInstallProductA(msifile, NULL);
2058     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
2059     todo_wine
2060     {
2061         ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
2062         ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
2063         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
2064         ok(!delete_pf("msitest", FALSE), "File is installed\n");
2065     }
2066
2067     delete_cab_files();
2068     DeleteFile("imperator");
2069     DeleteFile("maximus");
2070     DeleteFile("augustus");
2071     DeleteFile("caesar");
2072     DeleteFile(msifile);
2073 }
2074
2075 static void test_mixedmedia(void)
2076 {
2077     UINT r;
2078
2079     CreateDirectoryA("msitest", NULL);
2080     create_file("msitest\\maximus", 500);
2081     create_file("msitest\\augustus", 500);
2082     create_file("caesar", 500);
2083
2084     create_database(msifile, mm_tables, sizeof(mm_tables) / sizeof(msi_table));
2085
2086     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2087
2088     create_cab_file("test1.cab", MEDIA_SIZE, "caesar\0");
2089
2090     r = MsiInstallProductA(msifile, NULL);
2091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2092     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2093     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2094     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2095     ok(delete_pf("msitest", FALSE), "File not installed\n");
2096
2097     /* Delete the files in the temp (current) folder */
2098     DeleteFile("msitest\\maximus");
2099     DeleteFile("msitest\\augustus");
2100     RemoveDirectory("msitest");
2101     DeleteFile("caesar");
2102     DeleteFile("test1.cab");
2103     DeleteFile(msifile);
2104 }
2105
2106 static void test_samesequence(void)
2107 {
2108     UINT r;
2109
2110     create_cc_test_files();
2111     create_database(msifile, ss_tables, sizeof(ss_tables) / sizeof(msi_table));
2112
2113     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2114
2115     r = MsiInstallProductA(msifile, NULL);
2116     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
2117     {
2118         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2119         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2120         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2121         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2122         ok(delete_pf("msitest", FALSE), "File not installed\n");
2123     }
2124
2125     delete_cab_files();
2126     DeleteFile(msifile);
2127 }
2128
2129 static void test_uiLevelFlags(void)
2130 {
2131     UINT r;
2132
2133     create_cc_test_files();
2134     create_database(msifile, ui_tables, sizeof(ui_tables) / sizeof(msi_table));
2135
2136     MsiSetInternalUI(INSTALLUILEVEL_NONE | INSTALLUILEVEL_SOURCERESONLY, NULL);
2137
2138     r = MsiInstallProductA(msifile, NULL);
2139     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
2140     {
2141         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2142         ok(!delete_pf("msitest\\maximus", TRUE), "UI install occurred, but execute-only was requested.\n");
2143         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2144         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2145         ok(delete_pf("msitest", FALSE), "File not installed\n");
2146     }
2147
2148     delete_cab_files();
2149     DeleteFile(msifile);
2150 }
2151
2152 static BOOL file_matches(LPSTR path)
2153 {
2154     CHAR buf[MAX_PATH];
2155     HANDLE file;
2156     DWORD size;
2157
2158     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
2159                       NULL, OPEN_EXISTING, 0, NULL);
2160
2161     ZeroMemory(buf, MAX_PATH);
2162     ReadFile(file, buf, 15, &size, NULL);
2163     CloseHandle(file);
2164
2165     return !lstrcmp(buf, "msitest\\maximus");
2166 }
2167
2168 static void test_readonlyfile(void)
2169 {
2170     UINT r;
2171     DWORD size;
2172     HANDLE file;
2173     CHAR path[MAX_PATH];
2174
2175     CreateDirectoryA("msitest", NULL);
2176     create_file("msitest\\maximus", 500);
2177     create_database(msifile, rof_tables, sizeof(rof_tables) / sizeof(msi_table));
2178
2179     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2180
2181     lstrcpy(path, PROG_FILES_DIR);
2182     lstrcat(path, "\\msitest");
2183     CreateDirectory(path, NULL);
2184
2185     lstrcat(path, "\\maximus");
2186     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
2187                       NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
2188
2189     WriteFile(file, "readonlyfile", strlen("readonlyfile"), &size, NULL);
2190     CloseHandle(file);
2191
2192     r = MsiInstallProductA(msifile, NULL);
2193     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2194     ok(file_matches(path), "Expected file to be overwritten\n");
2195     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2196     ok(delete_pf("msitest", FALSE), "File not installed\n");
2197
2198     /* Delete the files in the temp (current) folder */
2199     DeleteFile("msitest\\maximus");
2200     RemoveDirectory("msitest");
2201     DeleteFile(msifile);
2202 }
2203
2204 static void test_setdirproperty(void)
2205 {
2206     UINT r;
2207
2208     CreateDirectoryA("msitest", NULL);
2209     create_file("msitest\\maximus", 500);
2210     create_database(msifile, sdp_tables, sizeof(sdp_tables) / sizeof(msi_table));
2211
2212     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2213
2214     r = MsiInstallProductA(msifile, NULL);
2215     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2216     ok(delete_cf("msitest\\maximus", TRUE), "File not installed\n");
2217     ok(delete_cf("msitest", FALSE), "File not installed\n");
2218
2219     /* Delete the files in the temp (current) folder */
2220     DeleteFile(msifile);
2221     DeleteFile("msitest\\maximus");
2222     RemoveDirectory("msitest");
2223 }
2224
2225 static void test_cabisextracted(void)
2226 {
2227     UINT r;
2228
2229     CreateDirectoryA("msitest", NULL);
2230     create_file("msitest\\gaius", 500);
2231     create_file("maximus", 500);
2232     create_file("augustus", 500);
2233     create_file("caesar", 500);
2234
2235     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
2236     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
2237     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
2238
2239     create_database(msifile, cie_tables, sizeof(cie_tables) / sizeof(msi_table));
2240
2241     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2242
2243     r = MsiInstallProductA(msifile, NULL);
2244     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2245     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2246     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2247     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2248     ok(delete_pf("msitest\\gaius", TRUE), "File not installed\n");
2249     ok(delete_pf("msitest", FALSE), "File not installed\n");
2250
2251     /* Delete the files in the temp (current) folder */
2252     delete_cab_files();
2253     DeleteFile(msifile);
2254     DeleteFile("maximus");
2255     DeleteFile("augustus");
2256     DeleteFile("caesar");
2257     DeleteFile("msitest\\gaius");
2258     RemoveDirectory("msitest");
2259 }
2260
2261 static void test_concurrentinstall(void)
2262 {
2263     UINT r;
2264     CHAR path[MAX_PATH];
2265
2266     CreateDirectoryA("msitest", NULL);
2267     CreateDirectoryA("msitest\\msitest", NULL);
2268     create_file("msitest\\maximus", 500);
2269     create_file("msitest\\msitest\\augustus", 500);
2270
2271     create_database(msifile, ci_tables, sizeof(ci_tables) / sizeof(msi_table));
2272
2273     lstrcpyA(path, CURR_DIR);
2274     lstrcatA(path, "\\msitest\\concurrent.msi");
2275     create_database(path, ci2_tables, sizeof(ci2_tables) / sizeof(msi_table));
2276
2277     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2278
2279     r = MsiInstallProductA(msifile, NULL);
2280     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2281     if (!delete_pf("msitest\\augustus", TRUE))
2282         trace("concurrent installs not supported\n");
2283     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2284     ok(delete_pf("msitest", FALSE), "File not installed\n");
2285
2286     DeleteFile(path);
2287
2288     r = MsiInstallProductA(msifile, NULL);
2289     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2290     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2291     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2292     ok(delete_pf("msitest", FALSE), "File not installed\n");
2293
2294     DeleteFile(msifile);
2295     DeleteFile("msitest\\msitest\\augustus");
2296     DeleteFile("msitest\\maximus");
2297     RemoveDirectory("msitest\\msitest");
2298     RemoveDirectory("msitest");
2299 }
2300
2301 static void test_setpropertyfolder(void)
2302 {
2303     UINT r;
2304     CHAR path[MAX_PATH];
2305     DWORD attr;
2306
2307     lstrcpyA(path, PROG_FILES_DIR);
2308     lstrcatA(path, "\\msitest\\added");
2309
2310     CreateDirectoryA("msitest", NULL);
2311     create_file("msitest\\maximus", 500);
2312
2313     create_database(msifile, spf_tables, sizeof(spf_tables) / sizeof(msi_table));
2314
2315     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2316
2317     r = MsiInstallProductA(msifile, NULL);
2318     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2319     attr = GetFileAttributesA(path);
2320     if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY))
2321     {
2322         ok(delete_pf("msitest\\added\\maximus", TRUE), "File not installed\n");
2323         ok(delete_pf("msitest\\added", FALSE), "File not installed\n");
2324         ok(delete_pf("msitest", FALSE), "File not installed\n");
2325     }
2326     else
2327     {
2328         trace("changing folder property not supported\n");
2329         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2330         ok(delete_pf("msitest", FALSE), "File not installed\n");
2331     }
2332
2333     /* Delete the files in the temp (current) folder */
2334     DeleteFile(msifile);
2335     DeleteFile("msitest\\maximus");
2336     RemoveDirectory("msitest");
2337 }
2338
2339 static BOOL file_exists(LPCSTR file)
2340 {
2341     return GetFileAttributes(file) != INVALID_FILE_ATTRIBUTES;
2342 }
2343
2344 static BOOL pf_exists(LPCSTR file)
2345 {
2346     CHAR path[MAX_PATH];
2347
2348     lstrcpyA(path, PROG_FILES_DIR);
2349     lstrcatA(path, "\\");
2350     lstrcatA(path, file);
2351
2352     return file_exists(path);
2353 }
2354
2355 static void delete_pfmsitest_files(void)
2356 {
2357     SHFILEOPSTRUCT shfl;
2358     CHAR path[MAX_PATH+11];
2359
2360     lstrcpyA(path, PROG_FILES_DIR);
2361     lstrcatA(path, "\\msitest\\*");
2362     path[strlen(path) + 1] = '\0';
2363
2364     shfl.hwnd = NULL;
2365     shfl.wFunc = FO_DELETE;
2366     shfl.pFrom = path;
2367     shfl.pTo = NULL;
2368     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
2369
2370     SHFileOperation(&shfl);
2371
2372     lstrcpyA(path, PROG_FILES_DIR);
2373     lstrcatA(path, "\\msitest");
2374     RemoveDirectoryA(path);
2375 }
2376
2377 static void check_reg_str(HKEY prodkey, LPCSTR name, LPCSTR expected, BOOL bcase, DWORD line)
2378 {
2379     char val[MAX_PATH];
2380     DWORD size, type;
2381     LONG res;
2382
2383     size = MAX_PATH;
2384     val[0] = '\0';
2385     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)val, &size);
2386
2387     if (res != ERROR_SUCCESS ||
2388         (type != REG_SZ && type != REG_EXPAND_SZ && type != REG_MULTI_SZ))
2389     {
2390         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2391         return;
2392     }
2393
2394     if (!expected)
2395         ok_(__FILE__, line)(lstrlenA(val) == 0, "Expected empty string, got %s\n", val);
2396     else
2397     {
2398         if (bcase)
2399             ok_(__FILE__, line)(!lstrcmpA(val, expected), "Expected %s, got %s\n", expected, val);
2400         else
2401             ok_(__FILE__, line)(!lstrcmpiA(val, expected), "Expected %s, got %s\n", expected, val);
2402     }
2403 }
2404
2405 static void check_reg_dword(HKEY prodkey, LPCSTR name, DWORD expected, DWORD line)
2406 {
2407     DWORD val, size, type;
2408     LONG res;
2409
2410     size = sizeof(DWORD);
2411     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)&val, &size);
2412
2413     if (res != ERROR_SUCCESS || type != REG_DWORD)
2414     {
2415         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2416         return;
2417     }
2418
2419     ok_(__FILE__, line)(val == expected, "Expected %d, got %d\n", expected, val);
2420 }
2421
2422 static void check_reg_dword2(HKEY prodkey, LPCSTR name, DWORD expected1, DWORD expected2, DWORD line)
2423 {
2424     DWORD val, size, type;
2425     LONG res;
2426
2427     size = sizeof(DWORD);
2428     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)&val, &size);
2429
2430     if (res != ERROR_SUCCESS || type != REG_DWORD)
2431     {
2432         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2433         return;
2434     }
2435
2436     ok_(__FILE__, line)(val == expected1 || val == expected2, "Expected %d or %d, got %d\n", expected1, expected2, val);
2437 }
2438
2439 static void check_reg_dword3(HKEY prodkey, LPCSTR name, DWORD expected1, DWORD expected2, DWORD expected3, DWORD line)
2440 {
2441     DWORD val, size, type;
2442     LONG res;
2443
2444     size = sizeof(DWORD);
2445     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)&val, &size);
2446
2447     if (res != ERROR_SUCCESS || type != REG_DWORD)
2448     {
2449         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2450         return;
2451     }
2452
2453     ok_(__FILE__, line)(val == expected1 || val == expected2 || val == expected3,
2454                         "Expected %d, %d or %d, got %d\n", expected1, expected2, expected3, val);
2455 }
2456
2457 #define CHECK_REG_STR(prodkey, name, expected) \
2458     check_reg_str(prodkey, name, expected, TRUE, __LINE__);
2459
2460 #define CHECK_DEL_REG_STR(prodkey, name, expected) \
2461     check_reg_str(prodkey, name, expected, TRUE, __LINE__); \
2462     RegDeleteValueA(prodkey, name);
2463
2464 #define CHECK_REG_ISTR(prodkey, name, expected) \
2465     check_reg_str(prodkey, name, expected, FALSE, __LINE__);
2466
2467 #define CHECK_DEL_REG_ISTR(prodkey, name, expected) \
2468     check_reg_str(prodkey, name, expected, FALSE, __LINE__); \
2469     RegDeleteValueA(prodkey, name);
2470
2471 #define CHECK_REG_DWORD(prodkey, name, expected) \
2472     check_reg_dword(prodkey, name, expected, __LINE__);
2473
2474 #define CHECK_DEL_REG_DWORD(prodkey, name, expected) \
2475     check_reg_dword(prodkey, name, expected, __LINE__); \
2476     RegDeleteValueA(prodkey, name);
2477
2478 #define CHECK_REG_DWORD2(prodkey, name, expected1, expected2) \
2479     check_reg_dword2(prodkey, name, expected1, expected2, __LINE__);
2480
2481 #define CHECK_DEL_REG_DWORD2(prodkey, name, expected1, expected2) \
2482     check_reg_dword2(prodkey, name, expected1, expected2, __LINE__); \
2483     RegDeleteValueA(prodkey, name);
2484
2485 #define CHECK_REG_DWORD3(prodkey, name, expected1, expected2, expected3) \
2486     check_reg_dword3(prodkey, name, expected1, expected2, expected3, __LINE__);
2487
2488 #define CHECK_DEL_REG_DWORD3(prodkey, name, expected1, expected2, expected3) \
2489     check_reg_dword3(prodkey, name, expected1, expected2, expected3, __LINE__); \
2490     RegDeleteValueA(prodkey, name);
2491
2492 static void get_date_str(LPSTR date)
2493 {
2494     SYSTEMTIME systime;
2495
2496     static const char date_fmt[] = "%d%02d%02d";
2497     GetLocalTime(&systime);
2498     sprintf(date, date_fmt, systime.wYear, systime.wMonth, systime.wDay);
2499 }
2500
2501 static void test_publish_registerproduct(void)
2502 {
2503     UINT r;
2504     LONG res;
2505     HKEY hkey;
2506     HKEY props, usage;
2507     LPSTR usersid;
2508     char date[MAX_PATH];
2509     char temp[MAX_PATH];
2510     char keypath[MAX_PATH];
2511
2512     static const CHAR uninstall[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2513                                     "\\Uninstall\\{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2514     static const CHAR userdata[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Installer"
2515                                    "\\UserData\\%s\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2516     static const CHAR ugkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Installer"
2517                                 "\\UpgradeCodes\\51AAE0C44620A5E4788506E91F249BD2";
2518     static const CHAR userugkey[] = "Software\\Microsoft\\Installer\\UpgradeCodes"
2519                                     "\\51AAE0C44620A5E4788506E91F249BD2";
2520
2521     if (!get_user_sid(&usersid))
2522         return;
2523
2524     get_date_str(date);
2525     GetTempPath(MAX_PATH, temp);
2526
2527     CreateDirectoryA("msitest", NULL);
2528     create_file("msitest\\maximus", 500);
2529
2530     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2531
2532     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2533
2534     /* RegisterProduct */
2535     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
2536     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2537     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2538     ok(delete_pf("msitest", FALSE), "File not installed\n");
2539
2540     res = RegOpenKeyA(HKEY_CURRENT_USER, userugkey, &hkey);
2541     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2542
2543     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, uninstall, &hkey);
2544     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2545
2546     CHECK_DEL_REG_STR(hkey, "DisplayName", "MSITEST");
2547     CHECK_DEL_REG_STR(hkey, "DisplayVersion", "1.1.1");
2548     CHECK_DEL_REG_STR(hkey, "InstallDate", date);
2549     CHECK_DEL_REG_STR(hkey, "InstallSource", temp);
2550     CHECK_DEL_REG_ISTR(hkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2551     CHECK_DEL_REG_STR(hkey, "Publisher", "Wine");
2552     CHECK_DEL_REG_STR(hkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2553     CHECK_DEL_REG_STR(hkey, "AuthorizedCDFPrefix", NULL);
2554     CHECK_DEL_REG_STR(hkey, "Comments", NULL);
2555     CHECK_DEL_REG_STR(hkey, "Contact", NULL);
2556     CHECK_DEL_REG_STR(hkey, "HelpLink", NULL);
2557     CHECK_DEL_REG_STR(hkey, "HelpTelephone", NULL);
2558     CHECK_DEL_REG_STR(hkey, "InstallLocation", NULL);
2559     CHECK_DEL_REG_STR(hkey, "Readme", NULL);
2560     CHECK_DEL_REG_STR(hkey, "Size", NULL);
2561     CHECK_DEL_REG_STR(hkey, "URLInfoAbout", NULL);
2562     CHECK_DEL_REG_STR(hkey, "URLUpdateInfo", NULL);
2563     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
2564     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
2565     CHECK_DEL_REG_DWORD(hkey, "VersionMajor", 1);
2566     CHECK_DEL_REG_DWORD(hkey, "VersionMinor", 1);
2567     CHECK_DEL_REG_DWORD(hkey, "WindowsInstaller", 1);
2568     todo_wine
2569     {
2570         CHECK_DEL_REG_DWORD3(hkey, "EstimatedSize", 12, -12, 4);
2571     }
2572
2573     RegDeleteKeyA(hkey, "");
2574     RegCloseKey(hkey);
2575
2576     sprintf(keypath, userdata, usersid);
2577     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2578     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2579
2580     res = RegOpenKeyA(hkey, "InstallProperties", &props);
2581     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2582
2583     RegDeleteValueA(props, "LocalPackage"); /* LocalPackage is nondeterministic */
2584     CHECK_DEL_REG_STR(props, "DisplayName", "MSITEST");
2585     CHECK_DEL_REG_STR(props, "DisplayVersion", "1.1.1");
2586     CHECK_DEL_REG_STR(props, "InstallDate", date);
2587     CHECK_DEL_REG_STR(props, "InstallSource", temp);
2588     CHECK_DEL_REG_ISTR(props, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2589     CHECK_DEL_REG_STR(props, "Publisher", "Wine");
2590     CHECK_DEL_REG_STR(props, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2591     CHECK_DEL_REG_STR(props, "AuthorizedCDFPrefix", NULL);
2592     CHECK_DEL_REG_STR(props, "Comments", NULL);
2593     CHECK_DEL_REG_STR(props, "Contact", NULL);
2594     CHECK_DEL_REG_STR(props, "HelpLink", NULL);
2595     CHECK_DEL_REG_STR(props, "HelpTelephone", NULL);
2596     CHECK_DEL_REG_STR(props, "InstallLocation", NULL);
2597     CHECK_DEL_REG_STR(props, "Readme", NULL);
2598     CHECK_DEL_REG_STR(props, "Size", NULL);
2599     CHECK_DEL_REG_STR(props, "URLInfoAbout", NULL);
2600     CHECK_DEL_REG_STR(props, "URLUpdateInfo", NULL);
2601     CHECK_DEL_REG_DWORD(props, "Language", 1033);
2602     CHECK_DEL_REG_DWORD(props, "Version", 0x1010001);
2603     CHECK_DEL_REG_DWORD(props, "VersionMajor", 1);
2604     CHECK_DEL_REG_DWORD(props, "VersionMinor", 1);
2605     CHECK_DEL_REG_DWORD(props, "WindowsInstaller", 1);
2606     todo_wine
2607     {
2608         CHECK_DEL_REG_DWORD3(props, "EstimatedSize", 12, -12, 4);
2609     }
2610
2611     RegDeleteKeyA(props, "");
2612     RegCloseKey(props);
2613
2614     res = RegOpenKeyA(hkey, "Usage", &usage);
2615     todo_wine
2616     {
2617         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2618     }
2619
2620     RegDeleteKeyA(usage, "");
2621     RegCloseKey(usage);
2622     RegDeleteKeyA(hkey, "");
2623     RegCloseKey(hkey);
2624
2625     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, ugkey, &hkey);
2626     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2627
2628     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
2629
2630     RegDeleteKeyA(hkey, "");
2631     RegCloseKey(hkey);
2632
2633     /* RegisterProduct, machine */
2634     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 ALLUSERS=1");
2635     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2636     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2637     ok(delete_pf("msitest", FALSE), "File not installed\n");
2638
2639     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, userugkey, &hkey);
2640     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2641
2642     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, uninstall, &hkey);
2643     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2644
2645     CHECK_DEL_REG_STR(hkey, "DisplayName", "MSITEST");
2646     CHECK_DEL_REG_STR(hkey, "DisplayVersion", "1.1.1");
2647     CHECK_DEL_REG_STR(hkey, "InstallDate", date);
2648     CHECK_DEL_REG_STR(hkey, "InstallSource", temp);
2649     CHECK_DEL_REG_ISTR(hkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2650     CHECK_DEL_REG_STR(hkey, "Publisher", "Wine");
2651     CHECK_DEL_REG_STR(hkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2652     CHECK_DEL_REG_STR(hkey, "AuthorizedCDFPrefix", NULL);
2653     CHECK_DEL_REG_STR(hkey, "Comments", NULL);
2654     CHECK_DEL_REG_STR(hkey, "Contact", NULL);
2655     CHECK_DEL_REG_STR(hkey, "HelpLink", NULL);
2656     CHECK_DEL_REG_STR(hkey, "HelpTelephone", NULL);
2657     CHECK_DEL_REG_STR(hkey, "InstallLocation", NULL);
2658     CHECK_DEL_REG_STR(hkey, "Readme", NULL);
2659     CHECK_DEL_REG_STR(hkey, "Size", NULL);
2660     CHECK_DEL_REG_STR(hkey, "URLInfoAbout", NULL);
2661     CHECK_DEL_REG_STR(hkey, "URLUpdateInfo", NULL);
2662     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
2663     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
2664     CHECK_DEL_REG_DWORD(hkey, "VersionMajor", 1);
2665     CHECK_DEL_REG_DWORD(hkey, "VersionMinor", 1);
2666     CHECK_DEL_REG_DWORD(hkey, "WindowsInstaller", 1);
2667     todo_wine
2668     {
2669         CHECK_DEL_REG_DWORD3(hkey, "EstimatedSize", 12, -12, 4);
2670     }
2671
2672     RegDeleteKeyA(hkey, "");
2673     RegCloseKey(hkey);
2674
2675     sprintf(keypath, userdata, "S-1-5-18");
2676     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2677     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2678
2679     res = RegOpenKeyA(hkey, "InstallProperties", &props);
2680     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2681
2682     RegDeleteValueA(props, "LocalPackage"); /* LocalPackage is nondeterministic */
2683     CHECK_DEL_REG_STR(props, "DisplayName", "MSITEST");
2684     CHECK_DEL_REG_STR(props, "DisplayVersion", "1.1.1");
2685     CHECK_DEL_REG_STR(props, "InstallDate", date);
2686     CHECK_DEL_REG_STR(props, "InstallSource", temp);
2687     CHECK_DEL_REG_ISTR(props, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2688     CHECK_DEL_REG_STR(props, "Publisher", "Wine");
2689     CHECK_DEL_REG_STR(props, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2690     CHECK_DEL_REG_STR(props, "AuthorizedCDFPrefix", NULL);
2691     CHECK_DEL_REG_STR(props, "Comments", NULL);
2692     CHECK_DEL_REG_STR(props, "Contact", NULL);
2693     CHECK_DEL_REG_STR(props, "HelpLink", NULL);
2694     CHECK_DEL_REG_STR(props, "HelpTelephone", NULL);
2695     CHECK_DEL_REG_STR(props, "InstallLocation", NULL);
2696     CHECK_DEL_REG_STR(props, "Readme", NULL);
2697     CHECK_DEL_REG_STR(props, "Size", NULL);
2698     CHECK_DEL_REG_STR(props, "URLInfoAbout", NULL);
2699     CHECK_DEL_REG_STR(props, "URLUpdateInfo", NULL);
2700     CHECK_DEL_REG_DWORD(props, "Language", 1033);
2701     CHECK_DEL_REG_DWORD(props, "Version", 0x1010001);
2702     CHECK_DEL_REG_DWORD(props, "VersionMajor", 1);
2703     CHECK_DEL_REG_DWORD(props, "VersionMinor", 1);
2704     CHECK_DEL_REG_DWORD(props, "WindowsInstaller", 1);
2705     todo_wine
2706     {
2707         CHECK_DEL_REG_DWORD3(props, "EstimatedSize", 12, -12, 4);
2708     }
2709
2710     RegDeleteKeyA(props, "");
2711     RegCloseKey(props);
2712
2713     res = RegOpenKeyA(hkey, "Usage", &usage);
2714     todo_wine
2715     {
2716         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2717     }
2718
2719     RegDeleteKeyA(usage, "");
2720     RegCloseKey(usage);
2721     RegDeleteKeyA(hkey, "");
2722     RegCloseKey(hkey);
2723
2724     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, ugkey, &hkey);
2725     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2726
2727     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
2728
2729     RegDeleteKeyA(hkey, "");
2730     RegCloseKey(hkey);
2731
2732     DeleteFile(msifile);
2733     DeleteFile("msitest\\maximus");
2734     RemoveDirectory("msitest");
2735     HeapFree(GetProcessHeap(), 0, usersid);
2736 }
2737
2738 static void test_publish_publishproduct(void)
2739 {
2740     UINT r;
2741     LONG res;
2742     LPSTR usersid;
2743     HKEY sourcelist, net, props;
2744     HKEY hkey, patches, media;
2745     CHAR keypath[MAX_PATH];
2746     CHAR temp[MAX_PATH];
2747     CHAR path[MAX_PATH];
2748
2749     static const CHAR prodpath[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2750                                    "\\Installer\\UserData\\%s\\Products"
2751                                    "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2752     static const CHAR cuprodpath[] = "Software\\Microsoft\\Installer\\Products"
2753                                      "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2754     static const CHAR cuupgrades[] = "Software\\Microsoft\\Installer\\UpgradeCodes"
2755                                      "\\51AAE0C44620A5E4788506E91F249BD2";
2756     static const CHAR badprod[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2757                                   "\\Installer\\Products"
2758                                   "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2759     static const CHAR machprod[] = "Installer\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2760     static const CHAR machup[] = "Installer\\UpgradeCodes\\51AAE0C44620A5E4788506E91F249BD2";
2761
2762     if (!get_user_sid(&usersid))
2763         return;
2764
2765     GetTempPath(MAX_PATH, temp);
2766
2767     CreateDirectoryA("msitest", NULL);
2768     create_file("msitest\\maximus", 500);
2769
2770     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2771
2772     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2773
2774     /* PublishProduct, current user */
2775     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
2776     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2777     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2778     ok(delete_pf("msitest", FALSE), "File not installed\n");
2779
2780     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, badprod, &hkey);
2781     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2782
2783     sprintf(keypath, prodpath, usersid);
2784     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2785     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2786
2787     res = RegOpenKeyA(hkey, "InstallProperties", &props);
2788     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2789
2790     res = RegOpenKeyA(hkey, "Patches", &patches);
2791     todo_wine
2792     {
2793         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2794
2795         CHECK_DEL_REG_STR(patches, "AllPatches", NULL);
2796     }
2797
2798     RegDeleteKeyA(patches, "");
2799     RegCloseKey(patches);
2800     RegDeleteKeyA(hkey, "");
2801     RegCloseKey(hkey);
2802
2803     res = RegOpenKeyA(HKEY_CURRENT_USER, cuprodpath, &hkey);
2804     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2805
2806     CHECK_DEL_REG_STR(hkey, "ProductName", "MSITEST");
2807     CHECK_DEL_REG_STR(hkey, "PackageCode", "AC75740029052c94DA02821EECD05F2F");
2808     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
2809     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
2810     CHECK_DEL_REG_DWORD(hkey, "AuthorizedLUAApp", 0);
2811     CHECK_DEL_REG_DWORD(hkey, "Assignment", 0);
2812     CHECK_DEL_REG_DWORD(hkey, "AdvertiseFlags", 0x184);
2813     CHECK_DEL_REG_DWORD(hkey, "InstanceType", 0);
2814     CHECK_DEL_REG_STR(hkey, "Clients", ":");
2815
2816     res = RegOpenKeyA(hkey, "SourceList", &sourcelist);
2817     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2818
2819     lstrcpyA(path, "n;1;");
2820     lstrcatA(path, temp);
2821     CHECK_DEL_REG_STR(sourcelist, "LastUsedSource", path);
2822     CHECK_DEL_REG_STR(sourcelist, "PackageName", "msitest.msi");
2823
2824     res = RegOpenKeyA(sourcelist, "Net", &net);
2825     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2826
2827     CHECK_DEL_REG_STR(net, "1", temp);
2828
2829     RegDeleteKeyA(net, "");
2830     RegCloseKey(net);
2831
2832     res = RegOpenKeyA(sourcelist, "Media", &media);
2833     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2834
2835     CHECK_DEL_REG_STR(media, "1", "DISK1;");
2836
2837     RegDeleteKeyA(media, "");
2838     RegCloseKey(media);
2839     RegDeleteKeyA(sourcelist, "");
2840     RegCloseKey(sourcelist);
2841     RegDeleteKeyA(hkey, "");
2842     RegCloseKey(hkey);
2843
2844     res = RegOpenKeyA(HKEY_CURRENT_USER, cuupgrades, &hkey);
2845     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2846
2847     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
2848
2849     RegDeleteKeyA(hkey, "");
2850     RegCloseKey(hkey);
2851
2852     /* PublishProduct, machine */
2853     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1 ALLUSERS=1");
2854     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2855     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2856     ok(delete_pf("msitest", FALSE), "File not installed\n");
2857
2858     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, badprod, &hkey);
2859     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2860
2861     sprintf(keypath, prodpath, "S-1-5-18");
2862     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2863     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2864
2865     res = RegOpenKeyA(hkey, "InstallProperties", &props);
2866     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2867
2868     res = RegOpenKeyA(hkey, "Patches", &patches);
2869     todo_wine
2870     {
2871         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2872
2873         CHECK_DEL_REG_STR(patches, "AllPatches", NULL);
2874     }
2875
2876     RegDeleteKeyA(patches, "");
2877     RegCloseKey(patches);
2878     RegDeleteKeyA(hkey, "");
2879     RegCloseKey(hkey);
2880
2881     res = RegOpenKeyA(HKEY_CLASSES_ROOT, machprod, &hkey);
2882     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2883
2884     CHECK_DEL_REG_STR(hkey, "ProductName", "MSITEST");
2885     CHECK_DEL_REG_STR(hkey, "PackageCode", "AC75740029052c94DA02821EECD05F2F");
2886     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
2887     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
2888     CHECK_DEL_REG_DWORD(hkey, "AuthorizedLUAApp", 0);
2889     todo_wine CHECK_DEL_REG_DWORD(hkey, "Assignment", 1);
2890     CHECK_DEL_REG_DWORD(hkey, "AdvertiseFlags", 0x184);
2891     CHECK_DEL_REG_DWORD(hkey, "InstanceType", 0);
2892     CHECK_DEL_REG_STR(hkey, "Clients", ":");
2893
2894     res = RegOpenKeyA(hkey, "SourceList", &sourcelist);
2895     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2896
2897     lstrcpyA(path, "n;1;");
2898     lstrcatA(path, temp);
2899     CHECK_DEL_REG_STR(sourcelist, "LastUsedSource", path);
2900     CHECK_DEL_REG_STR(sourcelist, "PackageName", "msitest.msi");
2901
2902     res = RegOpenKeyA(sourcelist, "Net", &net);
2903     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2904
2905     CHECK_DEL_REG_STR(net, "1", temp);
2906
2907     RegDeleteKeyA(net, "");
2908     RegCloseKey(net);
2909
2910     res = RegOpenKeyA(sourcelist, "Media", &media);
2911     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2912
2913     CHECK_DEL_REG_STR(media, "1", "DISK1;");
2914
2915     RegDeleteKeyA(media, "");
2916     RegCloseKey(media);
2917     RegDeleteKeyA(sourcelist, "");
2918     RegCloseKey(sourcelist);
2919     RegDeleteKeyA(hkey, "");
2920     RegCloseKey(hkey);
2921
2922     res = RegOpenKeyA(HKEY_CLASSES_ROOT, machup, &hkey);
2923     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2924
2925     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
2926
2927     RegDeleteKeyA(hkey, "");
2928     RegCloseKey(hkey);
2929
2930     DeleteFile(msifile);
2931     DeleteFile("msitest\\maximus");
2932     RemoveDirectory("msitest");
2933     HeapFree(GetProcessHeap(), 0, usersid);
2934 }
2935
2936 static void test_publish_publishfeatures(void)
2937 {
2938     UINT r;
2939     LONG res;
2940     HKEY hkey;
2941     LPSTR usersid;
2942     CHAR keypath[MAX_PATH];
2943
2944     static const CHAR cupath[] = "Software\\Microsoft\\Installer\\Features"
2945                                  "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2946     static const CHAR udpath[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2947                                  "\\Installer\\UserData\\%s\\Products"
2948                                  "\\84A88FD7F6998CE40A22FB59F6B9C2BB\\Features";
2949     static const CHAR featkey[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2950                                   "\\Installer\\Features";
2951     static const CHAR classfeat[] = "Software\\Classes\\Installer\\Features"
2952                                     "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2953
2954     if (!get_user_sid(&usersid))
2955         return;
2956
2957     CreateDirectoryA("msitest", NULL);
2958     create_file("msitest\\maximus", 500);
2959
2960     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2961
2962     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2963
2964     /* PublishFeatures, current user */
2965     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
2966     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2967     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2968     ok(delete_pf("msitest", FALSE), "File not installed\n");
2969
2970     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, featkey, &hkey);
2971     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2972
2973     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, classfeat, &hkey);
2974     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2975
2976     res = RegOpenKeyA(HKEY_CURRENT_USER, cupath, &hkey);
2977     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2978
2979     CHECK_REG_STR(hkey, "feature", "");
2980     CHECK_REG_STR(hkey, "montecristo", "");
2981
2982     RegDeleteValueA(hkey, "feature");
2983     RegDeleteValueA(hkey, "montecristo");
2984     RegDeleteKeyA(hkey, "");
2985     RegCloseKey(hkey);
2986
2987     sprintf(keypath, udpath, usersid);
2988     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2989     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2990
2991     CHECK_REG_STR(hkey, "feature", "VGtfp^p+,?82@JU1j_KE");
2992     CHECK_REG_STR(hkey, "montecristo", "VGtfp^p+,?82@JU1j_KE");
2993
2994     RegDeleteValueA(hkey, "feature");
2995     RegDeleteValueA(hkey, "montecristo");
2996     RegDeleteKeyA(hkey, "");
2997     RegCloseKey(hkey);
2998
2999     /* PublishFeatures, machine */
3000     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1 ALLUSERS=1");
3001     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3002     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3003     ok(delete_pf("msitest", FALSE), "File not installed\n");
3004
3005     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, featkey, &hkey);
3006     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3007
3008     res = RegOpenKeyA(HKEY_CURRENT_USER, cupath, &hkey);
3009     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3010
3011     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, classfeat, &hkey);
3012     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3013
3014     CHECK_REG_STR(hkey, "feature", "");
3015     CHECK_REG_STR(hkey, "montecristo", "");
3016
3017     RegDeleteValueA(hkey, "feature");
3018     RegDeleteValueA(hkey, "montecristo");
3019     RegDeleteKeyA(hkey, "");
3020     RegCloseKey(hkey);
3021
3022     sprintf(keypath, udpath, "S-1-5-18");
3023     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
3024     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3025
3026     CHECK_REG_STR(hkey, "feature", "VGtfp^p+,?82@JU1j_KE");
3027     CHECK_REG_STR(hkey, "montecristo", "VGtfp^p+,?82@JU1j_KE");
3028
3029     RegDeleteValueA(hkey, "feature");
3030     RegDeleteValueA(hkey, "montecristo");
3031     RegDeleteKeyA(hkey, "");
3032     RegCloseKey(hkey);
3033
3034     DeleteFile(msifile);
3035     DeleteFile("msitest\\maximus");
3036     RemoveDirectory("msitest");
3037     HeapFree(GetProcessHeap(), 0, usersid);
3038 }
3039
3040 static LPSTR reg_get_val_str(HKEY hkey, LPCSTR name)
3041 {
3042     DWORD len = 0;
3043     LPSTR val;
3044     LONG r;
3045
3046     r = RegQueryValueExA(hkey, name, NULL, NULL, NULL, &len);
3047     if (r != ERROR_SUCCESS)
3048         return NULL;
3049
3050     len += sizeof (WCHAR);
3051     val = HeapAlloc(GetProcessHeap(), 0, len);
3052     if (!val) return NULL;
3053     val[0] = 0;
3054     RegQueryValueExA(hkey, name, NULL, NULL, (LPBYTE)val, &len);
3055     return val;
3056 }
3057
3058 static void get_owner_company(LPSTR *owner, LPSTR *company)
3059 {
3060     LONG res;
3061     HKEY hkey;
3062
3063     *owner = *company = NULL;
3064
3065     res = RegOpenKeyA(HKEY_CURRENT_USER,
3066                       "Software\\Microsoft\\MS Setup (ACME)\\User Info", &hkey);
3067     if (res == ERROR_SUCCESS)
3068     {
3069         *owner = reg_get_val_str(hkey, "DefName");
3070         *company = reg_get_val_str(hkey, "DefCompany");
3071         RegCloseKey(hkey);
3072     }
3073
3074     if (!*owner || !*company)
3075     {
3076         res = RegOpenKeyA(HKEY_LOCAL_MACHINE,
3077                           "Software\\Microsoft\\Windows\\CurrentVersion", &hkey);
3078         if (res == ERROR_SUCCESS)
3079         {
3080             *owner = reg_get_val_str(hkey, "RegisteredOwner");
3081             *company = reg_get_val_str(hkey, "RegisteredOrganization");
3082             RegCloseKey(hkey);
3083         }
3084     }
3085
3086     if (!*owner || !*company)
3087     {
3088         res = RegOpenKeyA(HKEY_LOCAL_MACHINE,
3089                           "Software\\Microsoft\\Windows NT\\CurrentVersion", &hkey);
3090         if (res == ERROR_SUCCESS)
3091         {
3092             *owner = reg_get_val_str(hkey, "RegisteredOwner");
3093             *company = reg_get_val_str(hkey, "RegisteredOrganization");
3094             RegCloseKey(hkey);
3095         }
3096     }
3097 }
3098
3099 static void test_publish_registeruser(void)
3100 {
3101     UINT r;
3102     LONG res;
3103     HKEY props;
3104     LPSTR usersid;
3105     LPSTR owner, company;
3106     CHAR keypath[MAX_PATH];
3107
3108     static const CHAR keyfmt[] =
3109         "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\"
3110         "UserData\\%s\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties";
3111
3112     if (!get_user_sid(&usersid))
3113         return;
3114
3115     get_owner_company(&owner, &company);
3116
3117     CreateDirectoryA("msitest", NULL);
3118     create_file("msitest\\maximus", 500);
3119
3120     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
3121
3122     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3123
3124     /* RegisterUser, per-user */
3125     r = MsiInstallProductA(msifile, "REGISTER_USER=1");
3126     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3127     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3128     ok(delete_pf("msitest", FALSE), "File not installed\n");
3129
3130     sprintf(keypath, keyfmt, usersid);
3131
3132     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
3133     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3134
3135     CHECK_REG_STR(props, "ProductID", "none");
3136     CHECK_REG_STR(props, "RegCompany", company);
3137     CHECK_REG_STR(props, "RegOwner", owner);
3138
3139     RegDeleteValueA(props, "ProductID");
3140     RegDeleteValueA(props, "RegCompany");
3141     RegDeleteValueA(props, "RegOwner");
3142     RegDeleteKeyA(props, "");
3143     RegCloseKey(props);
3144
3145     /* RegisterUser, machine */
3146     r = MsiInstallProductA(msifile, "REGISTER_USER=1 ALLUSERS=1");
3147     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3148     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3149     ok(delete_pf("msitest", FALSE), "File not installed\n");
3150
3151     sprintf(keypath, keyfmt, "S-1-5-18");
3152
3153     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
3154     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3155
3156     CHECK_REG_STR(props, "ProductID", "none");
3157     CHECK_REG_STR(props, "RegCompany", company);
3158     CHECK_REG_STR(props, "RegOwner", owner);
3159
3160     RegDeleteValueA(props, "ProductID");
3161     RegDeleteValueA(props, "RegCompany");
3162     RegDeleteValueA(props, "RegOwner");
3163     RegDeleteKeyA(props, "");
3164     RegCloseKey(props);
3165
3166     HeapFree(GetProcessHeap(), 0, company);
3167     HeapFree(GetProcessHeap(), 0, owner);
3168
3169     DeleteFile(msifile);
3170     DeleteFile("msitest\\maximus");
3171     RemoveDirectory("msitest");
3172 }
3173
3174 static void test_publish_processcomponents(void)
3175 {
3176     UINT r;
3177     LONG res;
3178     DWORD size;
3179     HKEY comp, hkey;
3180     LPSTR usersid;
3181     CHAR val[MAX_PATH];
3182     CHAR keypath[MAX_PATH];
3183     CHAR program_files_maximus[MAX_PATH];
3184
3185     static const CHAR keyfmt[] =
3186         "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\"
3187         "UserData\\%s\\Components\\%s";
3188     static const CHAR compkey[] =
3189         "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Components";
3190
3191     if (!get_user_sid(&usersid))
3192         return;
3193
3194     CreateDirectoryA("msitest", NULL);
3195     create_file("msitest\\maximus", 500);
3196
3197     create_database(msifile, ppc_tables, sizeof(ppc_tables) / sizeof(msi_table));
3198
3199     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3200
3201     /* ProcessComponents, per-user */
3202     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
3203     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3204     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3205     ok(delete_pf("msitest", FALSE), "File not installed\n");
3206
3207     sprintf(keypath, keyfmt, usersid, "CBABC2FDCCB35E749A8944D8C1C098B5");
3208
3209     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
3210     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3211
3212     size = MAX_PATH;
3213     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
3214                            NULL, NULL, (LPBYTE)val, &size);
3215     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3216
3217     lstrcpyA(program_files_maximus,PROG_FILES_DIR);
3218     lstrcatA(program_files_maximus,"\\msitest\\maximus");
3219
3220     ok(!lstrcmpiA(val, program_files_maximus),
3221        "Expected \"%s\", got \"%s\"\n", program_files_maximus, val);
3222
3223     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
3224     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3225
3226     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
3227     RegDeleteKeyA(comp, "");
3228     RegCloseKey(comp);
3229
3230     sprintf(keypath, keyfmt, usersid, "241C3DA58FECD0945B9687D408766058");
3231
3232     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
3233     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3234
3235     size = MAX_PATH;
3236     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
3237                            NULL, NULL, (LPBYTE)val, &size);
3238     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3239     ok(!lstrcmpA(val, "01\\msitest\\augustus"),
3240        "Expected \"01\\msitest\\augustus\", got \"%s\"\n", val);
3241
3242     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
3243     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3244
3245     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
3246     RegDeleteKeyA(comp, "");
3247     RegCloseKey(comp);
3248
3249     /* ProcessComponents, machine */
3250     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1 ALLUSERS=1");
3251     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3252     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3253     ok(delete_pf("msitest", FALSE), "File not installed\n");
3254
3255     sprintf(keypath, keyfmt, "S-1-5-18", "CBABC2FDCCB35E749A8944D8C1C098B5");
3256
3257     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
3258     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3259
3260     size = MAX_PATH;
3261     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
3262                            NULL, NULL, (LPBYTE)val, &size);
3263     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3264     ok(!lstrcmpiA(val, program_files_maximus),
3265        "Expected \"%s\", got \"%s\"\n", program_files_maximus, val);
3266
3267     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
3268     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3269
3270     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
3271     RegDeleteKeyA(comp, "");
3272     RegCloseKey(comp);
3273
3274     sprintf(keypath, keyfmt, "S-1-5-18", "241C3DA58FECD0945B9687D408766058");
3275
3276     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
3277     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3278
3279     size = MAX_PATH;
3280     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
3281                            NULL, NULL, (LPBYTE)val, &size);
3282     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3283     ok(!lstrcmpA(val, "01\\msitest\\augustus"),
3284        "Expected \"01\\msitest\\augustus\", got \"%s\"\n", val);
3285
3286     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
3287     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3288
3289     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
3290     RegDeleteKeyA(comp, "");
3291     RegCloseKey(comp);
3292
3293     DeleteFile(msifile);
3294     DeleteFile("msitest\\maximus");
3295     RemoveDirectory("msitest");
3296 }
3297
3298 static void test_publish(void)
3299 {
3300     UINT r;
3301     LONG res;
3302     HKEY uninstall, prodkey;
3303     INSTALLSTATE state;
3304     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
3305     char date[MAX_PATH];
3306     char temp[MAX_PATH];
3307
3308     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
3309
3310     if (!pMsiQueryComponentStateA)
3311     {
3312         win_skip("MsiQueryComponentStateA is not available\n");
3313         return;
3314     }
3315
3316     get_date_str(date);
3317     GetTempPath(MAX_PATH, temp);
3318
3319     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
3320     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
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     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3330     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3331
3332     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3333     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3334
3335     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3336     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3337
3338     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3339                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3340     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3341     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3342
3343     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3344     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3345
3346     /* nothing published */
3347     r = MsiInstallProductA(msifile, NULL);
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     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3353     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3354
3355     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3356     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3357
3358     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3359     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3360
3361     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3362                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3363     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3364     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3365
3366     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3367     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3368
3369     /* PublishProduct and RegisterProduct */
3370     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1");
3371     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3372     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3373     ok(pf_exists("msitest"), "File not installed\n");
3374
3375     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3376     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3377
3378     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3379     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3380
3381     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3382     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3383
3384     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3385                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3386     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3387     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3388
3389     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3390     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3391
3392     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3393     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3394     CHECK_REG_STR(prodkey, "InstallDate", date);
3395     CHECK_REG_STR(prodkey, "InstallSource", temp);
3396     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3397     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3398     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3399     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3400     CHECK_REG_STR(prodkey, "Comments", NULL);
3401     CHECK_REG_STR(prodkey, "Contact", NULL);
3402     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3403     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3404     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3405     CHECK_REG_STR(prodkey, "Readme", NULL);
3406     CHECK_REG_STR(prodkey, "Size", NULL);
3407     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3408     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3409     CHECK_REG_DWORD(prodkey, "Language", 1033);
3410     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3411     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3412     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3413     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3414     todo_wine
3415     {
3416         CHECK_REG_DWORD2(prodkey, "EstimatedSize", 12, -12);
3417     }
3418
3419     RegCloseKey(prodkey);
3420
3421     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3423     ok(pf_exists("msitest\\maximus"), "File deleted\n");
3424     ok(pf_exists("msitest"), "File deleted\n");
3425
3426     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3427     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3428
3429     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3430     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3431
3432     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3433     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3434
3435     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3436                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3437     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3438     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3439
3440     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3441     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3442
3443     /* complete install */
3444     r = MsiInstallProductA(msifile, "FULL=1");
3445     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3446     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3447     ok(pf_exists("msitest"), "File not installed\n");
3448
3449     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3450     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3451
3452     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3453     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3454
3455     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3456     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3457
3458     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3459                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3461     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3462
3463     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3464     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3465
3466     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3467     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3468     CHECK_REG_STR(prodkey, "InstallDate", date);
3469     CHECK_REG_STR(prodkey, "InstallSource", temp);
3470     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3471     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3472     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3473     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3474     CHECK_REG_STR(prodkey, "Comments", NULL);
3475     CHECK_REG_STR(prodkey, "Contact", NULL);
3476     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3477     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3478     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3479     CHECK_REG_STR(prodkey, "Readme", NULL);
3480     CHECK_REG_STR(prodkey, "Size", NULL);
3481     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3482     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3483     CHECK_REG_DWORD(prodkey, "Language", 1033);
3484     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3485     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3486     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3487     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3488     todo_wine
3489     {
3490         CHECK_REG_DWORD2(prodkey, "EstimatedSize", 12, -12);
3491     }
3492
3493     RegCloseKey(prodkey);
3494
3495     /* no UnpublishFeatures */
3496     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3497     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3498     ok(!pf_exists("msitest\\maximus"), "File deleted\n");
3499     todo_wine
3500     {
3501         ok(!pf_exists("msitest"), "File deleted\n");
3502     }
3503
3504     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3505     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3506
3507     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3508     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3509
3510     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3511     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3512
3513     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3514                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3515     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3516     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3517
3518     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3519     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3520
3521     /* complete install */
3522     r = MsiInstallProductA(msifile, "FULL=1");
3523     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3524     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3525     ok(pf_exists("msitest"), "File not installed\n");
3526
3527     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3528     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3529
3530     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3531     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3532
3533     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3534     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3535
3536     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3537                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3538     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3539     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3540
3541     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3542     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3543
3544     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3545     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3546     CHECK_REG_STR(prodkey, "InstallDate", date);
3547     CHECK_REG_STR(prodkey, "InstallSource", temp);
3548     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3549     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3550     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3551     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3552     CHECK_REG_STR(prodkey, "Comments", NULL);
3553     CHECK_REG_STR(prodkey, "Contact", NULL);
3554     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3555     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3556     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3557     CHECK_REG_STR(prodkey, "Readme", NULL);
3558     CHECK_REG_STR(prodkey, "Size", NULL);
3559     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3560     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3561     CHECK_REG_DWORD(prodkey, "Language", 1033);
3562     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3563     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3564     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3565     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3566     todo_wine
3567     {
3568         CHECK_REG_DWORD2(prodkey, "EstimatedSize", 12, -12);
3569     }
3570
3571     RegCloseKey(prodkey);
3572
3573     /* UnpublishFeatures, only feature removed.  Only works when entire product is removed */
3574     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature");
3575     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3576     todo_wine ok(pf_exists("msitest\\maximus"), "File deleted\n");
3577     ok(pf_exists("msitest"), "File deleted\n");
3578
3579     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3580     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3581
3582     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3583     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3584
3585     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3586     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3587
3588     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3589                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3590     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3591     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3592
3593     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3594     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3595
3596     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3597     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3598     CHECK_REG_STR(prodkey, "InstallDate", date);
3599     CHECK_REG_STR(prodkey, "InstallSource", temp);
3600     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3601     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3602     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3603     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3604     CHECK_REG_STR(prodkey, "Comments", NULL);
3605     CHECK_REG_STR(prodkey, "Contact", NULL);
3606     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3607     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3608     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3609     CHECK_REG_STR(prodkey, "Readme", NULL);
3610     CHECK_REG_STR(prodkey, "Size", NULL);
3611     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3612     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3613     CHECK_REG_DWORD(prodkey, "Language", 1033);
3614     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3615     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3616     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3617     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3618     todo_wine
3619     {
3620         CHECK_REG_DWORD2(prodkey, "EstimatedSize", 12, -12);
3621     }
3622
3623     RegCloseKey(prodkey);
3624
3625     /* complete install */
3626     r = MsiInstallProductA(msifile, "FULL=1");
3627     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3628     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3629     ok(pf_exists("msitest"), "File not installed\n");
3630
3631     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3632     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3633
3634     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3635     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3636
3637     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3638     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3639
3640     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3641                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3642     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3643     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3644
3645     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3646     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3647
3648     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3649     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3650     CHECK_REG_STR(prodkey, "InstallDate", date);
3651     CHECK_REG_STR(prodkey, "InstallSource", temp);
3652     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3653     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3654     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3655     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3656     CHECK_REG_STR(prodkey, "Comments", NULL);
3657     CHECK_REG_STR(prodkey, "Contact", NULL);
3658     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3659     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3660     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3661     CHECK_REG_STR(prodkey, "Readme", NULL);
3662     CHECK_REG_STR(prodkey, "Size", NULL);
3663     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3664     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3665     CHECK_REG_DWORD(prodkey, "Language", 1033);
3666     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3667     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3668     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3669     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3670     todo_wine
3671     {
3672         CHECK_REG_DWORD2(prodkey, "EstimatedSize", 12, -20);
3673     }
3674
3675     RegCloseKey(prodkey);
3676
3677     /* UnpublishFeatures, both features removed */
3678     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature,montecristo");
3679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3680     ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3681     todo_wine
3682     {
3683         ok(!pf_exists("msitest"), "File not deleted\n");
3684     }
3685
3686     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3687     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3688
3689     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3690     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3691
3692     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3693     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3694
3695     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3696                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3697     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3698     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3699
3700     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3701     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3702
3703     /* complete install */
3704     r = MsiInstallProductA(msifile, "FULL=1");
3705     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3706     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3707     ok(pf_exists("msitest"), "File not installed\n");
3708
3709     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3710     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3711
3712     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3713     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3714
3715     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3716     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3717
3718     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3719                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3720     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3721     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3722
3723     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3724     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3725
3726     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3727     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3728     CHECK_REG_STR(prodkey, "InstallDate", date);
3729     CHECK_REG_STR(prodkey, "InstallSource", temp);
3730     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3731     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3732     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3733     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3734     CHECK_REG_STR(prodkey, "Comments", NULL);
3735     CHECK_REG_STR(prodkey, "Contact", NULL);
3736     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3737     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3738     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3739     CHECK_REG_STR(prodkey, "Readme", NULL);
3740     CHECK_REG_STR(prodkey, "Size", NULL);
3741     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3742     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3743     CHECK_REG_DWORD(prodkey, "Language", 1033);
3744     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3745     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3746     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3747     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3748     todo_wine
3749     {
3750         CHECK_REG_DWORD2(prodkey, "EstimatedSize", 12, -12);
3751     }
3752
3753     RegCloseKey(prodkey);
3754
3755     /* complete uninstall */
3756     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3757     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3758     ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3759     todo_wine
3760     {
3761         ok(!pf_exists("msitest"), "File not deleted\n");
3762     }
3763
3764     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3765     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3766
3767     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3768     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3769
3770     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3771     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3772
3773     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3774                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3775     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3776     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3777
3778     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3779     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3780
3781     /* make sure 'Program Files\msitest' is removed */
3782     delete_pfmsitest_files();
3783
3784     RegCloseKey(uninstall);
3785     DeleteFile(msifile);
3786     DeleteFile("msitest\\maximus");
3787     RemoveDirectory("msitest");
3788 }
3789
3790 static void test_publishsourcelist(void)
3791 {
3792     UINT r;
3793     DWORD size;
3794     CHAR value[MAX_PATH];
3795     CHAR path[MAX_PATH];
3796     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
3797
3798     if (!pMsiSourceListEnumSourcesA || !pMsiSourceListGetInfoA)
3799     {
3800         win_skip("MsiSourceListEnumSourcesA and/or MsiSourceListGetInfoA are not available\n");
3801         return;
3802     }
3803
3804     CreateDirectoryA("msitest", NULL);
3805     create_file("msitest\\maximus", 500);
3806
3807     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
3808
3809     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3810
3811     r = MsiInstallProductA(msifile, NULL);
3812     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3813     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3814     ok(pf_exists("msitest"), "File not installed\n");
3815
3816     /* nothing published */
3817     size = MAX_PATH;
3818     lstrcpyA(value, "aaa");
3819     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3820                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
3821     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3822     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
3823     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
3824
3825     size = MAX_PATH;
3826     lstrcpyA(value, "aaa");
3827     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3828                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
3829     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3830     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
3831     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
3832
3833     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
3834     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3835     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3836     ok(pf_exists("msitest"), "File not installed\n");
3837
3838     /* after RegisterProduct */
3839     size = MAX_PATH;
3840     lstrcpyA(value, "aaa");
3841     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3842                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
3843     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3844     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
3845     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
3846
3847     size = MAX_PATH;
3848     lstrcpyA(value, "aaa");
3849     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3850                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
3851     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3852     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
3853     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
3854
3855     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
3856     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3857     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3858     ok(pf_exists("msitest"), "File not installed\n");
3859
3860     /* after ProcessComponents */
3861     size = MAX_PATH;
3862     lstrcpyA(value, "aaa");
3863     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3864                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
3865     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3866     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
3867     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
3868
3869     size = MAX_PATH;
3870     lstrcpyA(value, "aaa");
3871     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3872                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
3873     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3874     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
3875     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
3876
3877     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
3878     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3879     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3880     ok(pf_exists("msitest"), "File not installed\n");
3881
3882     /* after PublishFeatures */
3883     size = MAX_PATH;
3884     lstrcpyA(value, "aaa");
3885     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3886                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
3887     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3888     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
3889     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
3890
3891     size = MAX_PATH;
3892     lstrcpyA(value, "aaa");
3893     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3894                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
3895     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3896     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
3897     ok(!lstrcmpA(value, "aaa"), "Expected \"aaa\", got \"%s\"\n", value);
3898
3899     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
3900     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3901     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3902     ok(pf_exists("msitest"), "File not installed\n");
3903
3904     /* after PublishProduct */
3905     size = MAX_PATH;
3906     lstrcpyA(value, "aaa");
3907     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3908                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
3909     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3910     ok(!lstrcmpA(value, "msitest.msi"), "Expected 'msitest.msi', got %s\n", value);
3911     ok(size == 11, "Expected 11, got %d\n", size);
3912
3913     size = MAX_PATH;
3914     lstrcpyA(value, "aaa");
3915     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3916                                MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATH, value, &size);
3917     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3918     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
3919     ok(size == 0, "Expected 0, got %d\n", size);
3920
3921     size = MAX_PATH;
3922     lstrcpyA(value, "aaa");
3923     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3924                                MSICODE_PRODUCT, INSTALLPROPERTY_DISKPROMPT, value, &size);
3925     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3926     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
3927     ok(size == 0, "Expected 0, got %d\n", size);
3928
3929     lstrcpyA(path, CURR_DIR);
3930     lstrcatA(path, "\\");
3931
3932     size = MAX_PATH;
3933     lstrcpyA(value, "aaa");
3934     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3935                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size);
3936     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3937     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3938     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3939
3940     size = MAX_PATH;
3941     lstrcpyA(value, "aaa");
3942     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3943                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE, value, &size);
3944     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3945     ok(!lstrcmpA(value, "n"), "Expected \"n\", got \"%s\"\n", value);
3946     ok(size == 1, "Expected 1, got %d\n", size);
3947
3948     size = MAX_PATH;
3949     lstrcpyA(value, "aaa");
3950     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3951                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
3952     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3953     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
3954     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
3955
3956     size = MAX_PATH;
3957     lstrcpyA(value, "aaa");
3958     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3959                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
3960     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3961     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3962     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3963
3964     size = MAX_PATH;
3965     lstrcpyA(value, "aaa");
3966     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3967                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 1, value, &size);
3968     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3969     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
3970     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
3971
3972     /* complete uninstall */
3973     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3974     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3975     ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3976     todo_wine
3977     {
3978         ok(!pf_exists("msitest"), "File not deleted\n");
3979     }
3980
3981     /* make sure 'Program Files\msitest' is removed */
3982     delete_pfmsitest_files();
3983
3984     DeleteFile(msifile);
3985     DeleteFile("msitest\\maximus");
3986     RemoveDirectory("msitest");
3987 }
3988
3989 static UINT run_query(MSIHANDLE hdb, MSIHANDLE hrec, const char *query)
3990 {
3991     MSIHANDLE hview = 0;
3992     UINT r;
3993
3994     r = MsiDatabaseOpenView(hdb, query, &hview);
3995     if(r != ERROR_SUCCESS)
3996         return r;
3997
3998     r = MsiViewExecute(hview, hrec);
3999     if(r == ERROR_SUCCESS)
4000         r = MsiViewClose(hview);
4001     MsiCloseHandle(hview);
4002     return r;
4003 }
4004
4005 static void set_transform_summary_info(void)
4006 {
4007     UINT r;
4008     MSIHANDLE suminfo = 0;
4009
4010     /* build summary info */
4011     r = MsiGetSummaryInformation(0, mstfile, 3, &suminfo);
4012     todo_wine
4013     {
4014         ok(r == ERROR_SUCCESS , "Failed to open summaryinfo\n");
4015     }
4016
4017     r = MsiSummaryInfoSetProperty(suminfo, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
4018     todo_wine
4019     {
4020         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
4021     }
4022
4023     r = MsiSummaryInfoSetProperty(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
4024                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
4025                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
4026                         "{4C0EAA15-0264-4E5A-8758-609EF142B92D}");
4027     todo_wine
4028     {
4029         ok(r == ERROR_SUCCESS , "Failed to set summary info\n");
4030     }
4031
4032     r = MsiSummaryInfoSetProperty(suminfo, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
4033     todo_wine
4034     {
4035         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
4036     }
4037
4038     r = MsiSummaryInfoPersist(suminfo);
4039     todo_wine
4040     {
4041         ok(r == ERROR_SUCCESS , "Failed to make summary info persist\n");
4042     }
4043
4044     r = MsiCloseHandle(suminfo);
4045     ok(r == ERROR_SUCCESS , "Failed to close suminfo\n");
4046 }
4047
4048 static void generate_transform(void)
4049 {
4050     MSIHANDLE hdb1, hdb2;
4051     LPCSTR query;
4052     UINT r;
4053
4054     /* start with two identical databases */
4055     CopyFile(msifile, msifile2, FALSE);
4056
4057     r = MsiOpenDatabase(msifile2, MSIDBOPEN_TRANSACT, &hdb1);
4058     ok(r == ERROR_SUCCESS , "Failed to create database\n");
4059
4060     r = MsiDatabaseCommit(hdb1);
4061     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
4062
4063     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb2);
4064     ok(r == ERROR_SUCCESS , "Failed to create database\n");
4065
4066     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
4067     r = run_query(hdb1, 0, query);
4068     ok(r == ERROR_SUCCESS, "failed to add property\n");
4069
4070     /* database needs to be committed */
4071     MsiDatabaseCommit(hdb1);
4072
4073     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
4074     ok(r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r);
4075
4076 #if 0  /* not implemented in wine yet */
4077     r = MsiCreateTransformSummaryInfo(hdb2, hdb2, mstfile, 0, 0);
4078     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4079 #endif
4080
4081     MsiCloseHandle(hdb1);
4082     MsiCloseHandle(hdb2);
4083 }
4084
4085 /* data for generating a transform */
4086
4087 /* tables transform names - encoded as they would be in an msi database file */
4088 static const WCHAR name1[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
4089 static const WCHAR name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
4090 static const WCHAR name3[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
4091
4092 /* data in each table */
4093 static const char data1[] = /* _StringData */
4094     "propval";  /* all the strings squashed together */
4095
4096 static const WCHAR data2[] = { /* _StringPool */
4097 /*  len, refs */
4098     0,   0,    /* string 0 ''     */
4099     4,   1,    /* string 1 'prop' */
4100     3,   1,    /* string 2 'val'  */
4101 };
4102
4103 static const WCHAR data3[] = { /* Property */
4104     0x0201, 0x0001, 0x0002,
4105 };
4106
4107 static const struct {
4108     LPCWSTR name;
4109     const void *data;
4110     DWORD size;
4111 } table_transform_data[] =
4112 {
4113     { name1, data1, sizeof data1 - 1 },
4114     { name2, data2, sizeof data2 },
4115     { name3, data3, sizeof data3 },
4116 };
4117
4118 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
4119
4120 static void generate_transform_manual(void)
4121 {
4122     IStorage *stg = NULL;
4123     IStream *stm;
4124     WCHAR name[0x20];
4125     HRESULT r;
4126     DWORD i, count;
4127     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
4128
4129     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
4130
4131     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
4132
4133     r = StgCreateDocfile(name, mode, 0, &stg);
4134     ok(r == S_OK, "failed to create storage\n");
4135     if (!stg)
4136         return;
4137
4138     r = IStorage_SetClass(stg, &CLSID_MsiTransform);
4139     ok(r == S_OK, "failed to set storage type\n");
4140
4141     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
4142     {
4143         r = IStorage_CreateStream(stg, table_transform_data[i].name,
4144                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
4145         if (FAILED(r))
4146         {
4147             ok(0, "failed to create stream %08x\n", r);
4148             continue;
4149         }
4150
4151         r = IStream_Write(stm, table_transform_data[i].data,
4152                           table_transform_data[i].size, &count);
4153         if (FAILED(r) || count != table_transform_data[i].size)
4154             ok(0, "failed to write stream\n");
4155         IStream_Release(stm);
4156     }
4157
4158     IStorage_Release(stg);
4159
4160     set_transform_summary_info();
4161 }
4162
4163 static void test_transformprop(void)
4164 {
4165     UINT r;
4166
4167     CreateDirectoryA("msitest", NULL);
4168     create_file("msitest\\augustus", 500);
4169
4170     create_database(msifile, tp_tables, sizeof(tp_tables) / sizeof(msi_table));
4171
4172     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4173
4174     r = MsiInstallProductA(msifile, NULL);
4175     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4176     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4177     ok(!delete_pf("msitest", FALSE), "File installed\n");
4178
4179     if (0)
4180         generate_transform();
4181     else
4182         generate_transform_manual();
4183
4184     r = MsiInstallProductA(msifile, "TRANSFORMS=winetest.mst");
4185     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4186     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4187     ok(delete_pf("msitest", FALSE), "File not installed\n");
4188
4189     /* Delete the files in the temp (current) folder */
4190     DeleteFile(msifile);
4191     DeleteFile(msifile2);
4192     DeleteFile(mstfile);
4193     DeleteFile("msitest\\augustus");
4194     RemoveDirectory("msitest");
4195 }
4196
4197 static void test_currentworkingdir(void)
4198 {
4199     UINT r;
4200     CHAR drive[MAX_PATH], path[MAX_PATH];
4201     LPSTR ptr;
4202
4203     CreateDirectoryA("msitest", NULL);
4204     create_file("msitest\\augustus", 500);
4205
4206     create_database(msifile, cwd_tables, sizeof(cwd_tables) / sizeof(msi_table));
4207
4208     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4209
4210     CreateDirectoryA("diffdir", NULL);
4211     SetCurrentDirectoryA("diffdir");
4212
4213     sprintf(path, "..\\%s", msifile);
4214     r = MsiInstallProductA(path, NULL);
4215     todo_wine
4216     {
4217         ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
4218         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4219         ok(!delete_pf("msitest", FALSE), "File installed\n");
4220     }
4221
4222     sprintf(path, "%s\\%s", CURR_DIR, msifile);
4223     r = MsiInstallProductA(path, NULL);
4224     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4225     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4226     ok(delete_pf("msitest", FALSE), "File not installed\n");
4227
4228     lstrcpyA(drive, CURR_DIR);
4229     drive[2] = '\\';
4230     drive[3] = '\0';
4231     SetCurrentDirectoryA(drive);
4232
4233     lstrcpy(path, CURR_DIR);
4234     if (path[lstrlenA(path) - 1] != '\\')
4235         lstrcatA(path, "\\");
4236     lstrcatA(path, msifile);
4237     ptr = strchr(path, ':');
4238     ptr +=2;
4239
4240     r = MsiInstallProductA(ptr, NULL);
4241     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4242     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4243     ok(delete_pf("msitest", FALSE), "File not installed\n");
4244
4245     SetCurrentDirectoryA(CURR_DIR);
4246
4247     DeleteFile(msifile);
4248     DeleteFile("msitest\\augustus");
4249     RemoveDirectory("msitest");
4250     RemoveDirectory("diffdir");
4251 }
4252
4253 static void set_admin_summary_info(const CHAR *name)
4254 {
4255     MSIHANDLE db, summary;
4256     UINT r;
4257
4258     r = MsiOpenDatabaseA(name, MSIDBOPEN_DIRECT, &db);
4259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4260
4261     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
4262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4263
4264     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 5, NULL, NULL);
4265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4266
4267     /* write the summary changes back to the stream */
4268     r = MsiSummaryInfoPersist(summary);
4269     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4270
4271     MsiCloseHandle(summary);
4272
4273     r = MsiDatabaseCommit(db);
4274     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4275
4276     MsiCloseHandle(db);
4277 }
4278
4279 static void test_admin(void)
4280 {
4281     UINT r;
4282
4283     CreateDirectoryA("msitest", NULL);
4284     create_file("msitest\\augustus", 500);
4285
4286     create_database(msifile, adm_tables, sizeof(adm_tables) / sizeof(msi_table));
4287     set_admin_summary_info(msifile);
4288
4289     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4290
4291     r = MsiInstallProductA(msifile, NULL);
4292     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4293     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4294     ok(!delete_pf("msitest", FALSE), "File installed\n");
4295     ok(!DeleteFile("c:\\msitest\\augustus"), "File installed\n");
4296     ok(!RemoveDirectory("c:\\msitest"), "File installed\n");
4297
4298     r = MsiInstallProductA(msifile, "ACTION=ADMIN");
4299     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4300     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4301     ok(!delete_pf("msitest", FALSE), "File installed\n");
4302     todo_wine
4303     {
4304         ok(DeleteFile("c:\\msitest\\augustus"), "File not installed\n");
4305         ok(RemoveDirectory("c:\\msitest"), "File not installed\n");
4306     }
4307
4308     DeleteFile(msifile);
4309     DeleteFile("msitest\\augustus");
4310     RemoveDirectory("msitest");
4311 }
4312
4313 static void set_admin_property_stream(LPCSTR file)
4314 {
4315     IStorage *stg;
4316     IStream *stm;
4317     WCHAR fileW[MAX_PATH];
4318     HRESULT hr;
4319     DWORD count;
4320     const DWORD mode = STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
4321
4322     /* AdminProperties */
4323     static const WCHAR stmname[] = {0x41ca,0x4330,0x3e71,0x44b5,0x4233,0x45f5,0x422c,0x4836,0};
4324     static const WCHAR data[] = {'M','Y','P','R','O','P','=','2','7','1','8',' ',
4325         'M','y','P','r','o','p','=','4','2',0};
4326
4327     MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH);
4328
4329     hr = StgOpenStorage(fileW, NULL, mode, NULL, 0, &stg);
4330     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
4331     if (!stg)
4332         return;
4333
4334     hr = IStorage_CreateStream(stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
4335     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
4336
4337     hr = IStream_Write(stm, data, sizeof(data), &count);
4338     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
4339
4340     IStream_Release(stm);
4341     IStorage_Release(stg);
4342 }
4343
4344 static void test_adminprops(void)
4345 {
4346     UINT r;
4347
4348     CreateDirectoryA("msitest", NULL);
4349     create_file("msitest\\augustus", 500);
4350
4351     create_database(msifile, amp_tables, sizeof(amp_tables) / sizeof(msi_table));
4352     set_admin_summary_info(msifile);
4353     set_admin_property_stream(msifile);
4354
4355     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4356
4357     r = MsiInstallProductA(msifile, NULL);
4358     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4359     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4360     ok(delete_pf("msitest", FALSE), "File installed\n");
4361
4362     DeleteFile(msifile);
4363     DeleteFile("msitest\\augustus");
4364     RemoveDirectory("msitest");
4365 }
4366
4367 static void create_pf_data(LPCSTR file, LPCSTR data, BOOL is_file)
4368 {
4369     CHAR path[MAX_PATH];
4370
4371     lstrcpyA(path, PROG_FILES_DIR);
4372     lstrcatA(path, "\\");
4373     lstrcatA(path, file);
4374
4375     if (is_file)
4376         create_file_data(path, data, 500);
4377     else
4378         CreateDirectoryA(path, NULL);
4379 }
4380
4381 #define create_pf(file, is_file) create_pf_data(file, file, is_file)
4382
4383 static void test_removefiles(void)
4384 {
4385     UINT r;
4386
4387     CreateDirectoryA("msitest", NULL);
4388     create_file("msitest\\hydrogen", 500);
4389     create_file("msitest\\helium", 500);
4390     create_file("msitest\\lithium", 500);
4391
4392     create_database(msifile, rem_tables, sizeof(rem_tables) / sizeof(msi_table));
4393
4394     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
4395
4396     r = MsiInstallProductA(msifile, NULL);
4397     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4398     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
4399     ok(!pf_exists("msitest\\helium"), "File installed\n");
4400     ok(pf_exists("msitest\\lithium"), "File not installed\n");
4401     ok(pf_exists("msitest"), "File not installed\n");
4402
4403     r = MsiInstallProductA(msifile, "REMOVE=ALL");
4404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4405     ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
4406     ok(!pf_exists("msitest\\helium"), "File not deleted\n");
4407     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
4408     ok(delete_pf("msitest", FALSE), "File deleted\n");
4409
4410     create_pf("msitest", FALSE);
4411     create_pf("msitest\\hydrogen", TRUE);
4412     create_pf("msitest\\helium", TRUE);
4413     create_pf("msitest\\lithium", TRUE);
4414
4415     r = MsiInstallProductA(msifile, NULL);
4416     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4417     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
4418     ok(pf_exists("msitest\\helium"), "File not installed\n");
4419     ok(pf_exists("msitest\\lithium"), "File not installed\n");
4420     ok(pf_exists("msitest"), "File not installed\n");
4421
4422     r = MsiInstallProductA(msifile, "REMOVE=ALL");
4423     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4424     ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
4425     ok(delete_pf("msitest\\helium", TRUE), "File deleted\n");
4426     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
4427     ok(delete_pf("msitest", FALSE), "File deleted\n");
4428
4429     create_pf("msitest", FALSE);
4430     create_pf("msitest\\furlong", TRUE);
4431     create_pf("msitest\\firkin", TRUE);
4432     create_pf("msitest\\fortnight", TRUE);
4433     create_pf("msitest\\becquerel", TRUE);
4434     create_pf("msitest\\dioptre", TRUE);
4435     create_pf("msitest\\attoparsec", TRUE);
4436     create_pf("msitest\\storeys", TRUE);
4437     create_pf("msitest\\block", TRUE);
4438     create_pf("msitest\\siriometer", TRUE);
4439     create_pf("msitest\\cabout", FALSE);
4440     create_pf("msitest\\cabout\\blocker", TRUE);
4441
4442     r = MsiInstallProductA(msifile, NULL);
4443     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4444     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
4445     ok(!pf_exists("msitest\\helium"), "File installed\n");
4446     ok(pf_exists("msitest\\lithium"), "File not installed\n");
4447     ok(!pf_exists("msitest\\furlong"), "File not deleted\n");
4448     ok(!pf_exists("msitest\\firkin"), "File not deleted\n");
4449     ok(!pf_exists("msitest\\fortnight"), "File not deleted\n");
4450     ok(pf_exists("msitest\\becquerel"), "File not installed\n");
4451     ok(pf_exists("msitest\\dioptre"), "File not installed\n");
4452     ok(pf_exists("msitest\\attoparsec"), "File not installed\n");
4453     ok(!pf_exists("msitest\\storeys"), "File not deleted\n");
4454     ok(!pf_exists("msitest\\block"), "File not deleted\n");
4455     ok(!pf_exists("msitest\\siriometer"), "File not deleted\n");
4456     ok(pf_exists("msitest\\cabout"), "Directory removed\n");
4457     ok(pf_exists("msitest"), "File not installed\n");
4458
4459     create_pf("msitest\\furlong", TRUE);
4460     create_pf("msitest\\firkin", TRUE);
4461     create_pf("msitest\\fortnight", TRUE);
4462     create_pf("msitest\\storeys", TRUE);
4463     create_pf("msitest\\block", TRUE);
4464     create_pf("msitest\\siriometer", TRUE);
4465
4466     r = MsiInstallProductA(msifile, "REMOVE=ALL");
4467     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4468     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not deleted\n");
4469     ok(!delete_pf("msitest\\helium", TRUE), "File not deleted\n");
4470     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
4471     ok(delete_pf("msitest\\furlong", TRUE), "File deleted\n");
4472     ok(delete_pf("msitest\\firkin", TRUE), "File deleted\n");
4473     ok(delete_pf("msitest\\fortnight", TRUE), "File deleted\n");
4474     ok(!delete_pf("msitest\\becquerel", TRUE), "File not deleted\n");
4475     ok(!delete_pf("msitest\\dioptre", TRUE), "File not deleted\n");
4476     ok(delete_pf("msitest\\attoparsec", TRUE), "File deleted\n");
4477     ok(!delete_pf("msitest\\storeys", TRUE), "File not deleted\n");
4478     ok(!delete_pf("msitest\\block", TRUE), "File not deleted\n");
4479     ok(delete_pf("msitest\\siriometer", TRUE), "File deleted\n");
4480     ok(pf_exists("msitest\\cabout"), "Directory deleted\n");
4481     ok(pf_exists("msitest"), "Directory deleted\n");
4482
4483     r = MsiInstallProductA(msifile, NULL);
4484     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4485     ok(delete_pf("msitest\\hydrogen", TRUE), "File not installed\n");
4486     ok(!delete_pf("msitest\\helium", TRUE), "File installed\n");
4487     ok(delete_pf("msitest\\lithium", TRUE), "File not installed\n");
4488     ok(pf_exists("msitest\\cabout"), "Directory deleted\n");
4489     ok(pf_exists("msitest"), "Directory deleted\n");
4490
4491     delete_pf("msitest\\cabout\\blocker", TRUE);
4492
4493     r = MsiInstallProductA(msifile, "REMOVE=ALL");
4494     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4495     ok(!delete_pf("msitest\\cabout", FALSE), "Directory not deleted\n");
4496     ok(delete_pf("msitest", FALSE), "Directory deleted\n");
4497
4498     DeleteFile(msifile);
4499     DeleteFile("msitest\\hydrogen");
4500     DeleteFile("msitest\\helium");
4501     DeleteFile("msitest\\lithium");
4502     RemoveDirectory("msitest");
4503 }
4504
4505 static void test_movefiles(void)
4506 {
4507     UINT r;
4508     char props[MAX_PATH];
4509
4510     CreateDirectoryA("msitest", NULL);
4511     create_file("msitest\\augustus", 100);
4512     create_file("cameroon", 100);
4513     create_file("djibouti", 100);
4514     create_file("egypt", 100);
4515     create_file("finland", 100);
4516     create_file("gambai", 100);
4517     create_file("honduras", 100);
4518     create_file("msitest\\india", 100);
4519     create_file("japan", 100);
4520     create_file("kenya", 100);
4521     CreateDirectoryA("latvia", NULL);
4522     create_file("nauru", 100);
4523     create_file("peru", 100);
4524     create_file("apple", 100);
4525     create_file("application", 100);
4526     create_file("ape", 100);
4527     create_file("foo", 100);
4528     create_file("fao", 100);
4529     create_file("fbod", 100);
4530     create_file("budding", 100);
4531     create_file("buddy", 100);
4532     create_file("bud", 100);
4533     create_file("bar", 100);
4534     create_file("bur", 100);
4535     create_file("bird", 100);
4536
4537     create_database(msifile, mov_tables, sizeof(mov_tables) / sizeof(msi_table));
4538
4539     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
4540
4541     /* if the source or dest property is not a full path,
4542      * windows tries to access it as a network resource
4543      */
4544
4545     sprintf(props, "SOURCEFULL=\"%s\\\" DESTFULL=\"%s\\msitest\" "
4546             "FILEPATHBAD=\"%s\\japan\" FILEPATHGOOD=\"%s\\kenya\"",
4547             CURR_DIR, PROG_FILES_DIR, CURR_DIR, CURR_DIR);
4548
4549     r = MsiInstallProductA(msifile, props);
4550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4551     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4552     ok(!delete_pf("msitest\\dest", TRUE), "File copied\n");
4553     ok(delete_pf("msitest\\canada", TRUE), "File not copied\n");
4554     ok(delete_pf("msitest\\dominica", TRUE), "File not moved\n");
4555     ok(!delete_pf("msitest\\elsalvador", TRUE), "File moved\n");
4556     ok(!delete_pf("msitest\\france", TRUE), "File moved\n");
4557     ok(!delete_pf("msitest\\georgia", TRUE), "File moved\n");
4558     ok(delete_pf("msitest\\hungary", TRUE), "File not moved\n");
4559     ok(!delete_pf("msitest\\indonesia", TRUE), "File moved\n");
4560     ok(!delete_pf("msitest\\jordan", TRUE), "File moved\n");
4561     ok(delete_pf("msitest\\kiribati", TRUE), "File not moved\n");
4562     ok(!delete_pf("msitest\\lebanon", TRUE), "File moved\n");
4563     ok(!delete_pf("msitest\\lebanon", FALSE), "Directory moved\n");
4564     ok(delete_pf("msitest\\poland", TRUE), "File not moved\n");
4565     /* either apple or application will be moved depending on directory order */
4566     if (!delete_pf("msitest\\apple", TRUE))
4567         ok(delete_pf("msitest\\application", TRUE), "File not moved\n");
4568     else
4569         ok(!delete_pf("msitest\\application", TRUE), "File should not exist\n");
4570     ok(delete_pf("msitest\\wildcard", TRUE), "File not moved\n");
4571     ok(!delete_pf("msitest\\ape", TRUE), "File moved\n");
4572     /* either fao or foo will be moved depending on directory order */
4573     if (delete_pf("msitest\\foo", TRUE))
4574         ok(!delete_pf("msitest\\fao", TRUE), "File should not exist\n");
4575     else
4576         ok(delete_pf("msitest\\fao", TRUE), "File not moved\n");
4577     ok(delete_pf("msitest\\single", TRUE), "File not moved\n");
4578     ok(!delete_pf("msitest\\fbod", TRUE), "File moved\n");
4579     ok(delete_pf("msitest\\budding", TRUE), "File not moved\n");
4580     ok(delete_pf("msitest\\buddy", TRUE), "File not moved\n");
4581     ok(!delete_pf("msitest\\bud", TRUE), "File moved\n");
4582     ok(delete_pf("msitest\\bar", TRUE), "File not moved\n");
4583     ok(delete_pf("msitest\\bur", TRUE), "File not moved\n");
4584     ok(!delete_pf("msitest\\bird", TRUE), "File moved\n");
4585     ok(delete_pf("msitest", FALSE), "File not installed\n");
4586     ok(DeleteFileA("cameroon"), "File moved\n");
4587     ok(!DeleteFileA("djibouti"), "File not moved\n");
4588     ok(DeleteFileA("egypt"), "File moved\n");
4589     ok(DeleteFileA("finland"), "File moved\n");
4590     ok(DeleteFileA("gambai"), "File moved\n");
4591     ok(!DeleteFileA("honduras"), "File not moved\n");
4592     ok(DeleteFileA("msitest\\india"), "File moved\n");
4593     ok(DeleteFileA("japan"), "File moved\n");
4594     ok(!DeleteFileA("kenya"), "File not moved\n");
4595     ok(RemoveDirectoryA("latvia"), "Directory moved\n");
4596     ok(!DeleteFileA("nauru"), "File not moved\n");
4597     ok(!DeleteFileA("peru"), "File not moved\n");
4598     ok(!DeleteFileA("apple"), "File not moved\n");
4599     ok(!DeleteFileA("application"), "File not moved\n");
4600     ok(DeleteFileA("ape"), "File moved\n");
4601     ok(!DeleteFileA("foo"), "File not moved\n");
4602     ok(!DeleteFileA("fao"), "File not moved\n");
4603     ok(DeleteFileA("fbod"), "File moved\n");
4604     ok(!DeleteFileA("budding"), "File not moved\n");
4605     ok(!DeleteFileA("buddy"), "File not moved\n");
4606     ok(DeleteFileA("bud"), "File moved\n");
4607     ok(!DeleteFileA("bar"), "File not moved\n");
4608     ok(!DeleteFileA("bur"), "File not moved\n");
4609     ok(DeleteFileA("bird"), "File moved\n");
4610
4611     DeleteFile("msitest\\augustus");
4612     RemoveDirectory("msitest");
4613     DeleteFile(msifile);
4614 }
4615
4616 static void test_missingcab(void)
4617 {
4618     UINT r;
4619
4620     CreateDirectoryA("msitest", NULL);
4621     create_file("msitest\\augustus", 500);
4622     create_file("maximus", 500);
4623
4624     create_database(msifile, mc_tables, sizeof(mc_tables) / sizeof(msi_table));
4625
4626     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4627
4628     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
4629
4630     create_pf("msitest", FALSE);
4631     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
4632
4633     r = MsiInstallProductA(msifile, NULL);
4634     ok(r == ERROR_SUCCESS ||
4635        broken(r == ERROR_INSTALL_FAILURE), /* win9x */
4636        "Expected ERROR_SUCCESS, got %u\n", r);
4637     if (r == ERROR_SUCCESS)
4638     {
4639       ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4640       ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4641     }
4642     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
4643     ok(!delete_pf("msitest\\gaius", TRUE), "File installed\n");
4644     ok(delete_pf("msitest", FALSE), "File not installed\n");
4645
4646     create_pf("msitest", FALSE);
4647     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
4648     create_pf("msitest\\gaius", TRUE);
4649
4650     r = MsiInstallProductA(msifile, "GAIUS=1");
4651     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4652     todo_wine
4653     {
4654         ok(!delete_pf("msitest\\maximus", TRUE), "File installed\n");
4655         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4656     }
4657     ok(delete_pf("msitest\\caesar", TRUE), "File removed\n");
4658     ok(delete_pf("msitest\\gaius", TRUE), "File removed\n");
4659     ok(delete_pf("msitest", FALSE), "File not installed\n");
4660
4661     DeleteFile("msitest\\augustus");
4662     RemoveDirectory("msitest");
4663     DeleteFile("maximus");
4664     DeleteFile("test1.cab");
4665     DeleteFile(msifile);
4666 }
4667
4668 static void test_duplicatefiles(void)
4669 {
4670     UINT r;
4671
4672     CreateDirectoryA("msitest", NULL);
4673     create_file("msitest\\maximus", 500);
4674     create_database(msifile, df_tables, sizeof(df_tables) / sizeof(msi_table));
4675
4676     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4677
4678     /* fails if the destination folder is not a valid property */
4679
4680     r = MsiInstallProductA(msifile, NULL);
4681     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4682     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4683     ok(delete_pf("msitest\\augustus", TRUE), "File not duplicated\n");
4684     ok(delete_pf("msitest\\this\\doesnot\\exist\\maximus", TRUE), "File not duplicated\n");
4685     ok(delete_pf("msitest\\this\\doesnot\\exist", FALSE), "File not duplicated\n");
4686     ok(delete_pf("msitest\\this\\doesnot", FALSE), "File not duplicated\n");
4687     ok(delete_pf("msitest\\this", FALSE), "File not duplicated\n");
4688     ok(delete_pf("msitest", FALSE), "File not installed\n");
4689
4690     DeleteFile("msitest\\maximus");
4691     RemoveDirectory("msitest");
4692     DeleteFile(msifile);
4693 }
4694
4695 static void test_writeregistryvalues(void)
4696 {
4697     UINT r;
4698     LONG res;
4699     HKEY hkey;
4700     DWORD type, size;
4701     CHAR path[MAX_PATH];
4702
4703     CreateDirectoryA("msitest", NULL);
4704     create_file("msitest\\augustus", 500);
4705
4706     create_database(msifile, wrv_tables, sizeof(wrv_tables) / sizeof(msi_table));
4707
4708     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4709
4710     r = MsiInstallProductA(msifile, NULL);
4711     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4712     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4713     ok(delete_pf("msitest", FALSE), "File installed\n");
4714
4715     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
4716     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4717
4718     size = MAX_PATH;
4719     type = REG_MULTI_SZ;
4720     memset(path, 'a', MAX_PATH);
4721     res = RegQueryValueExA(hkey, "Value", NULL, &type, (LPBYTE)path, &size);
4722     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4723     ok(!memcmp(path, "one\0two\0three\0\0", size), "Wrong multi-sz data\n");
4724     ok(size == 15, "Expected 15, got %d\n", size);
4725     ok(type == REG_MULTI_SZ, "Expected REG_MULTI_SZ, got %d\n", type);
4726
4727     DeleteFile(msifile);
4728     DeleteFile("msitest\\augustus");
4729     RemoveDirectory("msitest");
4730
4731     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
4732     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine");
4733 }
4734
4735 static void test_sourcefolder(void)
4736 {
4737     UINT r;
4738
4739     CreateDirectoryA("msitest", NULL);
4740     create_file("augustus", 500);
4741
4742     create_database(msifile, sf_tables, sizeof(sf_tables) / sizeof(msi_table));
4743
4744     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4745
4746     r = MsiInstallProductA(msifile, NULL);
4747     ok(r == ERROR_INSTALL_FAILURE,
4748        "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4749     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4750     todo_wine
4751     {
4752         ok(!delete_pf("msitest", FALSE), "File installed\n");
4753     }
4754
4755     RemoveDirectoryA("msitest");
4756
4757     r = MsiInstallProductA(msifile, NULL);
4758     ok(r == ERROR_INSTALL_FAILURE,
4759        "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4760     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4761     todo_wine
4762     {
4763         ok(!delete_pf("msitest", FALSE), "File installed\n");
4764     }
4765
4766     DeleteFile(msifile);
4767     DeleteFile("augustus");
4768 }
4769
4770 static void test_customaction51(void)
4771 {
4772     UINT r;
4773
4774     CreateDirectoryA("msitest", NULL);
4775     create_file("msitest\\augustus", 500);
4776
4777     create_database(msifile, ca51_tables, sizeof(ca51_tables) / sizeof(msi_table));
4778
4779     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4780
4781     r = MsiInstallProductA(msifile, NULL);
4782     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4783     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4784     ok(delete_pf("msitest", FALSE), "File installed\n");
4785
4786     DeleteFile(msifile);
4787     DeleteFile("msitest\\augustus");
4788     RemoveDirectory("msitest");
4789 }
4790
4791 static void test_installstate(void)
4792 {
4793     UINT r;
4794
4795     CreateDirectoryA("msitest", NULL);
4796     create_file("msitest\\alpha", 500);
4797     create_file("msitest\\beta", 500);
4798     create_file("msitest\\gamma", 500);
4799     create_file("msitest\\theta", 500);
4800     create_file("msitest\\delta", 500);
4801     create_file("msitest\\epsilon", 500);
4802     create_file("msitest\\zeta", 500);
4803     create_file("msitest\\iota", 500);
4804     create_file("msitest\\eta", 500);
4805     create_file("msitest\\kappa", 500);
4806     create_file("msitest\\lambda", 500);
4807     create_file("msitest\\mu", 500);
4808
4809     create_database(msifile, is_tables, sizeof(is_tables) / sizeof(msi_table));
4810
4811     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4812
4813     r = MsiInstallProductA(msifile, NULL);
4814     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4815     ok(delete_pf("msitest\\alpha", TRUE), "File not installed\n");
4816     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4817     ok(delete_pf("msitest\\gamma", TRUE), "File not installed\n");
4818     ok(delete_pf("msitest\\theta", TRUE), "File not installed\n");
4819     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4820     ok(!delete_pf("msitest\\epsilon", TRUE), "File installed\n");
4821     ok(!delete_pf("msitest\\zeta", TRUE), "File installed\n");
4822     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4823     ok(!delete_pf("msitest\\eta", TRUE), "File installed\n");
4824     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4825     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4826     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4827     ok(delete_pf("msitest", FALSE), "File not installed\n");
4828
4829     r = MsiInstallProductA(msifile, "ADDLOCAL=\"one,two,three,four\"");
4830     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4831     ok(delete_pf("msitest\\alpha", TRUE), "File not installed\n");
4832     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4833     ok(delete_pf("msitest\\gamma", TRUE), "File not installed\n");
4834     ok(delete_pf("msitest\\theta", TRUE), "File not installed\n");
4835     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4836     ok(delete_pf("msitest\\epsilon", TRUE), "File not installed\n");
4837     ok(delete_pf("msitest\\zeta", TRUE), "File not installed\n");
4838     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4839     ok(delete_pf("msitest\\eta", TRUE), "File not installed\n");
4840     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4841     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4842     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4843     ok(delete_pf("msitest", FALSE), "File not installed\n");
4844
4845     r = MsiInstallProductA(msifile, "ADDSOURCE=\"one,two,three,four\"");
4846     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4847     ok(delete_pf("msitest\\alpha", TRUE), "File not installed\n");
4848     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4849     ok(!delete_pf("msitest\\gamma", TRUE), "File installed\n");
4850     ok(delete_pf("msitest\\theta", TRUE), "File not installed\n");
4851     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4852     ok(!delete_pf("msitest\\epsilon", TRUE), "File installed\n");
4853     ok(delete_pf("msitest\\zeta", TRUE), "File not installed\n");
4854     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4855     ok(!delete_pf("msitest\\eta", TRUE), "File installed\n");
4856     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4857     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4858     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4859     ok(delete_pf("msitest", FALSE), "File not installed\n");
4860
4861     r = MsiInstallProductA(msifile, "REMOVE=\"one,two,three,four\"");
4862     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4863     ok(!delete_pf("msitest\\alpha", TRUE), "File installed\n");
4864     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4865     ok(!delete_pf("msitest\\gamma", TRUE), "File installed\n");
4866     ok(!delete_pf("msitest\\theta", TRUE), "File installed\n");
4867     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4868     ok(!delete_pf("msitest\\epsilon", TRUE), "File installed\n");
4869     ok(!delete_pf("msitest\\zeta", TRUE), "File installed\n");
4870     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4871     ok(!delete_pf("msitest\\eta", TRUE), "File installed\n");
4872     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4873     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4874     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4875     ok(!delete_pf("msitest", FALSE), "File installed\n");
4876
4877     DeleteFile(msifile);
4878     DeleteFile("msitest\\alpha");
4879     DeleteFile("msitest\\beta");
4880     DeleteFile("msitest\\gamma");
4881     DeleteFile("msitest\\theta");
4882     DeleteFile("msitest\\delta");
4883     DeleteFile("msitest\\epsilon");
4884     DeleteFile("msitest\\zeta");
4885     DeleteFile("msitest\\iota");
4886     DeleteFile("msitest\\eta");
4887     DeleteFile("msitest\\kappa");
4888     DeleteFile("msitest\\lambda");
4889     DeleteFile("msitest\\mu");
4890     RemoveDirectory("msitest");
4891 }
4892
4893 struct sourcepathmap
4894 {
4895     BOOL sost; /* shortone\shorttwo */
4896     BOOL solt; /* shortone\longtwo */
4897     BOOL lost; /* longone\shorttwo */
4898     BOOL lolt; /* longone\longtwo */
4899     BOOL soste; /* shortone\shorttwo source exists */
4900     BOOL solte; /* shortone\longtwo source exists */
4901     BOOL loste; /* longone\shorttwo source exists */
4902     BOOL lolte; /* longone\longtwo source exists */
4903     UINT err;
4904     DWORD size;
4905 } spmap[256] =
4906 {
4907     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4908     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4909     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4910     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4911     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4912     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4913     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4914     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4915     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4916     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4917     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4918     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4919     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4920     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4921     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4922     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4923     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4924     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4925     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4926     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4927     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4928     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4929     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4930     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4931     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4932     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4933     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4934     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4935     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4936     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4937     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4938     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4939     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4940     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4941     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4942     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4943     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4944     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4945     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4946     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4947     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4948     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4949     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4950     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4951     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4952     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4953     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4954     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4955     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4956     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4957     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4958     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4959     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4960     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4961     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4962     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4963     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4964     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4965     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4966     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4967     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4968     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4969     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4970     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4971     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4972     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4973     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4974     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4975     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4976     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4977     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4978     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4979     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4980     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4981     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4982     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4983     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4984     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4985     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4986     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4987     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4988     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4989     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4990     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4991     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4992     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4993     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4994     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4995     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4996     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4997     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4998     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4999     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5000     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5001     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5002     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5003     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5004     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5005     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5006     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5007     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5008     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5009     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5010     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5011     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5012     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5013     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5014     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5015     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5016     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5017     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5018     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5019     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5020     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5021     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5022     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5023     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5024     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5025     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5026     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5027     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5028     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5029     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5030     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5031     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5032     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5033     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5034     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5035     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5036     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5037     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5038     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5039     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5040     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5041     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5042     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5043     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5044     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5045     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5046     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5047     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5048     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5049     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5050     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5051     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5052     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5053     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5054     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5055     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5056     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5057     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5058     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5059     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5060     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5061     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5062     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5063     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5064     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5065     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5066     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5067     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5068     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5069     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5070     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5071     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5072     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5073     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5074     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5075     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5076     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5077     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5078     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5079     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5080     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5081     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5082     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5083     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5084     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5085     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5086     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5087     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5088     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5089     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5090     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5091     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5092     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5093     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5094     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5095     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5096     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5097     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5098     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5099     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5100     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5101     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5102     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5103     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5104     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5105     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5106     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5107     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5108     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5109     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5110     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5111     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5112     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5113     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5114     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5115     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5116     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5117     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5118     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5119     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5120     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5121     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5122     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5123     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5124     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5125     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5126     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5127     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5128     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5129     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5130     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5131     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5132     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5133     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5134     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5135     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5136     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5137     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5138     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5139     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5140     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5141     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5142     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5143     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5144     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5145     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5146     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5147     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5148     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5149     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5150     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5151     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5152     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5153     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5154     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5155     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5156     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5157     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5158     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5159     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5160     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5161     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5162     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5163 };
5164
5165 static DWORD get_pf_file_size(LPCSTR file)
5166 {
5167     CHAR path[MAX_PATH];
5168     HANDLE hfile;
5169     DWORD size;
5170
5171     lstrcpyA(path, PROG_FILES_DIR);
5172     lstrcatA(path, "\\");
5173     lstrcatA(path, file);
5174
5175     hfile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
5176     if (hfile == INVALID_HANDLE_VALUE)
5177         return 0;
5178
5179     size = GetFileSize(hfile, NULL);
5180     CloseHandle(hfile);
5181     return size;
5182 }
5183
5184 static void test_sourcepath(void)
5185 {
5186     UINT r, i;
5187
5188     if (!winetest_interactive)
5189     {
5190         skip("Run in interactive mode to run source path tests.\n");
5191         return;
5192     }
5193
5194     create_database(msifile, sp_tables, sizeof(sp_tables) / sizeof(msi_table));
5195
5196     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5197
5198     for (i = 0; i < sizeof(spmap) / sizeof(spmap[0]); i++)
5199     {
5200         if (spmap[i].sost)
5201         {
5202             CreateDirectoryA("shortone", NULL);
5203             CreateDirectoryA("shortone\\shorttwo", NULL);
5204         }
5205
5206         if (spmap[i].solt)
5207         {
5208             CreateDirectoryA("shortone", NULL);
5209             CreateDirectoryA("shortone\\longtwo", NULL);
5210         }
5211
5212         if (spmap[i].lost)
5213         {
5214             CreateDirectoryA("longone", NULL);
5215             CreateDirectoryA("longone\\shorttwo", NULL);
5216         }
5217
5218         if (spmap[i].lolt)
5219         {
5220             CreateDirectoryA("longone", NULL);
5221             CreateDirectoryA("longone\\longtwo", NULL);
5222         }
5223
5224         if (spmap[i].soste)
5225             create_file("shortone\\shorttwo\\augustus", 50);
5226         if (spmap[i].solte)
5227             create_file("shortone\\longtwo\\augustus", 100);
5228         if (spmap[i].loste)
5229             create_file("longone\\shorttwo\\augustus", 150);
5230         if (spmap[i].lolte)
5231             create_file("longone\\longtwo\\augustus", 200);
5232
5233         r = MsiInstallProductA(msifile, NULL);
5234         ok(r == spmap[i].err, "%d: Expected %d, got %d\n", i, spmap[i].err, r);
5235         ok(get_pf_file_size("msitest\\augustus") == spmap[i].size,
5236            "%d: Expected %d, got %d\n", i, spmap[i].size,
5237            get_pf_file_size("msitest\\augustus"));
5238
5239         if (r == ERROR_SUCCESS)
5240         {
5241             ok(delete_pf("msitest\\augustus", TRUE), "%d: File not installed\n", i);
5242             ok(delete_pf("msitest", FALSE), "%d: File not installed\n", i);
5243         }
5244         else
5245         {
5246             ok(!delete_pf("msitest\\augustus", TRUE), "%d: File installed\n", i);
5247             todo_wine ok(!delete_pf("msitest", FALSE), "%d: File installed\n", i);
5248         }
5249
5250         DeleteFileA("shortone\\shorttwo\\augustus");
5251         DeleteFileA("shortone\\longtwo\\augustus");
5252         DeleteFileA("longone\\shorttwo\\augustus");
5253         DeleteFileA("longone\\longtwo\\augustus");
5254         RemoveDirectoryA("shortone\\shorttwo");
5255         RemoveDirectoryA("shortone\\longtwo");
5256         RemoveDirectoryA("longone\\shorttwo");
5257         RemoveDirectoryA("longone\\longtwo");
5258         RemoveDirectoryA("shortone");
5259         RemoveDirectoryA("longone");
5260     }
5261
5262     DeleteFileA(msifile);
5263 }
5264
5265 static void test_MsiConfigureProductEx(void)
5266 {
5267     UINT r;
5268     LONG res;
5269     DWORD type, size;
5270     HKEY props, source;
5271     CHAR keypath[MAX_PATH * 2];
5272     CHAR localpack[MAX_PATH];
5273
5274     if (on_win9x)
5275     {
5276         win_skip("Different registry keys on Win9x and WinMe\n");
5277         return;
5278     }
5279
5280     CreateDirectoryA("msitest", NULL);
5281     create_file("msitest\\hydrogen", 500);
5282     create_file("msitest\\helium", 500);
5283     create_file("msitest\\lithium", 500);
5284
5285     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
5286
5287     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5288
5289     /* NULL szProduct */
5290     r = MsiConfigureProductExA(NULL, INSTALLLEVEL_DEFAULT,
5291                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
5292     ok(r == ERROR_INVALID_PARAMETER,
5293        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5294
5295     /* empty szProduct */
5296     r = MsiConfigureProductExA("", INSTALLLEVEL_DEFAULT,
5297                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
5298     ok(r == ERROR_INVALID_PARAMETER,
5299        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5300
5301     /* garbage szProduct */
5302     r = MsiConfigureProductExA("garbage", INSTALLLEVEL_DEFAULT,
5303                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
5304     ok(r == ERROR_INVALID_PARAMETER,
5305        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5306
5307     /* guid without brackets */
5308     r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
5309                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5310                                "PROPVAR=42");
5311     ok(r == ERROR_INVALID_PARAMETER,
5312        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5313
5314     /* guid with brackets */
5315     r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
5316                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5317                                "PROPVAR=42");
5318     ok(r == ERROR_UNKNOWN_PRODUCT,
5319        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5320
5321     /* same length as guid, but random */
5322     r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
5323                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5324                                "PROPVAR=42");
5325     ok(r == ERROR_UNKNOWN_PRODUCT,
5326        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5327
5328     /* product not installed yet */
5329     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5330                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5331                                "PROPVAR=42");
5332     ok(r == ERROR_UNKNOWN_PRODUCT,
5333        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5334
5335     /* install the product, per-user unmanaged */
5336     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
5337     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5338     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5339     ok(pf_exists("msitest\\helium"), "File not installed\n");
5340     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5341     ok(pf_exists("msitest"), "File not installed\n");
5342
5343     /* product is installed per-user managed, remove it */
5344     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5345                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5346                                "PROPVAR=42");
5347     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5348     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5349     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5350     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5351     todo_wine
5352     {
5353         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5354     }
5355
5356     /* product has been removed */
5357     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5358                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5359                                "PROPVAR=42");
5360     ok(r == ERROR_UNKNOWN_PRODUCT,
5361        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
5362
5363     /* install the product, machine */
5364     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
5365     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5366     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5367     ok(pf_exists("msitest\\helium"), "File not installed\n");
5368     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5369     ok(pf_exists("msitest"), "File not installed\n");
5370
5371     /* product is installed machine, remove it */
5372     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5373                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5374                                "PROPVAR=42");
5375     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5376     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5377     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5378     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5379     todo_wine
5380     {
5381         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5382     }
5383
5384     /* product has been removed */
5385     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5386                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5387                                "PROPVAR=42");
5388     ok(r == ERROR_UNKNOWN_PRODUCT,
5389        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
5390
5391     /* install the product, machine */
5392     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
5393     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5394     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5395     ok(pf_exists("msitest\\helium"), "File not installed\n");
5396     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5397     ok(pf_exists("msitest"), "File not installed\n");
5398
5399     DeleteFileA(msifile);
5400
5401     /* local msifile is removed */
5402     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5403                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5404                                "PROPVAR=42");
5405     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5406     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5407     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5408     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5409     todo_wine
5410     {
5411         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5412     }
5413
5414     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
5415
5416     /* install the product, machine */
5417     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
5418     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5419     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5420     ok(pf_exists("msitest\\helium"), "File not installed\n");
5421     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5422     ok(pf_exists("msitest"), "File not installed\n");
5423
5424     DeleteFileA(msifile);
5425
5426     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
5427     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
5428     lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties");
5429
5430     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
5431     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5432
5433     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
5434                          (const BYTE *)"C:\\idontexist.msi", 18);
5435     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5436
5437     /* LocalPackage is used to find the cached msi package */
5438     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5439                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5440                                "PROPVAR=42");
5441     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
5442        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
5443     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5444     ok(pf_exists("msitest\\helium"), "File not installed\n");
5445     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5446     ok(pf_exists("msitest"), "File not installed\n");
5447
5448     RegCloseKey(props);
5449     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
5450
5451     /* LastUsedSource (local msi package) can be used as a last resort */
5452     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5453                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5454                                "PROPVAR=42");
5455     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5456     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5457     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5458     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5459     todo_wine
5460     {
5461         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5462     }
5463
5464     /* install the product, machine */
5465     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
5466     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5467     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5468     ok(pf_exists("msitest\\helium"), "File not installed\n");
5469     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5470     ok(pf_exists("msitest"), "File not installed\n");
5471
5472     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
5473     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
5474     lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties");
5475
5476     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
5477     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5478
5479     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
5480                          (const BYTE *)"C:\\idontexist.msi", 18);
5481     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5482
5483     lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\");
5484     lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\SourceList");
5485
5486     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &source);
5487     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5488
5489     type = REG_SZ;
5490     size = MAX_PATH;
5491     res = RegQueryValueExA(source, "PackageName", NULL, &type,
5492                            (LPBYTE)localpack, &size);
5493     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5494
5495     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
5496                          (const BYTE *)"idontexist.msi", 15);
5497     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5498
5499     /* SourceList is altered */
5500     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5501                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5502                                "PROPVAR=42");
5503     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
5504        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
5505     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5506     ok(pf_exists("msitest\\helium"), "File not installed\n");
5507     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5508     ok(pf_exists("msitest"), "File not installed\n");
5509
5510     /* restore the SourceList */
5511     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
5512                          (const BYTE *)localpack, lstrlenA(localpack) + 1);
5513     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5514
5515     /* finally remove the product */
5516     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5517                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5518                                "PROPVAR=42");
5519     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5520     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5521     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5522     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5523     todo_wine
5524     {
5525         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5526     }
5527
5528     DeleteFileA(msifile);
5529     RegCloseKey(source);
5530     RegCloseKey(props);
5531     DeleteFileA("msitest\\hydrogen");
5532     DeleteFileA("msitest\\helium");
5533     DeleteFileA("msitest\\lithium");
5534     RemoveDirectoryA("msitest");
5535 }
5536
5537 static void test_missingcomponent(void)
5538 {
5539     UINT r;
5540
5541     CreateDirectoryA("msitest", NULL);
5542     create_file("msitest\\hydrogen", 500);
5543     create_file("msitest\\helium", 500);
5544     create_file("msitest\\lithium", 500);
5545     create_file("beryllium", 500);
5546
5547     create_database(msifile, mcomp_tables, sizeof(mcomp_tables) / sizeof(msi_table));
5548
5549     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5550
5551     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
5552     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5553     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5554     ok(pf_exists("msitest\\helium"), "File not installed\n");
5555     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5556     ok(!pf_exists("msitest\\beryllium"), "File installed\n");
5557     ok(pf_exists("msitest"), "File not installed\n");
5558
5559     r = MsiInstallProductA(msifile, "REMOVE=ALL INSTALLLEVEL=10 PROPVAR=42");
5560     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5561     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5562     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5563     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5564     ok(!pf_exists("msitest\\beryllium"), "File installed\n");
5565     todo_wine
5566     {
5567         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5568     }
5569
5570     DeleteFileA(msifile);
5571     DeleteFileA("msitest\\hydrogen");
5572     DeleteFileA("msitest\\helium");
5573     DeleteFileA("msitest\\lithium");
5574     DeleteFileA("beryllium");
5575     RemoveDirectoryA("msitest");
5576 }
5577
5578 static void test_sourcedirprop(void)
5579 {
5580     UINT r;
5581     CHAR props[MAX_PATH];
5582
5583     CreateDirectoryA("msitest", NULL);
5584     create_file("msitest\\augustus", 500);
5585
5586     create_database(msifile, ca51_tables, sizeof(ca51_tables) / sizeof(msi_table));
5587
5588     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5589
5590     r = MsiInstallProductA(msifile, NULL);
5591     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5592     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
5593     ok(delete_pf("msitest", FALSE), "File installed\n");
5594
5595     DeleteFile("msitest\\augustus");
5596     RemoveDirectory("msitest");
5597
5598     CreateDirectoryA("altsource", NULL);
5599     CreateDirectoryA("altsource\\msitest", NULL);
5600     create_file("altsource\\msitest\\augustus", 500);
5601
5602     sprintf(props, "SRCDIR=%s\\altsource\\", CURR_DIR);
5603
5604     r = MsiInstallProductA(msifile, props);
5605     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5606     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
5607     ok(delete_pf("msitest", FALSE), "File installed\n");
5608
5609     DeleteFile(msifile);
5610     DeleteFile("altsource\\msitest\\augustus");
5611     RemoveDirectory("altsource\\msitest");
5612     RemoveDirectory("altsource");
5613 }
5614
5615 static void test_adminimage(void)
5616 {
5617     UINT r;
5618
5619     CreateDirectoryA("msitest", NULL);
5620     CreateDirectoryA("msitest\\first", NULL);
5621     CreateDirectoryA("msitest\\second", NULL);
5622     CreateDirectoryA("msitest\\cabout", NULL);
5623     CreateDirectoryA("msitest\\cabout\\new", NULL);
5624     create_file("msitest\\one.txt", 100);
5625     create_file("msitest\\first\\two.txt", 100);
5626     create_file("msitest\\second\\three.txt", 100);
5627     create_file("msitest\\cabout\\four.txt", 100);
5628     create_file("msitest\\cabout\\new\\five.txt", 100);
5629     create_file("msitest\\filename", 100);
5630     create_file("msitest\\service.exe", 100);
5631
5632     create_database_wordcount(msifile, ai_tables,
5633                               sizeof(ai_tables) / sizeof(msi_table),
5634                               msidbSumInfoSourceTypeAdminImage);
5635
5636     r = MsiInstallProductA(msifile, NULL);
5637     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5638
5639     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
5640     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
5641     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
5642     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
5643     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
5644     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
5645     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
5646     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
5647     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
5648     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
5649     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
5650     ok(delete_pf("msitest", FALSE), "File not installed\n");
5651
5652     DeleteFileA("msitest.msi");
5653     DeleteFileA("msitest\\cabout\\new\\five.txt");
5654     DeleteFileA("msitest\\cabout\\four.txt");
5655     DeleteFileA("msitest\\second\\three.txt");
5656     DeleteFileA("msitest\\first\\two.txt");
5657     DeleteFileA("msitest\\one.txt");
5658     DeleteFileA("msitest\\service.exe");
5659     DeleteFileA("msitest\\filename");
5660     RemoveDirectoryA("msitest\\cabout\\new");
5661     RemoveDirectoryA("msitest\\cabout");
5662     RemoveDirectoryA("msitest\\second");
5663     RemoveDirectoryA("msitest\\first");
5664     RemoveDirectoryA("msitest");
5665 }
5666
5667 static void test_propcase(void)
5668 {
5669     UINT r;
5670
5671     CreateDirectoryA("msitest", NULL);
5672     create_file("msitest\\augustus", 500);
5673
5674     create_database(msifile, pc_tables, sizeof(pc_tables) / sizeof(msi_table));
5675
5676     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5677
5678     r = MsiInstallProductA(msifile, "MyProp=42");
5679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5680     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
5681     ok(delete_pf("msitest", FALSE), "File not installed\n");
5682
5683     DeleteFile(msifile);
5684     DeleteFile("msitest\\augustus");
5685     RemoveDirectory("msitest");
5686 }
5687
5688 START_TEST(install)
5689 {
5690     DWORD len;
5691     char temp_path[MAX_PATH], prev_path[MAX_PATH];
5692     STATEMGRSTATUS status;
5693     BOOL ret = FALSE;
5694
5695     init_functionpointers();
5696
5697     on_win9x = check_win9x();
5698
5699     GetCurrentDirectoryA(MAX_PATH, prev_path);
5700     GetTempPath(MAX_PATH, temp_path);
5701     SetCurrentDirectoryA(temp_path);
5702
5703     lstrcpyA(CURR_DIR, temp_path);
5704     len = lstrlenA(CURR_DIR);
5705
5706     if(len && (CURR_DIR[len - 1] == '\\'))
5707         CURR_DIR[len - 1] = 0;
5708
5709     get_program_files_dir(PROG_FILES_DIR, COMMON_FILES_DIR);
5710
5711     /* Create a restore point ourselves so we circumvent the multitude of restore points
5712      * that would have been created by all the installation and removal tests.
5713      */
5714     if (pSRSetRestorePointA)
5715     {
5716         memset(&status, 0, sizeof(status));
5717         ret = notify_system_change(BEGIN_NESTED_SYSTEM_CHANGE, &status);
5718     }
5719
5720     /* Create only one log file and don't append. We have to pass something
5721      * for the log mode for this to work.
5722      */
5723     MsiEnableLogA(INSTALLLOGMODE_FATALEXIT, "msitest.log", 0);
5724
5725     test_MsiInstallProduct();
5726     test_MsiSetComponentState();
5727     test_packagecoltypes();
5728     test_continuouscabs();
5729     test_caborder();
5730     test_mixedmedia();
5731     test_samesequence();
5732     test_uiLevelFlags();
5733     test_readonlyfile();
5734     test_setdirproperty();
5735     test_cabisextracted();
5736     test_concurrentinstall();
5737     test_setpropertyfolder();
5738     test_publish_registerproduct();
5739     test_publish_publishproduct();
5740     test_publish_publishfeatures();
5741     test_publish_registeruser();
5742     test_publish_processcomponents();
5743     test_publish();
5744     test_publishsourcelist();
5745     test_transformprop();
5746     test_currentworkingdir();
5747     test_admin();
5748     test_adminprops();
5749     test_removefiles();
5750     test_movefiles();
5751     test_missingcab();
5752     test_duplicatefiles();
5753     test_writeregistryvalues();
5754     test_sourcefolder();
5755     test_customaction51();
5756     test_installstate();
5757     test_sourcepath();
5758     test_MsiConfigureProductEx();
5759     test_missingcomponent();
5760     test_sourcedirprop();
5761     test_adminimage();
5762     test_propcase();
5763
5764     DeleteFileA("msitest.log");
5765
5766     if (pSRSetRestorePointA && ret)
5767     {
5768         ret = notify_system_change(END_NESTED_SYSTEM_CHANGE, &status);
5769         if (ret)
5770             remove_restore_point(status.llSequenceNumber);
5771     }
5772     FreeLibrary(hsrclient);
5773
5774     SetCurrentDirectoryA(prev_path);
5775 }