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