1 /* 2 * Copyright (C) 2005 Mike McCormack for CodeWeavers 3 * 4 * A test program for MSI database files. 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 COBJMACROS 22 23 #include <stdio.h> 24 #include <windows.h> 25 #include <msi.h> 26 #include <msiquery.h> 27 #include <objidl.h> 28 29 #include "wine/test.h" 30 31 /* 32 * The following are defined in Windows SDK's msidefs.h 33 * but that file doesn't exist in the msvc6 header set. 34 * 35 * Some are already defined in PropIdl.h - undefine them 36 */ 37 #undef PID_DICTIONARY 38 #undef PID_CODEPAGE 39 #undef PID_SUBJECT 40 #undef PID_SECURITY 41 42 #define PID_DICTIONARY 0 43 #define PID_CODEPAGE 1 44 #define PID_TITLE 2 45 #define PID_SUBJECT 3 46 #define PID_AUTHOR 4 47 #define PID_KEYWORDS 5 48 #define PID_COMMENTS 6 49 #define PID_TEMPLATE 7 50 #define PID_LASTAUTHOR 8 51 #define PID_REVNUMBER 9 52 #define PID_EDITTINE 10 53 #define PID_LASTPRINTED 11 54 #define PID_CREATE_DTM 12 55 #define PID_LASTSAVE_DTM 13 56 #define PID_PAGECOUNT 14 57 #define PID_WORDCOUNT 15 58 #define PID_CHARCOUNT 16 59 #define PID_THUMBNAIL 17 60 #define PID_APPNAME 18 61 #define PID_SECURITY 19 62 #define PID_MSIVERSION PID_PAGECOUNT 63 #define PID_MSISOURCE PID_WORDCOUNT 64 #define PID_MSIRESTRICT PID_CHARCOUNT 65 66 static const char *msifile = "winetest-suminfo.msi"; 67 static const WCHAR msifileW[] = L"winetest-suminfo.msi"; 68 69 static void test_suminfo(void) 70 { 71 MSIHANDLE hdb = 0, hsuminfo; 72 UINT r, count, type; 73 DWORD sz; 74 INT val; 75 FILETIME ft; 76 char buf[0x10]; 77 78 DeleteFileA(msifile); 79 80 /* just MsiOpenDatabase should not create a file */ 81 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 82 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 83 84 r = MsiGetSummaryInformationA(hdb, NULL, 0, NULL); 85 ok(r == ERROR_INVALID_PARAMETER, "MsiGetSummaryInformation wrong error\n"); 86 87 r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsuminfo); 88 ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation failed %u\n", r); 89 90 r = MsiCloseHandle(hsuminfo); 91 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 92 93 r = MsiGetSummaryInformationA(0, "", 0, &hsuminfo); 94 todo_wine 95 ok(r == ERROR_INSTALL_PACKAGE_INVALID || r == ERROR_INSTALL_PACKAGE_OPEN_FAILED, 96 "MsiGetSummaryInformation failed %u\n", r); 97 98 r = MsiGetSummaryInformationA(hdb, "", 0, &hsuminfo); 99 ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation failed %u\n", r); 100 101 r = MsiSummaryInfoGetPropertyCount(0, NULL); 102 ok(r == ERROR_INVALID_HANDLE, "getpropcount failed\n"); 103 104 r = MsiSummaryInfoGetPropertyCount(hsuminfo, NULL); 105 ok(r == ERROR_SUCCESS, "getpropcount failed\n"); 106 107 count = -1; 108 r = MsiSummaryInfoGetPropertyCount(hsuminfo, &count); 109 ok(r == ERROR_SUCCESS, "getpropcount failed\n"); 110 ok(count == 0, "count should be zero\n"); 111 112 r = MsiSummaryInfoGetPropertyA(hsuminfo, 0, NULL, NULL, NULL, 0, NULL); 113 ok(r == ERROR_SUCCESS, "getpropcount failed\n"); 114 115 r = MsiSummaryInfoGetPropertyA(hsuminfo, -1, NULL, NULL, NULL, 0, NULL); 116 ok(r == ERROR_UNKNOWN_PROPERTY, "MsiSummaryInfoGetProperty wrong error\n"); 117 118 r = MsiSummaryInfoGetPropertyA(hsuminfo, PID_SECURITY+1, NULL, NULL, NULL, 0, NULL); 119 ok(r == ERROR_UNKNOWN_PROPERTY, "MsiSummaryInfoGetProperty wrong error\n"); 120 121 type = -1; 122 r = MsiSummaryInfoGetPropertyA(hsuminfo, 0, &type, NULL, NULL, 0, NULL); 123 ok(r == ERROR_SUCCESS, "getpropcount failed\n"); 124 ok(type == 0, "wrong type\n"); 125 126 type = -1; 127 val = 1234; 128 r = MsiSummaryInfoGetPropertyA(hsuminfo, 0, &type, &val, NULL, 0, NULL); 129 ok(r == ERROR_SUCCESS, "getpropcount failed\n"); 130 ok(type == 0, "wrong type\n"); 131 ok(val == 1234, "wrong val\n"); 132 133 buf[0]='x'; 134 buf[1]=0; 135 sz = 0x10; 136 r = MsiSummaryInfoGetPropertyA(hsuminfo, PID_REVNUMBER, &type, &val, NULL, buf, &sz); 137 ok(r == ERROR_SUCCESS, "getpropcount failed\n"); 138 ok(buf[0]=='x', "cleared buffer\n"); 139 ok(sz == 0x10, "count wasn't zero\n"); 140 ok(type == VT_EMPTY, "should be empty\n"); 141 142 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_TITLE, VT_LPSTR, 0, NULL, "Mike"); 143 ok(r == ERROR_FUNCTION_FAILED, "MsiSummaryInfoSetProperty wrong error\n"); 144 145 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_TITLE, VT_LPSTR, 1, NULL, "JungAh"); 146 ok(r == ERROR_FUNCTION_FAILED, "MsiSummaryInfoSetProperty wrong error\n"); 147 148 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_TITLE, VT_LPSTR, 1, &ft, "Mike"); 149 ok(r == ERROR_FUNCTION_FAILED, "MsiSummaryInfoSetProperty wrong error\n"); 150 151 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_CODEPAGE, VT_I2, 1, &ft, "JungAh"); 152 ok(r == ERROR_FUNCTION_FAILED, "MsiSummaryInfoSetProperty wrong error\n"); 153 154 r = MsiCloseHandle(hsuminfo); 155 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 156 157 /* try again with the update count set */ 158 r = MsiGetSummaryInformationA(hdb, NULL, 1, &hsuminfo); 159 ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation failed\n"); 160 161 r = MsiSummaryInfoSetPropertyA(hsuminfo, 0, VT_LPSTR, 1, NULL, NULL); 162 ok(r == ERROR_DATATYPE_MISMATCH, "MsiSummaryInfoSetProperty wrong error\n"); 163 164 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_CODEPAGE, VT_LPSTR, 1, NULL, NULL); 165 ok(r == ERROR_DATATYPE_MISMATCH, "MsiSummaryInfoSetProperty wrong error\n"); 166 167 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_TITLE, VT_I4, 0, NULL, "Mike"); 168 ok(r == ERROR_DATATYPE_MISMATCH, "MsiSummaryInfoSetProperty wrong error\n"); 169 170 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_AUTHOR, VT_I4, 0, NULL, "JungAh"); 171 ok(r == ERROR_DATATYPE_MISMATCH, "MsiSummaryInfoSetProperty wrong error\n"); 172 173 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_KEYWORDS, VT_I2, 0, NULL, "Mike"); 174 ok(r == ERROR_DATATYPE_MISMATCH, "MsiSummaryInfoSetProperty wrong error\n"); 175 176 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_COMMENTS, VT_FILETIME, 0, NULL, "JungAh"); 177 ok(r == ERROR_DATATYPE_MISMATCH, "MsiSummaryInfoSetProperty wrong error\n"); 178 179 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_TEMPLATE, VT_I2, 0, NULL, "Mike"); 180 ok(r == ERROR_DATATYPE_MISMATCH, "MsiSummaryInfoSetProperty wrong error\n"); 181 182 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_LASTAUTHOR, VT_LPSTR, 0, NULL, NULL); 183 ok(r == ERROR_INVALID_PARAMETER, "MsiSummaryInfoSetProperty wrong error\n"); 184 185 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_LASTSAVE_DTM, VT_FILETIME, 0, NULL, NULL); 186 ok(r == ERROR_INVALID_PARAMETER, "MsiSummaryInfoSetProperty wrong error\n"); 187 188 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_LASTAUTHOR, VT_LPWSTR, 0, NULL, "h\0i\0\0"); 189 ok(r == ERROR_DATATYPE_MISMATCH, "MsiSummaryInfoSetProperty wrong error\n"); 190 191 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_REVNUMBER, VT_I4, 0, NULL, "Jungah"); 192 ok(r == ERROR_DATATYPE_MISMATCH, "MsiSummaryInfoSetProperty wrong error\n"); 193 194 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_PAGECOUNT, VT_LPSTR, 1, NULL, NULL); 195 ok(r == ERROR_DATATYPE_MISMATCH, "MsiSummaryInfoSetProperty wrong error\n"); 196 197 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_TITLE, VT_LPSTR, 0, NULL, "Mike"); 198 ok(r == ERROR_SUCCESS, "MsiSummaryInfoSetProperty failed\n"); 199 200 sz = 2; 201 strcpy(buf,"x"); 202 r = MsiSummaryInfoGetPropertyA(hsuminfo, PID_TITLE, &type, NULL, NULL, buf, &sz ); 203 ok(r == ERROR_MORE_DATA, "MsiSummaryInfoSetProperty failed\n"); 204 ok(sz == 4, "count was wrong\n"); 205 ok(type == VT_LPSTR, "type was wrong\n"); 206 ok(!strcmp(buf,"M"), "buffer was wrong\n"); 207 208 sz = 4; 209 strcpy(buf,"x"); 210 r = MsiSummaryInfoGetPropertyA(hsuminfo, PID_TITLE, &type, NULL, NULL, buf, &sz ); 211 ok(r == ERROR_MORE_DATA, "MsiSummaryInfoSetProperty failed\n"); 212 ok(sz == 4, "count was wrong\n"); 213 ok(type == VT_LPSTR, "type was wrong\n"); 214 ok(!strcmp(buf,"Mik"), "buffer was wrong\n"); 215 216 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_TITLE, VT_LPSTR, 0, NULL, "JungAh"); 217 ok(r == ERROR_SUCCESS, "MsiSummaryInfoSetProperty failed\n"); 218 219 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_CODEPAGE, VT_I2, 1, &ft, "Mike"); 220 ok(r == ERROR_FUNCTION_FAILED, "MsiSummaryInfoSetProperty wrong error\n"); 221 222 r = MsiCloseHandle(hsuminfo); 223 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 224 225 /* try again with a higher update count */ 226 r = MsiGetSummaryInformationA(hdb, NULL, 10, &hsuminfo); 227 ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation failed\n"); 228 229 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_TITLE, VT_LPSTR, 0, NULL, "JungAh"); 230 ok(r == ERROR_SUCCESS, "MsiSummaryInfoSetProperty failed\n"); 231 232 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_CODEPAGE, VT_LPSTR, 1, NULL, NULL); 233 ok(r == ERROR_DATATYPE_MISMATCH, "MsiSummaryInfoSetProperty wrong error\n"); 234 235 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_CODEPAGE, VT_I2, 1, NULL, NULL); 236 ok(r == ERROR_SUCCESS, "MsiSummaryInfoSetProperty wrong error\n"); 237 238 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_CODEPAGE, VT_I2, 1, &ft, "Mike"); 239 ok(r == ERROR_SUCCESS, "MsiSummaryInfoSetProperty wrong error\n"); 240 241 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_AUTHOR, VT_LPSTR, 1, &ft, "Mike"); 242 ok(r == ERROR_SUCCESS, "MsiSummaryInfoSetProperty wrong error\n"); 243 244 r = MsiSummaryInfoPersist(hsuminfo); 245 ok(r == ERROR_SUCCESS, "MsiSummaryInfoPersist failed\n"); 246 247 MsiDatabaseCommit(hdb); 248 249 r = MsiCloseHandle(hsuminfo); 250 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 251 252 r = MsiCloseHandle(hdb); 253 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 254 255 /* filename, non-zero update count */ 256 r = MsiGetSummaryInformationA(0, msifile, 1, &hsuminfo); 257 ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation failed\n"); 258 259 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_AUTHOR, VT_LPSTR, 1, &ft, "Mike"); 260 ok(r == ERROR_SUCCESS, "MsiSummaryInfoSetProperty wrong error\n"); 261 262 r = MsiSummaryInfoPersist(hsuminfo); 263 ok(r == ERROR_SUCCESS, "MsiSummaryInfoPersist failed %u\n", r); 264 265 r = MsiCloseHandle(hsuminfo); 266 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed %u\n", r); 267 268 /* filename, zero update count */ 269 r = MsiGetSummaryInformationA(0, msifile, 0, &hsuminfo); 270 ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation failed %u\n", r); 271 272 r = MsiSummaryInfoSetPropertyA(hsuminfo, PID_AUTHOR, VT_LPSTR, 1, &ft, "Mike"); 273 todo_wine ok(r == ERROR_FUNCTION_FAILED, "MsiSummaryInfoSetProperty wrong error, %u\n", r); 274 275 r = MsiSummaryInfoPersist(hsuminfo); 276 ok(r == ERROR_FUNCTION_FAILED, "MsiSummaryInfoPersist wrong error %u\n", r); 277 278 r = MsiCloseHandle(hsuminfo); 279 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 280 281 r = DeleteFileA(msifile); 282 ok(r, "DeleteFile failed\n"); 283 } 284 285 static const WCHAR tb[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */ 286 static const WCHAR sd[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */ 287 static const WCHAR sp[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */ 288 289 #define LOSE_CONST(x) ((LPSTR)(UINT_PTR)(x)) 290 291 static void test_create_database_binary(void) 292 { 293 static const CLSID CLSID_MsiDatabase = 294 { 0xc1084, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46 } }; 295 static const CLSID IID_IPropertySetStorage = 296 { 0x13a, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46 } }; 297 static const CLSID FMTID_SummaryInformation = 298 { 0xf29f85e0, 0x4ff9, 0x1068, {0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9}}; 299 DWORD mode = STGM_CREATE | STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE; 300 IPropertySetStorage *pss = NULL; 301 IPropertyStorage *ps = NULL; 302 IStorage *stg = NULL; 303 IStream *stm = NULL; 304 HRESULT r; 305 PROPSPEC propspec[10]; 306 PROPVARIANT propvar[10]; 307 USHORT data[2] = { 0, 0 }; 308 309 r = StgCreateDocfile( msifileW, mode, 0, &stg ); 310 ok( r == S_OK, "failed to create database\n"); 311 312 r = IStorage_SetClass( stg, &CLSID_MsiDatabase ); 313 ok( r == S_OK, "failed to set clsid\n"); 314 315 /* create the _StringData stream */ 316 r = IStorage_CreateStream( stg, sd, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm ); 317 ok( r == S_OK, "failed to create stream\n"); 318 319 IStream_Release( stm ); 320 321 /* create the _StringPool stream */ 322 r = IStorage_CreateStream( stg, sp, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm ); 323 ok( r == S_OK, "failed to create stream\n"); 324 325 r = IStream_Write( stm, data, sizeof data, NULL ); 326 ok( r == S_OK, "failed to write stream\n"); 327 328 IStream_Release( stm ); 329 330 /* create the _Tables stream */ 331 r = IStorage_CreateStream( stg, tb, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm ); 332 ok( r == S_OK, "failed to create stream\n"); 333 334 IStream_Release( stm ); 335 336 r = IStorage_QueryInterface( stg, &IID_IPropertySetStorage, (void**) &pss ); 337 ok( r == S_OK, "failed to set clsid\n"); 338 339 r = IPropertySetStorage_Create( pss, &FMTID_SummaryInformation, NULL, 0, mode, &ps ); 340 ok( r == S_OK, "failed to create property set\n"); 341 342 r = IPropertyStorage_SetClass( ps, &FMTID_SummaryInformation ); 343 ok( r == S_OK, "failed to set class\n"); 344 345 propspec[0].ulKind = PRSPEC_PROPID; 346 propspec[0].propid = PID_TITLE; 347 propvar[0].vt = VT_LPSTR; 348 propvar[0].pszVal = LOSE_CONST("test title"); 349 350 propspec[1].ulKind = PRSPEC_PROPID; 351 propspec[1].propid = PID_SUBJECT; 352 propvar[1].vt = VT_LPSTR; 353 propvar[1].pszVal = LOSE_CONST("msi suminfo / property storage test"); 354 355 propspec[2].ulKind = PRSPEC_PROPID; 356 propspec[2].propid = PID_AUTHOR; 357 propvar[2].vt = VT_LPSTR; 358 propvar[2].pszVal = LOSE_CONST("mike_m"); 359 360 propspec[3].ulKind = PRSPEC_PROPID; 361 propspec[3].propid = PID_TEMPLATE; 362 propvar[3].vt = VT_LPSTR; 363 propvar[3].pszVal = LOSE_CONST(";1033"); /* actually the string table's codepage */ 364 365 propspec[4].ulKind = PRSPEC_PROPID; 366 propspec[4].propid = PID_REVNUMBER; 367 propvar[4].vt = VT_LPSTR; 368 propvar[4].pszVal = LOSE_CONST("{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}"); 369 370 propspec[5].ulKind = PRSPEC_PROPID; 371 propspec[5].propid = PID_PAGECOUNT; 372 propvar[5].vt = VT_I4; 373 propvar[5].lVal = 100; 374 375 propspec[6].ulKind = PRSPEC_PROPID; 376 propspec[6].propid = PID_WORDCOUNT; 377 propvar[6].vt = VT_I4; 378 propvar[6].lVal = 0; 379 380 /* MSDN says that PID_LASTPRINTED should be a VT_FILETIME... */ 381 propspec[7].ulKind = PRSPEC_PROPID; 382 propspec[7].propid = PID_LASTPRINTED; 383 propvar[7].vt = VT_LPSTR; 384 propvar[7].pszVal = LOSE_CONST("7/1/1999 5:17"); 385 386 r = IPropertyStorage_WriteMultiple( ps, 8, propspec, propvar, PID_FIRST_USABLE ); 387 ok( r == S_OK, "failed to write properties\n"); 388 389 IPropertyStorage_Commit( ps, STGC_DEFAULT ); 390 391 IPropertyStorage_Release( ps ); 392 IPropertySetStorage_Release( pss ); 393 394 IStorage_Commit( stg, STGC_DEFAULT ); 395 IStorage_Release( stg ); 396 } 397 398 static void test_summary_binary(void) 399 { 400 MSIHANDLE hdb = 0, hsuminfo = 0; 401 UINT r, type, count; 402 INT ival; 403 DWORD sz; 404 char sval[20]; 405 406 DeleteFileA( msifile ); 407 408 test_create_database_binary(); 409 410 ok(GetFileAttributesA(msifile) != INVALID_FILE_ATTRIBUTES, "file doesn't exist!\n"); 411 412 /* just MsiOpenDatabase should not create a file */ 413 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb); 414 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 415 416 r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsuminfo); 417 ok(r == ERROR_SUCCESS, "MsiGetSummaryInformation failed\n"); 418 419 /* 420 * Check what reading PID_LASTPRINTED does... 421 * The string value is written to the msi file 422 * but it appears that we're not allowed to read it back again. 423 * We can still read its type though...? 424 */ 425 sz = sizeof sval; 426 sval[0] = 0; 427 type = 0; 428 r = MsiSummaryInfoGetPropertyA(hsuminfo, PID_LASTPRINTED, &type, NULL, NULL, sval, &sz); 429 ok(r == ERROR_SUCCESS, "MsiSummaryInfoGetProperty failed\n"); 430 ok(!lstrcmpA(sval, "") || !lstrcmpA(sval, "7"), 431 "Expected empty string or \"7\", got \"%s\"\n", sval); 432 todo_wine { 433 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %d\n", type); 434 ok(sz == 0 || sz == 1, "Expected 0 or 1, got %lu\n", sz); 435 } 436 437 ival = -1; 438 r = MsiSummaryInfoGetPropertyA(hsuminfo, PID_WORDCOUNT, &type, &ival, NULL, NULL, NULL); 439 ok(r == ERROR_SUCCESS, "MsiSummaryInfoGetProperty failed\n"); 440 todo_wine ok( ival == 0, "value incorrect\n"); 441 442 /* looks like msi adds some of its own values in here */ 443 count = 0; 444 r = MsiSummaryInfoGetPropertyCount( hsuminfo, &count ); 445 ok(r == ERROR_SUCCESS, "getpropcount failed\n"); 446 todo_wine ok(count == 10, "prop count incorrect\n"); 447 448 r = MsiSummaryInfoSetPropertyA( hsuminfo, PID_TITLE, VT_LPSTR, 0, NULL, "Mike" ); 449 ok(r == ERROR_FUNCTION_FAILED, "MsiSummaryInfoSetProperty failed %u\n", r); 450 451 r = MsiSummaryInfoPersist( hsuminfo ); 452 ok(r == ERROR_FUNCTION_FAILED, "MsiSummaryInfoPersist failed %u\n", r); 453 454 MsiCloseHandle( hsuminfo ); 455 MsiCloseHandle( hdb ); 456 457 DeleteFileA( msifile ); 458 } 459 460 START_TEST(suminfo) 461 { 462 test_suminfo(); 463 test_summary_binary(); 464 } 465