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